interrupt handling
readerComm.cpp
- Committer:
- rwclough
- Date:
- 2015-03-20
- Revision:
- 4:9ab0d84bbd07
- Parent:
- 3:eaae5433ab45
- Child:
- 5:93c612f43ec2
File content as of revision 4:9ab0d84bbd07:
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 "interruptStuff.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 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) volatile 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]; extern uint8_t tagFlag; extern DigitalIn irqPin; extern DigitalOut debug1LED; extern DigitalOut debug2LED; extern DigitalOut ISO15693LED; extern DigitalOut heartbeatLED; extern DigitalOut testPin; extern uint8_t debugBuffer[1000]; // Capture data for analysis extern uint8_t bufIdx; void trf797xInitialSettings(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xInitialSettings() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { uint8_t mod_control[2]; mod_control[0] = SOFT_INIT; trf797xDirectCommand(mod_control); mod_control[0] = IDLE; trf797xDirectCommand(mod_control); mod_control[0] = MODULATOR_CONTROL; mod_control[1] = 0x21; // 6.78 MHz, OOK 100% trf797xWriteSingle(mod_control, 2); mod_control[0] = MODULATOR_CONTROL; trf797xReadSingle(mod_control, 1); // printf("\r\nMOD: 0x%02X 0x%02X\r\n", mod_control[0], mod_control[1]); /* mod_control[0] = CHIP_STATUS_CONTROL; mod_control[1] = 0x01; trf797xWriteSingle(mod_control, 2); mod_control[0] = CHIP_STATUS_CONTROL; trf797xReadSingle(mod_control, 1); printf("CHIP: 0x%02X 0x%02X\r\n", mod_control[0], mod_control[1]); mod_control[0] = ISO_CONTROL; mod_control[1] = 0x02; trf797xWriteSingle(mod_control, 2); mod_control[0] = ISO_CONTROL; mod_control[1] = ISO_CONTROL; trf797xReadSingle(mod_control, 1); printf("ISO: 0x%02X 0x%02X\r\n", mod_control[0], mod_control[1]); mod_control[0] = RX_SPECIAL_SETTINGS; mod_control[1] = 0x40; trf797xWriteSingle(mod_control, 2); mod_control[0] = RX_SPECIAL_SETTINGS; mod_control[1] = RX_SPECIAL_SETTINGS; trf797xReadSingle(mod_control, 1); printf("RX: 0x%02X 0x%02X\r\n", mod_control[0], mod_control[1]); */ /* command[0] = CHIP_STATUS_CONTROL; command[1] = CHIP_STATUS_CONTROL; command[1] = 0x01; // Set bit 0 => Vin = 5V trf797xWriteSingle(command, 2); command[0] = CHIP_STATUS_CONTROL; command[1] = CHIP_STATUS_CONTROL; trf797xReadSingle(command, 1); printf("CHIP 0x%02X 0x%02X\r\n", command[0], command[1]); */ } // End of trf797xInitialSettings() void trf797xDirectCommand(uint8_t *buffer) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xDirectCommand() // 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 trf797xDirectCommand() void trf797xWriteSingle(uint8_t *buffer, uint8_t length) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xWriteSingle() // 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); buffer++; length--; } } CS = DESELECT; } // End of trf797xWriteSingle() void trf797xReadSingle(uint8_t *buffer, uint8_t number) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xReadSingle() // 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 spi.write(*buffer); *buffer = spi.write(0x00); // *buffer <- register contents buffer++; number--; } CS = DESELECT; } // End of trf797xReadSingle() void trf797xReadContinuous(uint8_t *buffer, uint8_t length) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xReadContinuous() // 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. // 1) Read register(s) // 2) Write contents to *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); while(length > 0) { *buffer = spi.write(0x00); buffer++; length--; } // spi.write(0x00); spi.write(0x00); // 16 clock cycles, see TRF7970A FW Design Hints SLOA159 section 7.3 CS = DESELECT; } // End of trf797xReadContinuous() void trf797xRawWrite(uint8_t *buffer, uint8_t length) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xRawWrite() // 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 trf797xRawWrite() void trf797xStopDecoders(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xStopDecoders() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { command[0] = STOP_DECODERS; trf797xDirectCommand(command); } void trf797xRunDecoders(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xRunDecoders() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { command[0] = RUN_DECODERS; trf797xDirectCommand(command); } void trf797xTxNextSlot(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xTxNextSlot() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { command[0] = TRANSMIT_NEXT_SLOT; trf797xDirectCommand(command); } void trf797xDisableSlotCounter(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xDisableSlotCounter() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { buf[40] = IRQ_MASK; buf[41] = IRQ_MASK; trf797xReadSingle(&buf[41], 1); buf[41] &= 0xFE; trf797xWriteSingle(&buf[40], 2); } void trf797xReset(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xReset() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { command[0] = RESET; trf797xDirectCommand(command); } void trf797xTurnRfOn(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xTurnRfOn() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { command[0] = CHIP_STATUS_CONTROL; command[1] = CHIP_STATUS_CONTROL; trf797xReadSingle(&command[1], 1); command[1] &= 0x3F; command[1] |= 0x21; // Oroiginal code has 0x20 !!! // printf("\r\nCHIP 0x%02X 0x%02X\r\n", command[0], command[1]); trf797xWriteSingle(command, 2); // printf("\r\nCHIP 0x%02X 0x%02X\r\n", command[0], command[1]); } // End of trf797xTurnRfOn() void trf797xTurnRfOff(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xTurnRfOff() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { command[0] = CHIP_STATUS_CONTROL; command[1] = CHIP_STATUS_CONTROL; trf797xReadSingle(&command[1], 1); command[1] &= 0x1F; trf797xWriteSingle(command, 2); } // End of trf797xTurnRfOff() void trf797xWriteIsoControl(uint8_t iso_control) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // trf797xWriteIsoControl() // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { 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; trf797xWriteSingle(write, 2); iso_control &= 0x1F; } // End of trf797xWriteIsoControl() void iso15693FindTag(void) // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // iso15693FindTag() // Description: Used to detect ISO15693 conforming tags. // If an ISO15693 conforming tag is found ISO15693LED is turned ON. // 1) Turn RF ON // 2) Perform a complete anticollision sequence // 3) Turn RF OFF // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * { trf797xTurnRfOn(); trf797xWriteIsoControl(0x02); wait_ms(6); // 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) /* // Field Level Test: buffer[0] = RUN_DECODERS; // Enable receiver trf797xDirectCommand(buffer); buffer[0] = CHIP_STATUS_CONTROL; buffer[1] = 0x23; trf797xWriteSingle(buffer, 2); wait_ms(1); buffer[0] = CHECK_INTERNAL_RF; trf797xDirectCommand(buffer); buffer[0] = RSSI_LEVELS; trf797xReadSingle(buffer, 1); printf("RSSI: 0x%X\r\n", buffer[0]); // Result: RSSI = 0x5C (Range is 0x40 to 0x7F) */ flags = SIXTEEN_SLOTS; // SIXTEEN_SLOTS = 0x06 // flags = ONE_SLOT; // ONE_SLOT = 0x26 buf[20] = 0x00; iso15693Anticollision(&buf[20], 0x00); // Send Inventory request trf797xTurnRfOff(); trf797xResetIrqStatus(); // 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 = 0; // uint8_t irqStatus[2], iso_control; slot_no[0] = 0x00; if ((flags & BIT5) == 0x00) { // flags<5> is the number of slots indicator no_slots = 16; // 16 slots if flags<5> is cleared } else { no_slots = 1; // 1 slot if flags<5> 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); trf797xResetIrqStatus(); // ***** Original code sets up a 30 ms counter here ***** // ***** Original code enables IRQ here ***** // ***** nRF51422 clear IRQ register ***** readerInt.enable_irq(); trf797xRawWrite(&buf[0], mask_size + fifo_length); // Write to FIFO irqRegister = 0x01; irqFlag = 0x00; // ***** Original code starts the counter here ***** // Wait for end-of-TX interrupt: // IRQ_STATUS<7> set at start of TX, but // IRQ pin doesn't go high until TX ends. while(irqFlag == 0x00) {}; // ***** Original code stops the counter here ***** // Begin: This code used to be in interruptStuff.cpp/trf7970IrqHandler() /* do { iso_control = ISO_CONTROL; trf797xReadSingle(&iso_control, 1); trf797xReadIrqStatus(irqStatus); // debugBuffer[bufIdx] = irqStatus[1]; // bufIdx++; // heartbeatLED = !heartbeatLED; if (*irqStatus == 0xA0) { // TX active and only 3 bytes left in FIFO break; } if ((iso_control & BIT5) != BIT5) { // RFID mode trf797xISR(irqStatus); } else { // NFC mode if ((iso_control & BIT2) == BIT2) { // Tag emulation tagFlag = 1; trf797xNfcModeIsr(irqStatus); } else { if ((iso_control & BIT4) == BIT4) { // Active mode trf797xNfcModeIsr(irqStatus); } else { // Passive mode trf797xTargetIsr(irqStatus); } } } } while(irqPin); // While IRQ pin is high ********** */ // ISO15693LED = !ISO15693LED; // End: This code used to be in interruptStuff.cpp/trf7970IrqHandler() for (j = 1; j <= no_slots; j++) { // 1 or 16 available timeslots rxtxState = 1; // ***** Original code sets up a 20 ms counter and starts it here ***** irqFlag = 0x00; while(irqFlag == 0x00); // Wait for interrupt // ***** Original code stops the counter here ***** while(irqRegister == 0x01) { // Wait for RX complete k++; if (k == 0xFFF0) { irqRegister = 0x00; rxErrorFlag = 0x00; } } command[0] = RSSI_LEVELS; // Read RSSI levels trf797xReadSingle(command, 1); switch (irqRegister) { case 0xFF: // If received UID in buffer found = 1; printf("\r\nISO15693: [ "); 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 // ***** Original code does nothing! ***** break; default: // ***** Original code does nothing ***** break; } // switch (irqRegister) command[0] = RESET; // FIFO must be reset before receiving the next response trf797xDirectCommand(command); if ((no_slots == 16) && (j < 16)) { // If 16 slots used then send EOF (next slot) trf797xStopDecoders(); trf797xRunDecoders(); command[0] = RESET; // new trf797xDirectCommand(command); // new trf797xTxNextSlot(); // RESET must precede txNextSlot, see "TRF7970A FW Design Hints SLOA159. } else if ((no_slots == 16) && (j == 16)) { // At end of slot 16, stop the slot counter trf797xStopDecoders(); trf797xDisableSlotCounter(); } else if (no_slots == 1) { // 1 slot is used break; } } // for (j = 1; j <= no_slots; j++) if (found == 1) { ISO15693LED = LED_ON; } 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); printf("Idx: 0x%02X Buf: 0x%02X, ", bufIdx, debugBuffer[bufIdx-1]); iso15693Anticollision(&new_mask[0], new_length); // Recursive call with new Mask p_slot_no--; } // ***** Original code disables IRQ here ***** //readerInt.disable_irq(); } // End of iso15693Anticollision()