Below is the code I needed to get the PDIUSBD12's GoodLink(TM) indicator to come on. Naturally this code runs on the PIC16F877 of my project, which is wired up as described on in the #define
s as well as the USB page.
Below is a screenshot of HyperTerminal interacting with the system running this code. For more information on the PIC ←→ PC setup, see Tools.
This code assumes you are using either a dumb-terminal or equivalent (I was using HyperTerminal) to view the results of printf
and to satisfy getch()
statements.
This code was made for MPLAB v7.0, with the CCS add-in.
#include <16f877.h> #include <ctype.h> //-------------------------------------------------------- // Setup PIC and CCS compiler #fuses XT, PUT, NOWDT, NOPROTECT #use delay(clock = 4000000) #use rs232(baud = 9600, xmit = PIN_C6, rcv = PIN_C7) // By using C6 and C7, we will make use of the 877's hardware USART abilities #use standard_io(b) #byte port_d = 8 //-------------------------------------------------------- // Definitions #define ON 1 #define OFF 0 #define D12_A0 PIN_B6 #define D12_WR_N PIN_B2 #define D12_RD_N PIN_B1 #define D12_RESET_N PIN_B5 #define D12_SUSPEND PIN_B4 #define D12_INT_N PIN_B0 #define D12_DATA 0 #define D12_COMMAND 1 #define LED_N PIN_B7 //-------------------------------------------------------- // Global Variable Declarations //-------------------------------------------------------- // Function prototypes void D12Write(short, int); void D12Read(unsigned char, int); void D12InterruptHandler(); //-------------------------------------------------------- // Entry point void main(void){ short debug = OFF; output_low(LED_N); // Turn on the yellow LED while(debug) { printf("Hello World!\r\n"); delay_ms(1000); output_toggle(LED_N); // Yellow LED } //--------------------------------- printf("[2J"); // Clear screen (ANSI escape sequence) printf("Putting pins into known state and resetting D12\r\n"); set_tris_b(0x01); //PIN_B1 (D12's INT) is input, the rest are output. set_tris_d(0x00); //All output port_d = 0xFF; //Set bus high, useful for checking the ribbon has not come loose output_high(D12_RD_N); output_high(D12_WR_N); output_low(D12_RESET_N); // Reset PDIUSBD12 output_low(D12_A0); // Indicates bus is for data output_low(D12_SUSPEND); // (? Not sure how this is meant to work in practice) disable_interrupts(GLOBAL); // Stop interrupts from interrupting us while we setup ;) ext_int_edge(H_TO_L); // Set up when to trigger enable_interrupts(INT_EXT); // Enable external interrupts (connected to the D12's INT_N) clear_interrupt(INT_EXT); // Remove pending interrupts enable_interrupts(GLOBAL); // Globally enable interrupts printf("=================================================\r\n"); printf("[1mReady[0m. Press any key to proceed.\r\n"); //--------------------------------- getch(); // Wait for keypress output_high(D12_RESET_N); // Bring D12 out of reset (start it up!) delay_ms(1); //if(input(D12_INT_N)==0) // D12InterruptHandler(); printf("CMD: Set Address/Enable\r\n"); D12Write(D12_COMMAND, 0xD0); printf("\tDATA: 0x80 (Enable, no address)\r\n"); D12Write(D12_DATA, 0x80); printf("CMD: Set endpoint enable\r\n"); D12Write(D12_COMMAND, 0xD8); printf("\tDATA: 0x01 (Enabled)\r\n"); D12Write(D12_DATA, 0x01); printf("CMD: Set Mode\r\n"); D12Write(D12_COMMAND, 0xF3); printf("\tDATA: No Lazy Clock, Clock Running, "); printf("Interrupts=1, SoftConnect=1\r\n"); D12Write(D12_DATA, 0x1E); printf("\tDATA: Start of Frame interrupt disabled, "); printf("Set-to-one not set, "); printf("\r\n\t\tClock Division Factor = 1011b\r\n"); D12Write(D12_DATA, 0x0B); printf("End of Program\r\n"); } //-------------------------------------------------------- // Used for passing commands or data to the PDIUSBD12 void D12Write(short type, int data) { switch(type) { case D12_DATA: case D12_COMMAND: set_tris_d(0x00); // Set bus to output mode output_high(D12_RD_N); // Ensure we don't conflict with RD_N if(type == D12_COMMAND) output_high(D12_A0); else output_low(D12_A0); port_d = data; // Setup bus delay_ms(1); // Settling time output_low(D12_WR_N); output_high(D12_WR_N); if(type == D12_COMMAND) output_low(D12_A0); break; default: printf("Error in D12Write(), unknown type: 0x%x!\r\n", type); printf("Expecting one of:\r\n\t 0x%x\r\n\t0x%x\r\n", D12_COMMAND, D12_DATA); } } //-------------------------------------------------------- // Used for reading data from the PDIUSBD12 void D12Read(unsigned char* buffer, int reads) { int i; set_tris_d(0xFF); // Set bus to intput mode for(i = 0; i<reads; i++) { output_low(D12_RD_N); buffer[i] = port_d; // Latch in the bus output_high(D12_RD_N); } } //-------------------------------------------------------- // FIXME: Probably want to save some registers when handling // this interrupt, as it takes quite a long time. #INT_EXT void D12InterruptHandler() { unsigned char buffer[2]; int i; // The first "" is an bell control-character, the second an escape // [1;31m makes text red and bold, [0;37m makes it normal and white printf("\r\n\r\n[1;31mInterrupt![0;37m\r\n"); printf("CMD: Read Interrupt Register\r\n"); D12Write(D12_COMMAND, 0xF4); D12Read(buffer, 2); printf("Interrupt register bytes were 0x%x and 0x%x.\r\n\r\n", buffer[0], buffer[1]); getch(); for(i=0; i<6; i++) { printf("CMD: Read Last Transaction Status Register (0x%x)\r\n", 0x40 + i); D12Write(D12_COMMAND, 0x40 + i); D12Read(buffer, 1); printf("\tStatus: 0x%x.\r\n", buffer[0]); } printf("Press a key to resume\r\n\r\n"); getch(); }