interrupt handling
Diff: readerComm.cpp
- Revision:
- 2:bd5afc5aa139
- Parent:
- 1:1eb96189824d
- Child:
- 3:eaae5433ab45
--- a/readerComm.cpp Mon Mar 02 19:50:31 2015 +0000 +++ b/readerComm.cpp Thu Mar 05 20:16:40 2015 +0000 @@ -1,5 +1,5 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - Filename: readerComm.c + Filename: readerComm.cpp Description: Functions used to communicate with the TRF7970 eval bd. Communication is by means of an SPI interface between the nRF51-DK board (nRF51422 MCU) and the TRF7970 eval bd. @@ -10,170 +10,448 @@ Changes: Rev Date Who Details ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 0.0 2015-02-2 RWC Original version. + 0.0 2015-02-27 RWC Original version. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "mbed.h" #include "readerComm.h" - -extern SPI spi; // main.cpp -extern DigitalOut CS; // main.cpp +#include "main.h" -void firstComm(void) { +uint8_t afi = 0; +uint8_t flags = 0; // Stores the mask value (used in anticollision) +uint8_t command[2]; +uint8_t temp; +extern DigitalOut ISO15693LED; // ISO15693 LED +extern SPI spi; // main.cpp +extern Serial pc; // main.cpp +extern DigitalOut CS; // main.cpp +extern InterruptIn readerInt; // main.cpp +extern int8_t rxtxState; // Transmit/Receive byte count (main.cpp) +extern uint8_t buf[300]; // main.cpp +extern uint8_t irqRegister; // Interrupt register (main.cpp) +extern uint8_t irqFlag; // main.cpp +extern uint8_t rxErrorFlag; // main.cpp +extern uint8_t readerMode; // Determines how interrupts will be handled (main.cpp) +extern uint8_t buffer[2]; + +void initialSettings(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// firstComm() +// initialSettings() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - int mod_control[2]; +{ + uint8_t mod_control[2]; mod_control[0] = SOFT_INIT; - directCommand(mod_control); + spiDirectCommand(mod_control); mod_control[0] = IDLE; - directCommand(mod_control); + spiDirectCommand(mod_control); mod_control[0] = MODULATOR_CONTROL; - mod_control[1] = 0x21; - writeSingle(mod_control, 2); + mod_control[1] = 0x21; // 6.78 MHz, OOK 100% + spiWriteSingle(mod_control, 2); mod_control[0] = MODULATOR_CONTROL; - readSingle(mod_control, 1); -} // End of firstComm() + spiReadSingle(mod_control, 1); +} // End of initialSettings() -void directCommand(int *buffer) { +void spiDirectCommand(uint8_t *buffer) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // directCommand() // Description: Transmit a Direct Command to the reader chip. // Parameter: *buffer = the direct command. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ *buffer = (0x80 | *buffer); // Setup command mode - *buffer = (0x9f & *buffer); // Setup command mode + *buffer = (0x9F & *buffer); // Setup command mode CS = SELECT; spi.write(*buffer); CS = DESELECT; } // End of directCommand() -void writeSingle(int *buffer, int length) { +void spiWriteSingle(uint8_t *buffer, uint8_t length) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// writeSingle() +// spiWriteSingle() // Description: Writes to specified reader registers. // Parameters: *buffer = addresses of the registers followed by the -// contends to write. +// contents to write. // length = number of registers * 2. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - int i=0; +{ + uint8_t i=0; CS = SELECT; while(length > 0) { - *buffer = (0x1f & *buffer); // Register address + *buffer = (0x1F & *buffer); // Register address for(i = 0; i < 2; i++) { spi.write(*buffer); + temp = spi.write(0x00); buffer++; length--; - } // if - } // while + } + } CS = DESELECT; -} // End of writeSingle() +} // End of spiWriteSingle() -void readSingle(int *buffer, int number) { +void spiReadSingle(uint8_t *buffer, uint8_t number) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -// readSingle() +// spiReadSingle() // Description: Reads specified reader chip registers and // writes register contents to *buffer. // Parameters: *buffer = addresses of the registers. // number = number of registers. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - int temp; - +{ CS = SELECT; while(number > 0) { *buffer = (0x40 | *buffer); // Address, read, single - *buffer = (0x5f & *buffer); // Register address + *buffer = (0x5F & *buffer); // Register address temp = spi.write(*buffer); - *buffer = spi.write(0x00); +// *buffer = spi.write(*buffer); +// temp = spi.write(0x00); // dummy read + *buffer = spi.write(0x00); // *buffer <- register contents buffer++; number--; + } + CS = DESELECT; +} // End of spiReadSingle() + +void spiReadContinuous(uint8_t *buffer, uint8_t length) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// spiReadContinuous() +// Description: Used in SPI mode to read a specified number of +// reader chip registers from a specified address upwards. +// Contents of the registers are stored in *buffer. +// Parameters: *buffer = address of first register. +// length = number of registers to read. +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + CS = SELECT; + *buffer = (0x60 | *buffer); // Address, read, continuous + *buffer = (0x7f & *buffer); // Register address + spi.write(*buffer); + temp = spi.write(0x00); + while(length > 0) { + spi.write(0x00); + *buffer = spi.write(0x00); + buffer++; + length--; } // while CS = DESELECT; -} // End of readSingle() +} // End of spiReadContinuous() + +void spiRawWrite(uint8_t *buffer, uint8_t length) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// rawWrite() +// Description: Used in SPI mode to write direct to the reader chip. +// Parameters: *buffer = raw data +// length = number of data bytes +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + CS = SELECT; + while(length > 0) { + temp = spi.write(*buffer); + buffer++; + length--; + } + CS = DESELECT; +} // End of spiRawWrite() + +void stopDecoders(void) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// stopDecoders() +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + command[0] = STOP_DECODERS; + spiDirectCommand(command); +} -void turnRfOn(void) { +void runDecoders(void) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// runDecoders() +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + command[0] = RUN_DECODERS; + spiDirectCommand(command); +} + +void txNextSlot(void) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// txNextSlot() +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + command[0] = TRANSMIT_NEXT_SLOT; + spiDirectCommand(command); +} + +void disableSlotCounter(void) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// disableSlotCounter() +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + buf[40] = IRQ_MASK; + buf[41] = IRQ_MASK; + spiReadSingle(&buf[41], 1); + buf[41] &= 0xFE; + spiWriteSingle(&buf[40], 2); +} + +void trf7970Reset(void) +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +// trf7970Reset() +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + command[0] = RESET; + spiDirectCommand(command); +} + +void turnRfOn(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // turnRfOn() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - int command[2]; +{ + uint8_t cmd[2]; - command[0] = CHIP_STATUS_CONTROL; - command[1] = CHIP_STATUS_CONTROL; - readSingle(&command[1], 1); - command[1] &= 0x3F; - command[1] |= 0x20; - writeSingle(command, 2); + cmd[0] = CHIP_STATUS_CONTROL; + cmd[1] = CHIP_STATUS_CONTROL; + spiReadSingle(&cmd[1], 1); + cmd[1] &= 0x3F; + cmd[1] |= 0x20; + spiWriteSingle(cmd, 2); + +// wait_ms(100); +// spiReadSingle(cmd, 1); +// printf("Cmd[0]: 0x%X\r\n", cmd[0]); +// printf("Cmd[1]: 0x%X\r\n", cmd[1]); + } // End of turnRfOn() -void turnRfOff(void) { +void turnRfOff(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // turnRfOff() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - int command[2]; +{ + uint8_t cmd[2]; - command[0] = CHIP_STATUS_CONTROL; - command[1] = CHIP_STATUS_CONTROL; - readSingle(&command[1], 1); - command[1] &= 0x1F; - writeSingle(command, 2); + cmd[0] = CHIP_STATUS_CONTROL; + cmd[1] = CHIP_STATUS_CONTROL; + spiReadSingle(&cmd[1], 1); + cmd[1] &= 0x1F; + spiWriteSingle(cmd, 2); } // End of turnRfOff() -void writeIsoControl(int iso_control) { +void writeIsoControl(uint8_t iso_control) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // writeIsoControl() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - int write[4]; +{ + uint8_t write[4]; -// if((iso_control & BIT5) == BIT5) -// { -// return; -// } + if ((iso_control & BIT5) == BIT5) { + printf("iso_control bit5 != 0\r\n"); + return; + } write[0] = ISO_CONTROL; write[1] = iso_control; -// write[1] &= ~BIT5; - writeSingle(write, 2); + write[1] &= ~BIT5; + spiWriteSingle(write, 2); + +// wait_ms(100); +// spiReadSingle(write, 1); +// printf("Reg[0]: 0x%X\r\n", write[0]); +// printf("Reg[1]: 0x%X\r\n", write[1]); iso_control &= 0x1F; } // End of writeIsoControl() -void resetIrqStatus(void) { +void resetIrqStatus(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // resetIrqStatus() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - +{ + uint8_t irq_status[4]; + + irq_status[0] = IRQ_STATUS; + irq_status[1] = IRQ_MASK; + + spiReadContinuous(irq_status, 2); // Read second register as dummy read } -void iso15693FindTag(void) { +void iso15693FindTag(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // iso15693FindTag() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ turnRfOn(); - writeIsoControl(0x02); - // The VCD should wait at least 1 ms after it activated the // powering field before sending the first request, to // ensure that the VICCs are ready to receive it. (ISO15693-3) wait_ms(6); - -// flags = SIXTEEN_SLOTS; -// flags = ONE_SLOT; - -// buf[20] = 0x00; -// Iso15693Anticollision(&buf[20], 0x00); // Send Inventory request - + flags = SIXTEEN_SLOTS; // 0x06 + buf[20] = 0x00; + Iso15693Anticollision(&buf[20], 0x00); // Send Inventory request turnRfOff(); - resetIrqStatus(); // Clear any IRQs } // End of iso15693FindTag() -void Iso15693Anticollision(int *mask, int length) { +void Iso15693Anticollision(uint8_t *mask, uint8_t length) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // Iso15693Anticollision() +// Description: Used to perform an inventory cycle of 1 or 16 timeslots. +// Send command, receive response and send response to host. +// Parameters: *mask = mask value +// length = number of significant bits of mask value // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +{ + uint8_t i = 1, j = 1, command[2], no_slots, found = 0; + uint8_t *p_slot_no, slot_no[17]; + uint8_t new_mask[8], new_length, mask_size; + uint32_t size; + uint8_t fifo_length = 0; + uint16_t k; + + slot_no[0] = 0x00; + if ((flags & BIT5) == 0x00) { // flag bit5 is the number of slots indicator + no_slots = 16; // 16 slots if bit5 is cleared + } + else { + no_slots = 1; // 1 slot if bit5 is set + } + + p_slot_no = &slot_no[0]; // slot number pointer + mask_size = (((length >> 2) + 1) >> 1); // mask_size is 1 for length = 4 or 8 + buf[0] = 0x8F; // RESET + buf[1] = 0x91; // send with CRC + buf[2] = 0x3D; // write continuous from 1D + buf[5] = flags; // ISO15693 flags + buf[6] = 0x01; // anticollision command code + + if (flags & 0x10) { // mask_size is 2 for length = 12 or 16 and so on + size = mask_size + 4; // mask value + mask length + afi + command code + flags + buf[7] = afi; + buf[8] = length; // mask length + if (length > 0) { + for(i = 0; i < mask_size; i++) { + buf[9 + i] = *(mask + i); + } + } + fifo_length = 9; + } + else { // mask_size is 2 for length = 12 or 16 and so on + size = mask_size + 3; // mask value + mask length + command code + flags + buf[7] = length; // mask length + if(length > 0) { + for(i = 0; i < mask_size; i++) { + buf[8 + i] = *(mask + i); + } + } + fifo_length = 8; + } + + buf[3] = (char) (size >> 8); + buf[4] = (char) (size << 4); + + resetIrqStatus(); + + spiRawWrite(&buf[0], mask_size + fifo_length); // Write to FIFO + irqRegister = 0x01; + irqFlag = 0x00; + readerInt.enable_irq(); + + printf("Anticollision 1 \r\n"); wait_ms(100); + + while(irqFlag == 0x00); // Wait for end-of-TX interrupt + + printf("Anticollision 2 \r\n"); wait_ms(100); + for (j=1; j <= no_slots; j++) { // 1 or 16 available timeslots + rxtxState = 1; + irqFlag = 0x00; + while(irqFlag == 0x00); // Wait for interrupt + while(irqRegister == 0x01) { // Wait for RX complete + k++; + if (k == 0xFFF0) { + irqRegister = 0x00; + rxErrorFlag = 0x00; + } + } // while + command[0] = RSSI_LEVELS; // Read RSSI levels + spiReadSingle(command, 1); + switch (irqRegister) { + case 0xFF: // If received UID in buffer + printf("ISO15693: [ "); + for (i=3; i < 11; i++) { + printf("%c", buf[i]); + } + printf(", %d ]\r\n", command[0]); + break; + + case 0x02: // Collision occurred + p_slot_no++; // Remember a collision was detected + *p_slot_no = j; + break; + + case 0x00: // Timer interrupt + break; + + default: + break; + } // switch + + command[0] = RESET; // FIFO must be reset before receiving the next response + spiDirectCommand(command); + + if ((no_slots == 16) && (j < 16)) { // If 16 slots used then send EOF (next slot) + stopDecoders(); + runDecoders(); + txNextSlot(); + } + else if ((no_slots == 16) && (j == 16)) { // At end of slot 16, stop the slot counter + stopDecoders(); + disableSlotCounter(); + } + else if (no_slots == 1) { // 1 slot is uesd + break; + } + } // for + + if (found == 1) { + ISO15693LED = LED_ON; + printf("Found ISO15693 tag\r\n"); + } + else { + ISO15693LED = LED_OFF; + } + + new_length = length + 4; // The mask length is a multiple of 4 bits + mask_size = (((new_length >> 2) + 1) >> 1); + while ((*p_slot_no != 0x00) && (no_slots == 16) && (new_length < 61) && (slot_no[16] != 16)) { + *p_slot_no = *p_slot_no - 1; + + for(i = 0; i < 8; i++) + { + new_mask[i] = *(mask + i); // First the whole mask is copied + } + + if((new_length & BIT2) == 0x00) + { + *p_slot_no = *p_slot_no << 4; + } + else + { + for(i = 7; i > 0; i--) + { + new_mask[i] = new_mask[i - 1]; + } + new_mask[0] &= 0x00; + } + new_mask[0] |= *p_slot_no; // The mask is changed + wait_ms(2); + + Iso15693Anticollision(&new_mask[0], new_length); // Recursive call with new Mask + + p_slot_no--; + } + + readerInt.disable_irq(); } // End of Iso15693Anticollision()