// file: irbeacon.c // vers: 1.0 // // This is a program for the PIC16F84 running on an iRX board // (see www.media.mit.edu/~r/projects/irx2_1/). // // This program repeatedly writes "Hello, world\r\n" to the // serial port and over the IR port using IrDA signalling // protocols. Its primary function is as a debugging aid for // other IrDA programs. // #include <16F84.H> #fuses HS,WDT,NOPROTECT,PUT #use DELAY(clock=10000000) #use fast_io(B) // Standard definitions for the irx2_1 board // #define RS232_XMIT PIN_B1 // (output) RS232 serial transmit #define RED_LED PIN_B2 // (output) Red LED (low true) #define IR_LED PIN_B3 // (output) Infrared LED (low true) #define IR_SENSOR PIN_B4 // (input) IR sensor (Sharp IS1U30) #define RS232_RCV PIN_B5 // (input) RS232 serial receive // Macros to simplify I/O operations // #define RED_LED_ON output_low(RED_LED) #define RED_LED_OFF output_high(RED_LED) #define IR_LED_ON output_low(IR_LED) #define IR_LED_OFF output_high(IR_LED) #define IR_RECEIVED (!input(IR_SENSOR)) // Default TRIS bits: RS232_RCV and IR_SENSOR are inputs, all // others are outputs // #define IRX_B_TRIS 0b00110000 // =================================================================== // General definitions // struct { short int RBIF; short int INTF; short int T0IF; short int RBIE; short int INTE; short int T0IE; short int PEIE; short int GIE; } INTCON; #byte INTCON = 0x0B // linkage between interrupt routine (handle_ext_int) and // foreground routines. Set to true when an IR pulse was // detected (at interrupt level). // int gFlags; #bit gIRDAPulseSeen = gFlags.0 // general I/O buffer // #define BUF_SIZE 32 char gBuf[BUF_SIZE]; // =================================================================== // IRDA constants // // Port B0 is also an input (jumpered from IR_RECEIVE port) #define IRDA_TRIS (IRX_B_TRIS | 0b00000001) // Minimum IRDA pulse is 1.63 uSec. With 400 nSec instruction // cycle time (10MHz clock), this requires 4+ cycles, ergo 5. // #define IRDA_PULSE_CYCLES 5 // The following assume an RTCC prescaler of 4:1, or 1600 nSec tics // #define IRDA_BIT_TICS 65 // 1/9600 baud // =================================================================== // IR Output // // Wait until the *previous* bit period has expired, then // write a single bit using IrDA 1.0 protocol: a 1.63 uSec // pulse for a zero bit, no pulse for a one bit. // // Reads low order bit in b // void putIRDABit(int b) { do {} while (!INTCON.T0IF); // wait for TMR0 to expire set_rtcc(256-IRDA_BIT_TICS); // reset for next bit period INTCON.T0IF = 0; restart_wdt(); output_high(PIN_A2); // for 'scope testing if (!(b&1)) { // pulse for 0 bit, no pulse for 1 IR_LED_ON; delay_cycles(IRDA_PULSE_CYCLES-1); IR_LED_OFF; } output_low(PIN_A2); // for 'scope testing } // write a start bit, 8 bits of b (LSB first), and a stop // bit using IrDA 1.0 protocol. // void putIRDAByte(char b) { output_high(PIN_A1); putIRDABit(0); // start bit putIRDABit(b); // b0: lsb first b >>= 1; putIRDABit(b); // b1 b >>= 1; putIRDABit(b); // b2 b >>= 1; putIRDABit(b); // b3 b >>= 1; putIRDABit(b); // b4 b >>= 1; putIRDABit(b); // b5 b >>= 1; putIRDABit(b); // b6 b >>= 1; putIRDABit(b); // b7: msb putIRDABit(1); // stop bit output_low(PIN_A1); } // =================================================================== // RS232 constants #use rs232(baud=9600, xmit=RS232_XMIT, rcv=RS232_RCV, RESTART_WDT) // =================================================================== // Main read/write loop // // sleep() 27 times for 18 mSec for a total of 500 mSec delay. // Normally we'd use a prescaler on the watchdog timer instead, // but the prescaler is already assigned to the RTCC. // void snooze() { int i; for (i=0; i<27; i++) sleep(); } void main() { set_tris_b(IRDA_TRIS); RED_LED_ON; // reality check at startup delay_ms(200); RED_LED_OFF; printf("IrDA Beacon 1.0\r\n"); setup_counters(RTCC_INTERNAL, RTCC_DIV_4); while (1) { RED_LED_ON; printf("Hello, world.\r\n"); RED_LED_OFF; INTCON.T0IF = 1; // makes putIRBit() start immediately putIRDAByte("Hello, world.\r\n"); snooze(); } }