interrupt handling
readerComm.cpp
- Committer:
- rwclough
- Date:
- 2015-03-05
- Revision:
- 2:bd5afc5aa139
- Parent:
- 1:1eb96189824d
- Child:
- 3:eaae5433ab45
File content as of revision 2:bd5afc5aa139:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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. Copyright (C) 2015 Gymtrack, Inc. Author: Ron Clough Date: 2015-02-27 Changes: Rev Date Who Details ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 0.0 2015-02-27 RWC Original version. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "mbed.h" #include "readerComm.h" #include "main.h" 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) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // initialSettings() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { uint8_t mod_control[2]; mod_control[0] = SOFT_INIT; spiDirectCommand(mod_control); mod_control[0] = IDLE; spiDirectCommand(mod_control); mod_control[0] = MODULATOR_CONTROL; mod_control[1] = 0x21; // 6.78 MHz, OOK 100% spiWriteSingle(mod_control, 2); mod_control[0] = MODULATOR_CONTROL; spiReadSingle(mod_control, 1); } // End of initialSettings() 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 CS = SELECT; spi.write(*buffer); CS = DESELECT; } // End of directCommand() void spiWriteSingle(uint8_t *buffer, uint8_t length) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // spiWriteSingle() // Description: Writes to specified reader registers. // Parameters: *buffer = addresses of the registers followed by the // contents to write. // length = number of registers * 2. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { uint8_t i=0; CS = SELECT; while(length > 0) { *buffer = (0x1F & *buffer); // Register address for(i = 0; i < 2; i++) { spi.write(*buffer); temp = spi.write(0x00); buffer++; length--; } } CS = DESELECT; } // End of spiWriteSingle() void spiReadSingle(uint8_t *buffer, uint8_t number) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // spiReadSingle() // Description: Reads specified reader chip registers and // writes register contents to *buffer. // Parameters: *buffer = addresses of the registers. // number = number of registers. // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { CS = SELECT; while(number > 0) { *buffer = (0x40 | *buffer); // Address, read, single *buffer = (0x5F & *buffer); // Register address temp = spi.write(*buffer); // *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 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 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() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { uint8_t cmd[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) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // turnRfOff() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { uint8_t cmd[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(uint8_t iso_control) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // writeIsoControl() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { uint8_t write[4]; if ((iso_control & BIT5) == BIT5) { printf("iso_control bit5 != 0\r\n"); return; } write[0] = ISO_CONTROL; write[1] = iso_control; 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) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 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) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 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; // 0x06 buf[20] = 0x00; Iso15693Anticollision(&buf[20], 0x00); // Send Inventory request turnRfOff(); resetIrqStatus(); // Clear any IRQs } // End of iso15693FindTag() 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()