#include #include "hardware.h" // ======================================================================= #define BUF_LENGTH 100 //Number of characters in a frame #define EnableInterrupts _EINT() char rxdata; //RS232 RX data byte unsigned char buf[BUF_LENGTH]; signed char RXTXstate; //used for transmit recieve byte count unsigned char flags; //stores the mask value (used in anticollision) unsigned char RXErrorFlag; unsigned char RXflag; //indicates that data is in buffer unsigned char i_reg; //interrupt register unsigned char CollPoss; unsigned char uid[10]; unsigned char i; unsigned char RXdone; unsigned char ENABLE; unsigned char POLLING; unsigned char Register[10]; unsigned char command[10]; #define BAUD0 0x3A //baud rate generator = 115200 for 6.78 MHz Clock #define BAUD1 0x00 #define BAUD0EN 0x2B //baud rate for DCO = 4.9MHz #define BAUD1EN 0x00 // ========================================================================= // Main function with init and an endless loop // // void InventoryRequest(unsigned char *mask, unsigned char lenght); void EnableSlotCounter(void); void DisableSlotCounter(void); void WriteSingle(unsigned char *pbuf, unsigned char lenght); void WriteCont(unsigned char *pbuf, unsigned char lenght); void ReadSingle(unsigned char *pbuf, unsigned char lenght); void ReadCont(unsigned char *pbuf, unsigned char lenght); void DirectCommand(unsigned char *pbuf); void RAWwrite(unsigned char *pbuf, unsigned char lenght); void delay_ms(unsigned int n_ms); void CounterSet(void); void PARset(void) { TRFDirOUT; /* P4 output */ TRFFunc; TRFWrite = 0x00; /* P4 set to 0 - choose parallel inteface for the TRF796x */ clkOFF; clkPOUTset; /* DATA_CLK on P3.3 */ irqPINset; irqEDGEset; /* rising edge interrupt */ } void InitialSettings(void) { /*~~~~~~~~~~~~~~~~~~~~~~~*/ unsigned char command[2]; /*~~~~~~~~~~~~~~~~~~~~~~~*/ command[0] = ModulatorControl; command[1] = 0x20; //6.78 MHz // command[1] = 0x31; //13.56 MHz WriteSingle(command, 2); } void OSCsel(unsigned char mode) { unsigned int ii1; if(mode == 0x00){ //select crystal oscilator BCSCTL1 |= XTS + XT2OFF; // ACLK = LFXT1 HF XTAL BCSCTL3 |= LFXT1S1+LFXT1S0; // 3 – 16MHz crystal or resonator // turn external oscillator on do { IFG1 &= ~OFIFG; // Clear OSCFault flag for (ii1 = 0xFF; ii1 > 0; ii1--); // Time delay for flag to set } while ((IFG1 & OFIFG) == OFIFG); // OSCFault flag still set? BCSCTL2 |= SELM1 + SELM0 + SELS; // MCLK = SMCLK = HF LFXT1 (safe) return; } else{ //select DCO for main clock DCOCTL |= DCO0 + DCO1 + DCO2; BCSCTL1 |= XT2OFF + XTS + RSEL0 + RSEL1 + RSEL2; // turn external oscillator on // do // { // IFG1 &= ~OFIFG; // Clear OSCFault flag // for (ii1 = 0xFF; ii1 > 0; ii1--); // Time delay for flag to set // } // while ((IFG1 & OFIFG) == OFIFG); // OSCFault flag still set? BCSCTL2 &= ~(SELM1 + SELM0 + SELS + DCOR); return; } //_BIC_SR(OSCOFF); } unsigned char FindTags(unsigned char protocol) { while(1) { // ISO15693 // command[0] = ChipStateControl; // turn on RF driver command[1] = 0x20; command[2] = ISOControl; // set register 0x01 for ISO15693 operation command[3] = 0x02; WriteSingle(command, 4); delay_ms(5); flags = 0x06; // 16 slots //flags = 0x26; //1 slot command[0] = 0x00; InventoryRequest(command, 0); // send Inventory request // command[0] = ChipStateControl; // turn off RF driver // command[1] = 0x01; WriteSingle(command, 2); delay_ms(1); command[0] = IRQStatus; command[1] = IRQMask; ReadSingle(command, 1); } /* while */ } /* FindTags */ void InventoryRequest(unsigned char *mask, unsigned char lenght) /* host command 0x14 */ { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* 010800030414(req.packet)[00ff] */ unsigned char i = 1, j = 3, NoSlots; unsigned char *PslotNo, slotNo[17]; unsigned char NewMask[8], NewLenght, masksize; int size; unsigned int k = 0; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ //added code buf[0] = ModulatorControl; buf[1] = 0x20; WriteSingle(buf, 2); //end added code slotNo[0] = 0x00; if((flags & BIT5) == 0x00) { /* flag bit5 is the number of slots indicator */ NoSlots = 17; /* 16 slots if bit is cleared */ EnableSlotCounter(); } else NoSlots = 2; /* 1 slot if bit is set */ PslotNo = &slotNo[0]; /* slot number pointer */ masksize = (((lenght >> 2) + 1) >> 1); /* masksize is 1 for lenght = 4 or 8 */ /* * masksize is 2 for lenght = 12 or 16 ; * and so on */ size = masksize + 3; /* mask value + mask lenght + command code + flags */ buf[0] = 0x8f; buf[1] = 0x91; /* send with CRC */ buf[2] = 0x3d; /* write continous from 1D */ buf[3] = (char) (size >> 8); buf[4] = (char) (size << 4); buf[5] = flags; /* ISO15693 flags */ buf[6] = 0x01; /* anticollision command code */ //optional AFI should be here buf[7] = lenght; /* masklenght */ if(lenght > 0) { for(i = 0; i < masksize; i++) buf[i + 8] = *(mask + i); } /* if */ command[0] = IRQStatus; command[1] = IRQMask; //Dummy read ReadCont(command, 1); CounterSet(); /* TimerA set */ countValue = count1ms * 20; /* 20ms */ irqCLR; /* PORT2 interrupt flag clear */ irqON; RAWwrite(&buf[0], masksize + 8); /* writing to FIFO */ i_reg = 0x01; startCounter; /* start timer up mode */ LPM0; /* wait for end of TX interrupt */ for(i = 1; i < NoSlots; i++) { /* 1 or 16 available timeslots */ RXTXstate = 1; /* prepare the global counter */ /* the first UID will be stored from buf[1] upwards */ CounterSet(); /* TimerA set */ //countValue = count1ms * 20; /* 20ms */ countValue = 0x4E20; startCounter; /* start timer up mode */ k = 0; LPM0; while(i_reg == 0x01) { /* wait for RX complete */ k++; if(k == 0xFFF0) { i_reg = 0x00; RXErrorFlag = 0x00; break; } } command[0] = RSSILevels; /* read RSSI levels */ ReadSingle(command, 1); if(i_reg == 0xFF) { /* recieved UID in buffer */ for(j = 3; j < 11; j++) { //Put_byte(buf[j]); } i=0; for(j=10; j>=3;j--) { uid[i]=buf[j]; i++; } } else if(i_reg == 0x02) { /* collision occured */ PslotNo++; *PslotNo = i; } else if(i_reg == 0x00) { /* timer interrupt */ } else ; command[0] = Reset; /* FIFO has to be reset before recieving the next response */ DirectCommand(command); if((NoSlots == 17) && (i < 16)) { /* if 16 slots used send EOF(next slot) */ command[0] = StopDecoders; DirectCommand(command); command[0] = RunDecoders; DirectCommand(command); //while(1) // { command[0] = TransmitNextSlot; DirectCommand(command); // } } else if((NoSlots == 17) && (i == 16)) { /* at the end of slot 16 stop the slot counter */ DisableSlotCounter(); } else if(NoSlots == 2) break; } /* for */ NewLenght = lenght + 4; /* the mask lenght is a multiple of 4 bits */ masksize = (((NewLenght >> 2) + 1) >> 1) - 1; while((*PslotNo != 0x00) && (NoSlots == 17)) { *PslotNo = *PslotNo - 1; for(i = 0; i < 8; i++) NewMask[i] = *(mask + i); /* first the whole mask is copied */ if((NewLenght & BIT2) == 0x00) *PslotNo = *PslotNo << 4; NewMask[masksize] |= *PslotNo; /* the mask is changed */ InventoryRequest(&NewMask[0], NewLenght); /* recursive call */ PslotNo--; } /* while */ irqOFF; } /* InventoryRequest */ void EnableSlotCounter(void) { buf[41] = IRQMask; /* next slot counter */ buf[40] = IRQMask; ReadSingle(&buf[41], 1); buf[41] |= BIT0; /* set BIT0 in register 0x01 */ WriteSingle(&buf[40], 2); } void DisableSlotCounter(void) { buf[41] = IRQMask; /* next slot counter */ buf[40] = IRQMask; ReadSingle(&buf[41], 1); buf[41] &= 0xfe; /* clear BIT0 in register 0x01 */ WriteSingle(&buf[40], 2); } /* ======================================================================================================================= ======================================================================================================================= */ void STOPcondition(void) { TRFWrite |= 0x80; /* stop condition */ clkON; TRFWrite = 0x00; clkOFF; } /* STOPcondition */ /* ======================================================================================================================= ======================================================================================================================= */ void STOPcont(void) { /* stop condition for continous mode */ TRFWrite = 0x00; TRFDirOUT; TRFWrite = 0x80; __no_operation(); TRFWrite = 0x00; } /* STOPcond */ /* ======================================================================================================================= ======================================================================================================================= */ void STARTcondition(void) { TRFWrite = 0x00; clkON; TRFWrite = 0xff; clkOFF; } /* STARTcondition */ /////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////// /* ======================================================================================================================= Function writes only one register or a multiple number ; of registers with specified addresses ; ======================================================================================================================= */ void WriteSingle(unsigned char *pbuf, unsigned char lenght) { STARTcondition(); while(lenght > 0) { *pbuf = (0x1f &*pbuf); /* register address */ /* address, write, single */ for(i = 0; i < 2; i++) { TRFWrite = *pbuf; /* send command and data */ clkON; clkOFF; pbuf++; lenght--; } } /* while */ STOPcondition(); } /* WriteSingle */ /* ======================================================================================================================= Function writes a specified number of registers from ; a specified address upwards ; ======================================================================================================================= */ void WriteCont(unsigned char *pbuf, unsigned char lenght) { STARTcondition(); *pbuf = (0x20 | *pbuf); /* address, write, continous */ *pbuf = (0x3f &*pbuf); /* register address */ while(lenght > 0) { TRFWrite = *pbuf; /* send command */ clkON; clkOFF; pbuf++; lenght--; } /* while */ STOPcont(); } /* WriteCont */ /* ======================================================================================================================= Function reads only one register ; ======================================================================================================================= */ void ReadSingle(unsigned char *pbuf, unsigned char lenght) { STARTcondition(); while(lenght > 0) { *pbuf = (0x40 | *pbuf); /* address, read, single */ *pbuf = (0x5f &*pbuf); /* register address */ TRFWrite = *pbuf; /* send command */ clkON; clkOFF; TRFDirIN; /* read register */ clkON; __no_operation(); *pbuf = TRFRead; clkOFF; TRFWrite = 0x00; TRFDirOUT; pbuf++; lenght--; } /* while */ STOPcondition(); /**************************************************************/ } /* ReadSingle */ /* ======================================================================================================================= Function reads specified number of registers from a ; specified address upwards. ; ======================================================================================================================= */ void ReadCont(unsigned char *pbuf, unsigned char lenght) { STARTcondition(); *pbuf = (0x60 | *pbuf); /* address, read, continous */ *pbuf = (0x7f &*pbuf); /* register address */ TRFWrite = *pbuf; /* send command */ clkON; clkOFF; TRFDirIN; /* read register */ /* * TRFWrite = 0x00; */ while(lenght > 0) { clkON; /* * TRFDirIN; */ __no_operation(); *pbuf = TRFRead; /* * TRFDirOUT; */ clkOFF; pbuf++; lenght--; } /* while */ STOPcont(); } /* ReadCont */ /* ======================================================================================================================= Function DirectCommand transmits a command to the reader chip ======================================================================================================================= */ void DirectCommand(unsigned char *pbuf) { STARTcondition(); *pbuf = (0x80 | *pbuf); /* command */ *pbuf = (0x9f &*pbuf); /* command code */ TRFWrite = *pbuf; /* send command */ clkON; clkOFF; STOPcondition(); } /* DirectCommand */ /* ======================================================================================================================= Function used for direct writing to reader chip ; ======================================================================================================================= */ void RAWwrite(unsigned char *pbuf, unsigned char lenght) { STARTcondition(); while(lenght > 0) { TRFWrite = *pbuf; /* send command */ clkON; clkOFF; pbuf++; lenght--; } /* while */ STOPcont(); } /* RAWwrite */ /* ======================================================================================================================= Direct mode (no stop condition) ; ======================================================================================================================= */ /* ======================================================================================================================= ======================================================================================================================= */ void InterruptHandlerReader(unsigned char *Register) { /*~~~~~~~~~~~~~~~~*/ /* * char phello[20]; * //for testing */ unsigned char len; /*~~~~~~~~~~~~~~~~*/ /* * Register = Register & 0xF7; * //set the parity flag to 0 ; * parity is not used in 15693 and Tag-It */ if(*Register == 0xA0) { /* TX active and only 3 bytes left in FIFO */ i_reg = 0x00; } else if(*Register == BIT7) { /* TX complete */ i_reg = 0x00; *Register = Reset; /* reset the FIFO after TX */ DirectCommand(Register); //led1on; P3OUT ^= BIT0; delay_ms(1); } else if((*Register & BIT1) == BIT1) { /* collision error */ i_reg = 0x02; /* RX complete */ *Register = StopDecoders; /* reset the FIFO after TX */ DirectCommand(Register); CollPoss = CollisionPosition; ReadSingle(&CollPoss, 1); len = CollPoss - 0x20; /* number of valid bytes if FIFO */ if((len & 0x0f) != 0x00) len = len + 0x10; /* add 1 byte if broken byte recieved */ len = len >> 4; if(len != 0x00) { buf[RXTXstate] = FIFO; /* write the recieved bytes to the correct place of the * buffer; * */ ReadCont(&buf[RXTXstate], len); RXTXstate = RXTXstate + len; } /* if */ *Register = Reset; DirectCommand(Register); *Register = IRQStatus; /* IRQ status register address */ *(Register + 1) = IRQMask; //ReadSingle(Register, 2); /* function call for single address read */ // ReadCont(Register, 2); ReadSingle(Register, 1); irqCLR; } else if(*Register == BIT6) { /* RX flag means that EOF has been recieved */ /* and the number of unread bytes is in FIFOstatus regiter */ if(RXErrorFlag == 0x02) { i_reg = 0x02; return; } *Register = FIFOStatus; ReadSingle(Register, 1); /* determine the number of bytes left in FIFO */ // ReadCont(Register, 1); *Register = (0x0F &*Register) + 0x01; buf[RXTXstate] = FIFO; /* write the recieved bytes to the correct place of the*/ ReadCont(&buf[RXTXstate], *Register); RXTXstate = RXTXstate +*Register; *Register = TXLenghtByte2; /* determine if there are broken bytes */ // ReadSingle(Register, 1); /* determine the number of bits */ ReadCont(Register, 1); if((*Register & BIT0) == BIT0) { *Register = (*Register >> 1) & 0x07; /* mask the first 5 bits */ *Register = 8 -*Register; buf[RXTXstate - 1] &= 0xFF << *Register; } /* if */ *Register = Reset; /* reset the FIFO after last byte has been read out */ DirectCommand(Register); i_reg = 0xFF; /* signal to the recieve funnction that this are the last bytes */ } else if(*Register == 0x60) { /* RX active and 9 bytes allready in FIFO */ i_reg = 0x01; buf[RXTXstate] = FIFO; ReadCont(&buf[RXTXstate], 9); /* read 9 bytes from FIFO */ RXTXstate = RXTXstate + 9; if(irqPORT & irqPIN) { *Register = IRQStatus; /* IRQ status register address */ *(Register + 1) = IRQMask; //ReadSingle(Register, 2); /* function call for single address read */ //ReadCont(Register, 2); ReadSingle(Register, 1); irqCLR; if(*Register == 0x40) { /* end of recieve */ *Register = FIFOStatus; ReadSingle(Register, 1); /* determine the number of bytes left in FIFO */ //ReadCont(Register, 1); *Register = 0x0F & (*Register + 0x01); buf[RXTXstate] = FIFO; /* write the recieved bytes to the correct place of the*/ ReadCont(&buf[RXTXstate], *Register); RXTXstate = RXTXstate +*Register; *Register = TXLenghtByte2; /* determine if there are broken bytes */ ReadSingle(Register, 1); /* determine the number of bits */ //ReadCont(Register, 1); if((*Register & BIT0) == BIT0) { *Register = (*Register >> 1) & 0x07; /* mask the first 5 bits */ *Register = 8 -*Register; buf[RXTXstate - 1] &= 0xFF << *Register; } /* if */ P1OUT |= BIT4; i_reg = 0xFF; /* signal to the recieve funnction that this are the last bytes */ *Register = Reset; /* reset the FIFO after last byte has been read out */ DirectCommand(Register); } else if(*Register == 0x50) { /* end of recieve and error */ i_reg = 0x02; } } else { Register[0] = IRQStatus; Register[1] = IRQMask; //ReadSingle(Register, 2); /* function call for single address read */ //ReadCont(Register, 2); ReadSingle(Register, 1); if(Register[0] == 0x00) i_reg = 0xFF; } } else if((*Register & BIT4) == BIT4) { /* CRC error */ if((*Register & BIT5) == BIT5) { i_reg = 0x01; /* RX active */ RXErrorFlag = 0x02; } else i_reg = 0x02; /* end of RX */ } else if((*Register & BIT2) == BIT2) { /* byte framing error */ if((*Register & BIT5) == BIT5) { i_reg = 0x01; /* RX active */ RXErrorFlag = 0x02; } else i_reg = 0x02; /* end of RX */ } else if(*Register == BIT0) { /* No response interrupt */ i_reg = 0x00; } else { /* Interrupt register not properly set */ i_reg = 0x02; *Register = StopDecoders; /* reset the FIFO after TX */ DirectCommand(Register); *Register = Reset; DirectCommand(Register); *Register = IRQStatus; /* IRQ status register address */ *(Register + 1) = IRQMask; //ReadSingle(Register, 2); /* function call for single address read */ //ReadCont(Register, 2); ReadSingle(Register, 1); irqCLR; } } /* InterruptHandlerReader */ /* ======================================================================================================================= ======================================================================================================================= */ void delay_ms(unsigned int n_ms) { unsigned int ii1, ii0; for(ii0=n_ms; ii0>0; ii0--) { ii1 = 0x07FF; // Delay do (ii1--); while (ii1 != 0); } } void CounterSet(void) { TACTL |= TACLR; TACTL &= ~TACLR; //reset the timerA TACTL |= TASSEL0 + ID1 + ID0; //ACLK, div 8, interrupt enable, timer stoped TAR = 0x0000; TACCTL0 |= CCIE; //compare interrupt enable }//CounterSet() void BaudSet(unsigned char mode) { if(mode == 0x00) { UCA0BR0 = BAUD0; /* baud rate register */ UCA0BR1 = BAUD1; } else { UCA0BR0 = BAUD0EN; /* baud rate register */ UCA0BR1 = BAUD1EN; } } /* BaudSet */ void main(void) { // initialize peripherals WDTCTL = WDTPW + WDTHOLD; P3OUT &=~BIT0; P3DIR |= BIT0; P2OUT &=~BIT2; P3OUT &=~0x06; ledselect1; ledselect2; delay_ms(1); PARset(); //Set Port Functions for Parallel Mode InitialSettings(); // Set MCU Clock Frequency to 13.56 MHz and OOK Modulation /*Now switch from DCO to external 13.56 MHz clock*/ OSCsel(0x00); //set the oscilator EnableInterrupts; // General enable interrupts delay_ms(10); //set OOK port tristate P2.2 LOW //ENABLE = 1; //POLLING = 1; FindTags(0x00); } // === end of main ===================================================== #pragma vector=TIMERA0_VECTOR __interrupt void TimerAhandler(void) { unsigned char Register[2]; stopCounter; Register[0] = IRQStatus; /* IRQ status register address */ Register[1] = IRQMask; //Dummy read ReadCont(Register, 2); uid[0]=*Register; *Register = *Register & 0xF7; //set the parity flag to 0 if(*Register == 0x00 || *Register == 0x80) //added code i_reg = 0x00; else i_reg = 0x01; __low_power_mode_off_on_exit(); }//TimerAhandler #pragma vector = PORT2_VECTOR __interrupt void Port_B (void) /* interrupt handler */ { P3OUT ^= BIT2; stopCounter; /* stop timer mode */ do { irqCLR; /* PORT2 interrupt flag clear */ Register[0] = IRQStatus; /* IRQ status register address */ Register[1] = IRQMask; //Dummy read // ReadSingle(Register, 2); /* function call for single address read */ ReadSingle(Register, 1); /* function call for single address read */ /* IRQ status register has to be read */ if(*Register == 0xA0) { /* TX active and only 3 bytes left in FIFO */ goto FINISH; } InterruptHandlerReader(&Register[0]); } while((irqPORT & irqPIN) == irqPIN); FINISH: __low_power_mode_off_on_exit(); }