/* * * Copyright 2012 Nanotec Systems Ltd, All Rights Reserved * */ #include #include #include #include #include void InitialiseSystem(void); void putrsUSARTjhh(const far rom char *data); void putrsUSARTjhh2(char *data); #pragma config FOSC=HS, PLLDIV=2, FCMEN=ON, WDT=OFF, IESO=OFF, XINST=OFF, LVP=OFF unsigned char command; unsigned char ledHigh; unsigned char ledMiddle; unsigned char ledLow; int ledValue; unsigned char buttonValue; char buttonValueString[4] = {' ', ' ', ' ', ' '}; unsigned char modulePaired; unsigned char n; char portNumber = ' '; char bitNumber = 0; char bitValue; unsigned char trisValue; int n2; char moduleName[22]; int butP =0; char sent = 0; char t; // PORTB for LEDs controllable from GBM (GBM output) // PORTD for PIC buttons (GBM input) // Commands from phone (Lxxx = LEDs<3 digit decimal byte(0..255)>, P = Paired, U = Unpaired // S<0,1,2,3,4,5,6,7,8> set output pin high (8 = all) // C<0,1,2,3,4,5,6,7,8> clear output pin (8 = all) // R<0,1,2,3,4,5,6,7,8> Read input state of pin (8 = all) // T<0,1,2,3,4,5,6,7,8><0,1> TRIS port (8 = all), 0 for output, 1 for input void main(void) { TRISB = 0x00; // All outputs for LEDs on PORT B TRISD = 0xFF; // All inputs for buttons on PORTD PORTB = 0; // Clear all LEDs PORTBbits.RB1 = 1; // Debug, light RB0 InitialiseSystem(); // Initialise the eusart baud rate to 9600 modulePaired = 0; while(1) { // Main loop, see if anything received from GBM then transmit anything to GBM // Check for any commands fom the Bluetooth module if (DataRdyUSART()) { command = getcUSART(); // Get the command from the Bluetooth module sent from the phone if (command >= 'a' && command <= 'z') command -= ('a' - 'A'); switch (command) { case 'N': for (n=0;n<22;n++) moduleName[n] = 0; // Clear the name (make sure 0 at end of name) // Read up to 20 characters for (n=0;n<20;n++) { while (!DataRdyUSART()) ; t = getcUSART(); if (t != ';') moduleName[n] = t; else break; } while(BusyUSART()) continue; // Wait for EUSART to become ready for (n=0;n<2;n++) Delay10KTCYx(200); // Delay 1 second RCSTAbits.CREN=0; // disable reception of serial data from the bt module putrsUSARTjhh ((const far rom char *)"AT+NAME"); putrsUSARTjhh2 ((char *)&moduleName[0]); // My version doesn't send the 0 at end of the string Delay10KTCYx(250); // Delay 1.25 seconds to make sure module has performed the command RCSTAbits.CREN=1; // Reenable reception from the BT module command = ' '; break; case 'L': while (!DataRdyUSART()) ; ledHigh = getcUSART(); // 100s while (!DataRdyUSART()) ; ledMiddle = getcUSART(); // 10s while (!DataRdyUSART()) ; ledLow = getcUSART(); // 1s ledValue = ((ledHigh-48)*100) + ((ledMiddle-48)*10) + ledLow-48; while (BusyUSART()); putcUSART((char)ledHigh); while (BusyUSART()); putcUSART((char)ledMiddle); while (BusyUSART()); putcUSART((char)ledLow); while (BusyUSART()); putcUSART(' '); while (BusyUSART()); putcUSART(0); PORTBbits.RB7 = (ledValue&0b10000000) != 0; PORTBbits.RB6 = (ledValue&0b01000000) != 0; PORTBbits.RB5 = (ledValue&0b00100000) != 0; PORTBbits.RB4 = (ledValue&0b00010000) != 0; PORTBbits.RB3 = (ledValue&0b00001000) != 0; PORTBbits.RB2 = (ledValue&0b00000100) != 0; PORTBbits.RB1 = (ledValue&0b00000010) != 0; PORTBbits.RB0 = (ledValue&0b00000001) != 0; // PORTB = ledValue; // Set all 8 LEds based on ledValue break; case 'P': // Pair modulePaired = 1; break; case 'U': // Unpair modulePaired = 0; break; case 'E': // Echo the character 'E' back to phone to test comms while (BusyUSART()); putcUSART('E'); while (BusyUSART()); putcUSART(0); break; // 50Hz with 1..2mS pulse that controls the servo position. 1.5mS is neutral. 5-10% duty cycle. case 'V': // Servo command Port D is assigned for servo control (up to 8) while (!DataRdyUSART()) ; bitNumber = getcUSART(); // bit 0 .. 8 (8=all) while (!DataRdyUSART()) ; ledHigh = getcUSART(); // 100s while (!DataRdyUSART()) ; ledMiddle = getcUSART(); // 10s while (!DataRdyUSART()) ; ledLow = getcUSART(); // 1s ledValue = ((ledHigh-48)*100) + ((ledMiddle-48)*10) + ledLow-48; switch (bitNumber) { case '0': PORTDbits.RD0 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD0 = 0; // Clear the servo output pulse break; case '1': PORTDbits.RD1 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD1 = 0; // Clear the servo output pulse break; case '2': PORTDbits.RD2 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD2 = 0; // Clear the servo output pulse break; case '3': PORTDbits.RD3 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD3 = 0; // Clear the servo output pulse break; case '4': PORTDbits.RD4 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD4 = 0; // Clear the servo output pulse break; case '5': PORTDbits.RD5 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD5 = 0; // Clear the servo output pulse break; case '6': PORTDbits.RD6 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD6 = 0; // Clear the servo output pulse break; case '7': PORTDbits.RD7 = 1; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTDbits.RD7 = 0; // Clear the servo output pulse break; case '8': PORTD = 0xFF; // Set the servo output pulse high // Delay 1mS + specified time Delay1KTCYx(2); // 1mS = 2000 instruction cycles @ 8MHz (each=0.5uS) if (ledValue > 0) Delay10TCYx((ledValue)); // 10 cycles = 5 uS PORTD = 0; // Clear the servo output pulse break; } break; case 'T': case 'C': case 'R': case 'S': while (!DataRdyUSART()) ; portNumber = getcUSART(); // Port A,B,C,D,E while (!DataRdyUSART()) ; bitNumber = getcUSART(); // Bit number or all bits if (command == 'T') { // Read the direction '0' for output, '1' for input while (!DataRdyUSART()) ; trisValue = getcUSART() - 48; // Input or output } if (portNumber >= 'a' && portNumber <= 'z') portNumber -= ('a' - 'A'); switch (portNumber) { case 'A': switch (bitNumber) { case '0': switch (command) { case 'S' : PORTAbits.RA0 = 1; break; case 'C' : PORTAbits.RA0 = 0; break; case 'R' : bitValue = PORTAbits.RA0; break; case 'T' : TRISAbits.TRISA0 = trisValue; break; } break; case '1': switch (command) { case 'S' : PORTAbits.RA1 = 1; break; case 'C' : PORTAbits.RA1 = 0; break; case 'R' : bitValue = PORTAbits.RA1; break; case 'T' : TRISAbits.TRISA1 = trisValue; break; } break; case '2': switch (command) { case 'S' : PORTAbits.RA2 = 1; break; case 'C' : PORTAbits.RA2 = 0; break; case 'R' : bitValue = PORTAbits.RA2; break; case 'T' : TRISAbits.TRISA2 = trisValue; break; } break; case '3': switch (command) { case 'S' : PORTAbits.RA3 = 1; break; case 'C' : PORTAbits.RA3 = 0; break; case 'R' : bitValue = PORTAbits.RA3; break; case 'T' : TRISAbits.TRISA3 = trisValue; break; } break; case '4': switch (command) { case 'S' : PORTAbits.RA4 = 1; break; case 'C' : PORTAbits.RA4 = 0; break; case 'R' : bitValue = PORTAbits.RA4; break; case 'T' : TRISAbits.TRISA4 = trisValue; break; } break; case '5': switch (command) { case 'S' : PORTAbits.RA5 = 1; break; case 'C' : PORTAbits.RA5 = 0; break; case 'R' : bitValue = PORTAbits.RA5; break; case 'T' : TRISAbits.TRISA5 = trisValue; break; } break; case '6': switch (command) { case 'S' : PORTAbits.RA6 = 1; break; case 'C' : PORTAbits.RA6 = 0; break; case 'R' : bitValue = PORTAbits.RA6; break; case 'T' : TRISAbits.TRISA6 = trisValue; break; } break; // case '7': // switch (command) { // case 'S' : // PORTAbits.RA7 = 1; // break; // case 'C' : // PORTAbits.RA7 = 0; // break; // case 'R' : // bitValue = PORTAbits.RA7; // break; // case 'T' : // TRISAbits.TRISA7 = trisValue; // break; // } // break; case '8': switch (command) { case 'S' : PORTA = 0xFF; break; case 'C' : PORTA = 0; break; case 'R' : bitValue = PORTA; break; case 'T' : TRISA = trisValue * 255; // if it's a '1' for input then set all bits break; } break; } break; case 'B': switch (bitNumber) { case '0': switch (command) { case 'S' : PORTBbits.RB0 = 1; break; case 'C' : PORTBbits.RB0 = 0; break; case 'R' : bitValue = PORTBbits.RB0; break; case 'T' : TRISBbits.TRISB0 = trisValue; break; } break; case '1': switch (command) { case 'S' : PORTBbits.RB1 = 1; break; case 'C' : PORTBbits.RB1 = 0; break; case 'R' : bitValue = PORTBbits.RB1; break; case 'T' : TRISBbits.TRISB1 = trisValue; break; } break; case '2': switch (command) { case 'S' : PORTBbits.RB2 = 1; break; case 'C' : PORTBbits.RB2 = 0; break; case 'R' : bitValue = PORTBbits.RB2; break; case 'T' : TRISBbits.TRISB2 = trisValue; break; } break; case '3': switch (command) { case 'S' : PORTBbits.RB3 = 1; break; case 'C' : PORTBbits.RB3 = 0; break; case 'R' : bitValue = PORTBbits.RB3; break; case 'T' : TRISBbits.TRISB3 = trisValue; break; } break; case '4': switch (command) { case 'S' : PORTBbits.RB4 = 1; break; case 'C' : PORTBbits.RB4 = 0; break; case 'R' : bitValue = PORTBbits.RB4; break; case 'T' : TRISBbits.TRISB4 = trisValue; break; } break; case '5': switch (command) { case 'S' : PORTBbits.RB5 = 1; break; case 'C' : PORTBbits.RB5 = 0; break; case 'R' : bitValue = PORTBbits.RB5; break; case 'T' : TRISBbits.TRISB5 = trisValue; break; } break; case '6': switch (command) { case 'S' : PORTBbits.RB6 = 1; break; case 'C' : PORTBbits.RB6 = 0; break; case 'R' : bitValue = PORTBbits.RB6; break; case 'T' : TRISBbits.TRISB6 = trisValue; break; } break; case '7': switch (command) { case 'S' : PORTBbits.RB7 = 1; break; case 'C' : PORTBbits.RB7 = 0; break; case 'R' : bitValue = PORTBbits.RB7; break; case 'T' : TRISBbits.TRISB7 = trisValue; break; } break; case '8': switch (command) { case 'S' : PORTB = 0xFF; break; case 'C' : PORTB = 0; break; case 'R' : bitValue = PORTB; break; case 'T' : TRISB = trisValue * 255; // if it's a '1' for input then set all bits break; } break; } break; case 'C': switch (bitNumber) { case '0': switch (command) { case 'S' : PORTCbits.RC0 = 1; break; case 'C' : PORTCbits.RC0 = 0; break; case 'R' : bitValue = PORTCbits.RC0; break; case 'T' : TRISCbits.TRISC0 = trisValue; break; } break; case '1': switch (command) { case 'S' : PORTCbits.RC1 = 1; break; case 'C' : PORTCbits.RC1 = 0; break; case 'R' : bitValue = PORTCbits.RC1; break; case 'T' : TRISCbits.TRISC1 = trisValue; break; } break; case '2': // Used for Bluetooth connection status break; // case '3': // switch (command) { // case 'S' : // PORTCbits.RC3 = 1; // break; // case 'C' : // PORTCbits.RC3 = 0; // break; // case 'R' : // bitValue = PORTCbits.RC3; // break; // case 'T' : // TRISCbits.TRISC3 = trisValue; // break; // } // break; case '4': switch (command) { case 'S' : PORTCbits.RC4 = 1; break; case 'C' : PORTCbits.RC4 = 0; break; case 'R' : bitValue = PORTCbits.RC4; break; // case 'T' : // TRISCbits.TRISC4 = trisValue; // break; } break; case '5': // Used for Bluetooth Serial port break; case '6': // Used for Bluetooth Serial port break; case '7': switch (command) { case 'S' : PORTCbits.RC7 = 1; break; case 'C' : PORTCbits.RC7 = 0; break; case 'R' : bitValue = PORTCbits.RC7; break; case 'T' : TRISCbits.TRISC7 = trisValue; break; } break; case '8': switch (command) { case 'S' : PORTC = 0xFF; break; case 'C' : PORTC = 0; break; case 'R' : bitValue = PORTC; break; case 'T' : TRISC = trisValue * 255; break; } break; } break; case 'D': switch (bitNumber) { case '0': switch (command) { case 'S' : PORTDbits.RD0 = 1; break; case 'C' : PORTDbits.RD0 = 0; break; case 'R' : bitValue = PORTDbits.RD0; break; case 'T' : TRISDbits.TRISD0 = trisValue; break; } break; case '1': switch (command) { case 'S' : PORTDbits.RD1 = 1; break; case 'C' : PORTDbits.RD1 = 0; break; case 'R' : bitValue = PORTDbits.RD1; break; case 'T' : TRISDbits.TRISD1 = trisValue; break; } break; case '2': switch (command) { case 'S' : PORTDbits.RD2 = 1; break; case 'C' : PORTDbits.RD2 = 0; break; case 'R' : bitValue = PORTDbits.RD2; break; case 'T' : TRISDbits.TRISD2 = trisValue; break; } break; case '3': switch (command) { case 'S' : PORTDbits.RD3 = 1; break; case 'C' : PORTDbits.RD3 = 0; break; case 'R' : bitValue = PORTDbits.RD3; break; case 'T' : TRISDbits.TRISD3 = trisValue; break; } break; case '4': switch (command) { case 'S' : PORTDbits.RD4 = 1; break; case 'C' : PORTDbits.RD4 = 0; break; case 'R' : bitValue = PORTDbits.RD4; break; case 'T' : TRISDbits.TRISD4 = trisValue; break; } break; case '5': switch (command) { case 'S' : PORTDbits.RD5 = 1; break; case 'C' : PORTDbits.RD5 = 0; break; case 'R' : bitValue = PORTDbits.RD5; break; case 'T' : TRISDbits.TRISD5 = trisValue; break; } break; case '6': switch (command) { case 'S' : PORTDbits.RD6 = 1; break; case 'C' : PORTDbits.RD6 = 0; break; case 'R' : bitValue = PORTDbits.RD6; break; case 'T' : TRISDbits.TRISD6 = trisValue; break; } break; case '7': switch (command) { case 'S' : PORTDbits.RD7 = 1; break; case 'C' : PORTDbits.RD7 = 0; break; case 'R' : bitValue = PORTDbits.RD7; break; case 'T' : TRISDbits.TRISD7 = trisValue; break; } break; case '8': switch (command) { case 'S' : PORTD = 0xFF; break; case 'C' : PORTD = 0; break; case 'R' : bitValue = PORTD; break; case 'T' : TRISD = trisValue * 255; break; } break; } break; case 'E': switch (bitNumber) { case '0': switch (command) { case 'S' : PORTEbits.RE0 = 1; break; case 'C' : PORTEbits.RE0 = 0; break; case 'R' : bitValue = PORTEbits.RE0; break; case 'T' : TRISEbits.TRISE0 = trisValue; break; } break; case '1': switch (command) { case 'S' : PORTEbits.RE1 = 1; break; case 'C' : PORTEbits.RE1 = 0; break; case 'R' : bitValue = PORTEbits.RE1; break; case 'T' : TRISEbits.TRISE1 = trisValue; break; } break; case '2': switch (command) { case 'S' : PORTEbits.RE2 = 1; break; case 'C' : PORTEbits.RE2 = 0; break; case 'R' : bitValue = PORTEbits.RE2; break; case 'T' : TRISEbits.TRISE2 = trisValue; break; } break; case '3': switch (command) { case 'S' : PORTEbits.RE3 = 1; break; case 'C' : PORTEbits.RE3 = 0; break; case 'R' : bitValue = PORTEbits.RE3; break; // case 'T' : // TRISEbits.TRISE3 = trisValue; // break; } break; // case '4': // switch (command) { // case 'S' : // PORTEbits.RE4 = 1; // break; // case 'C' : // PORTEbits.RE4 = 0; // break; // case 'R' : // bitValue = PORTEbits.RE4; // break; // case 'T' : // TRISEbits.TRISE4 = trisValue; // break; // } // break; case '5': // switch (command) { // case 'S' : // PORTEbits.RE5 = 1; // break; // case 'C' : // PORTEbits.RE5 = 0; // break; // case 'R' : // bitValue = PORTEbits.RA5; // break; // case 'T' : // TRISEbits.TRISE5 = trisValue; // break; // } // break; // case '6': // switch (command) { // case 'S' : // PORTEbits.RE6 = 1; // break; // case 'C' : // PORTEbits.RE6 = 0; // break; // case 'R' : // bitValue = PORTEbits.RE6; // break; // case 'T' : // TRISEbits.TRISE6 = trisValue; // break; // } // break; // case '7': // switch (command) { // case 'S' : // PORTEbits.RE7 = 1; // break; // case 'C' : // PORTEbits.RE7 = 0; // break; // case 'R' : // bitValue = PORTEbits.RA7; // break; // case 'T' : // TRISEbits.TRISE7 = trisValue; // break; // } // break; case '8': switch (command) { case 'S' : PORTE = 0xFF; break; case 'C' : PORTE = 0; break; case 'R' : bitValue = PORTE; break; case 'T' : TRISE = trisValue * 255; break; } break; } break; } break; default: break; } } if (command == 'R') { command = ' '; if (bitValue < 8) { // '0' or '1' while (BusyUSART()); putcUSART(bitValue+48); } else { // byte as 3 decimal values while (BusyUSART()); putcUSART((bitValue/100)+48); while (BusyUSART()); putcUSART(((bitValue%100)/10)+48); while (BusyUSART()); putcUSART(((bitValue%100)%10)+48); } } buttonValue = 0; // Check for any button presses if (PORTDbits.RD0) buttonValue += 1; if (PORTDbits.RD1) buttonValue += 2; if (PORTDbits.RD2) buttonValue += 4; if (PORTDbits.RD3) buttonValue += 8; if (PORTDbits.RD4) buttonValue += 16; if (PORTDbits.RD5) buttonValue += 32; if (PORTDbits.RD6) buttonValue += 64; if (PORTDbits.RD7) buttonValue += 128; // Check we have received a pair command 'P' from the host and are currently paired if (modulePaired != 0) { if (buttonValue != 0) { // Write the button values out as a 4 character decimal value including padding spaces buttonValueString[0] = ' '; buttonValueString[1] = ' '; buttonValueString[2] = ' '; buttonValueString[3] = ' '; itoa (buttonValue, buttonValueString); while (BusyUSART()); putcUSART('B'); for (n=0; n<4; n++) { while (BusyUSART()); putcUSART((char)buttonValueString[n]); if (buttonValueString[n] == 0) break; } sent = 0; } else { if (sent == 0) { butP++; // increment timer to send 0 button pressed message if (butP == 10000) { butP = 0; while (BusyUSART()); putrsUSART ((const far rom char *)"B0"); sent = 1; } } } } } CloseUSART(); while(1); // If I don't put this in then the main program repeats from the start forever } // Own version that doesnt send the 0 at end of string void putrsUSARTjhh(const far rom char *data) { char c; while ((c = *data++)) { // Transmit a byte while (PIR1bits.TXIF == 0) ; TXREG = c; }; } void putrsUSARTjhh2(char *data) { char c; while ((c = *data++)) { // Transmit a byte while (PIR1bits.TXIF == 0) ; TXREG = c; }; } void InitialiseSystem() { TRISCbits.TRISC6 = 1; TRISCbits.TRISC7 = 1; SPBRG=51; TXSTAbits.BRGH=1; //data rate for sending (see 18F4550 manual under 'EUSART') TXSTAbits.SYNC=0; //asynchronous RCSTAbits.SPEN=1; //enable serial port pins RCSTAbits.CREN=1; //enable reception RCSTAbits.SREN=0; //no effect PIE1bits.TXIE=0; //disable tx interrupts PIE1bits.RCIE=0; //disable rx interrupts TXSTAbits.TX9=0; //8-bit transmission RCSTAbits.RX9=0; //8-bit reception TXSTAbits.TXEN=0; //reset transmitter TXSTAbits.TXEN=1; //enable the transmitter ADCON0 = 0x00; UCONbits.USBEN = 0; // Disable USB ADCON1 = 0x0F; // Configure RB4:0 to digital inputs CMCON = 7; // Set comparators for digital input }