interrupt handling

Dependencies:  

Revision:
2:bd5afc5aa139
Child:
3:eaae5433ab45
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interruptStuff.cpp	Thu Mar 05 20:16:40 2015 +0000
@@ -0,0 +1,369 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+    Filename:       interruptHandler.cpp
+    Description:    Handles interrupt from TRF7970
+    Copyright (C)   2015 Gymtrack, Inc.
+    Author:         Ron Clough
+    Date:           2015-03-03
+    
+    Changes:
+    Rev     Date        Who     Details
+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    0.0     2015-03-03  RWC     Original version.
+    
+* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include    "mbed.h"
+#include    "interruptStuff.h"
+#include    "readerComm.h"
+
+InterruptIn readerInt(p7);              // Interrupt from TRF7970
+DigitalIn   irqPin(p7, PullNone);
+extern  Serial      pc;                 // main.cpp
+
+extern  uint8_t irqRegister;    // Interrupt register (main.cpp)
+extern  uint8_t buf[300];
+extern  int16_t nfc_state;
+extern  uint8_t nfc_protocol;
+extern  uint8_t active;
+extern  int8_t  rxtxState;
+extern  uint8_t rxErrorFlag;
+extern  uint8_t tagFlag;
+extern  uint8_t irqFlag;
+
+void setupIrq(void)
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+//  setupIrq()
+//  Description:    Interrupt from TRF7970 appears at pin 7 of 
+//                  on nRF51-DK eval board. trf7970IrqHandler() is called 
+//                  when a rising edge is detected.
+//                  Interrupts are initially disabled.
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+{
+    readerInt.rise(&trf7970IrqHandler);    // Interrupt on rising edge, call trf7970IrqHandler()
+    readerInt.disable_irq();
+    
+}
+
+void readIrqStatus(uint8_t *buffer)
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+//  readIrqStatus()
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+{
+    *buffer = IRQ_STATUS;
+    *(buffer + 1) = IRQ_MASK;
+    spiReadContinuous(buffer, 2);
+}   // End of readIrqStatus()
+
+void nfcModeIrq(uint8_t *Register)
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+//  nfcModeIrq()
+//  bit0 - RF collision avoidance error
+//  bit1 - RF collision avoidance OK
+//  bit2 - Change in RF field level
+//  bit3 - SDD OK
+//  bit4 - Communication error
+//  bit5 - FIFO high/low
+//  bit6 - RX
+//  bit7 - TX
+//
+//  irqRegister is used for signaling to the protocol functions
+//  irqRegister = 0x00 - OK
+//  irqRegister = 0x01 - progress
+//  irqRegister = 0x02 - error
+//  irqRegister = 0xFF - end of RX
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+{
+    if (*Register == BIT0) {
+        irqRegister = 0x02;
+    }
+    else if (*Register == BIT1) {
+        irqRegister = 0x00;
+    }
+    else if (*Register == BIT3) {
+        irqRegister = 0x00;
+    }
+    else if ((*Register  & BIT4) == BIT4) {
+        *Register = RX_SPECIAL_SETTINGS;        // Check filter and gain
+        spiReadSingle(Register, 1);
+        stopDecoders();
+        irqRegister = 0x02;
+    }
+    else if (*Register == BIT7) {              // TX complete
+        irqRegister = 0x00;
+        trf7970Reset();
+    }
+    else if (*Register == 0x40 || *Register == 0x44) {  // RX flag means that EOF has been received and
+                                                        // the number of unread bytes is in FIFOstatus register
+        *Register = RX_SPECIAL_SETTINGS;                // Check filter and gain
+        spiReadSingle(Register, 1);
+        *Register = FIFO_CONTROL;
+        spiReadSingle(Register, 1);
+        *Register = 0x7F & *Register;
+        buf[nfc_state] = FIFO;                          // Write the received bytes to the correct place in the buffer
+        spiReadContinuous(&buf[nfc_state], *Register);
+        nfc_state = nfc_state + *Register;
+        trf7970Reset();                                 // Reset the FIFO after last byte has been read out
+        irqRegister = 0xFF;                             // Signal to the receive function that these are the last bytes
+        resetIrqStatus();
+    }
+    else if ((*Register == 0x60) || (*Register == 0x64)) {  // RX and FIFO interrupt
+        irqRegister = 0x01;
+    }
+    else if (*Register == 0x48) {                       // SDD complete
+        irqRegister = 0x00;
+    }
+}   // End of nfcModeIrq()
+
+void targetIrq(uint8_t *Register)
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+//  targetIrq()
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+{
+    uint8_t command, i;
+    
+    if (*Register == 0x48) {
+        TargetProtocol:
+        // Determine the NFC target protocol
+        command = NFC_TARGET_PROTOCOL;
+        spiReadSingle(&command, 1);         //read the NFCtargetprotocol register
+        command &= 0x3F;
+        buf[50] = ISO_CONTROL;
+        if (command == 0x09) {
+            nfc_protocol = 0x01;
+            *Register = FIFO_CONTROL;
+            spiReadSingle(Register, 1);     // Determine the number of bytes left in FIFO
+            *Register = 0x7F & *Register;
+            buf[nfc_state] = FIFO;          // Write the received bytes to the correct place in the buffer
+            spiReadContinuous(&buf[nfc_state], *Register);
+            nfc_state = nfc_state + *Register;
+            irqRegister = 0xFF;
+        }
+        else {
+            *Register = FIFO_CONTROL;
+            spiReadSingle(Register, 1);     // Determine the number of bytes left in FIFO
+            *Register = 0x7F & *Register;
+            buf[nfc_state] = FIFO;          // Write the received bytes to the correct place in the buffer
+            spiReadContinuous(&buf[nfc_state], *Register);
+            nfc_state = nfc_state + *Register;
+            irqRegister = 0xFF;
+            if ((command == 0x01)) {         // 14443A - active
+                buf[51] = NFC106AC;
+                spiWriteSingle(&buf[50], 2);
+                nfc_protocol = 0x02;
+                active = 0xFF;
+            }
+            else if (command == 0x05) {     // 14443B - tag emulation
+                buf[51] = TAG14443B;
+                spiWriteSingle(&buf[50], 2);
+                nfc_protocol = 0x07;
+                active = 0x00;
+            }
+            else if (command == 0x12) {
+                if(buf[1] == 0x06) {        // Felica 212 - passive
+                    buf[51] = NFC212PA;
+                    spiWriteSingle(&buf[50], 2);
+                    nfc_protocol = 0x03;
+                    active = 0x00;
+                }
+                else {                          // Felica 212 - active
+                    buf[51] = NFC212AC;
+                    spiWriteSingle(&buf[50], 2);
+                    nfc_protocol = 0x04;
+                    active = 0xFF;
+                }
+            } // if (command == 0x12)
+            else if (command == 0x13) {
+                if(buf[1] == 0x06) {            //Felica 424 - passive
+                    buf[51] = NFC424PA;
+                    spiWriteSingle(&buf[50], 2);
+                    nfc_protocol = 0x05;
+                    active = 0x00;
+                }
+                else {                          // Felica 424 - active
+                    buf[51] = NFC424AC;
+                    spiWriteSingle(&buf[50], 2);
+                    nfc_protocol = 0x06;
+                    active = 0xFF;
+                } // if (buf[1] == 0x06)
+            } // if (command == 0x13)
+        } // if (command == 0x09)
+    } // if (*Register == 0x48)
+    else if (*Register == 0x60) {
+        irqRegister = 0x01;
+        buf[nfc_state] = FIFO;
+        spiReadContinuous(&buf[nfc_state], FIFO_MORE);  // Read FIFO_MORE bytes from FIFO
+        nfc_state = nfc_state + FIFO_MORE;
+        resetIrqStatus();
+    }
+    else if ((*Register & BIT3) == BIT3) {     // SDD finished
+        irqRegister = 0xFF;
+        for(i = 0; i < 255; i++);
+        nfc_protocol = 0x01;
+        trf7970Reset();
+        stopDecoders();
+        runDecoders();
+    }
+    else if (*Register == 0x44) {
+        readIrqStatus(Register);
+        if (*Register == 0x40) {
+            goto TargetProtocol;
+        }
+        else if (*Register == 0x00) {
+            goto RFfieldChange;
+        }
+    }
+    else if (*Register == BIT2) {                       // RF field change
+        RFfieldChange:
+        trf7970Reset();
+        stopDecoders();
+        runDecoders();
+    }
+    resetIrqStatus();
+}   // End of targetIrq()
+
+void howToHandleTrf7970Irq(uint8_t *irq_status)
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+//  howToHandleTrf7970Irq()
+//  Description:    The Interrupt Handler determines how the IRQ should
+//                  be handled. The Trf797x IRQ status register is read
+//                  to determine the cause of the IRQ.
+//                  Conditions are checked and appropriate actions taken. 
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+{
+    printf("*irq_status: %X\r\n", *irq_status);
+    
+    if (*irq_status == 0xA0) {               // BIT5 and BIT7, TX active and only 3 bytes left in FIFO
+        irqRegister = 0x00;
+    }
+    else if (*irq_status == BIT7) {          // TX complete
+        irqRegister = 0x00;
+        trf7970Reset();                      // Reset the FIFO after TX
+    }
+    else if ((*irq_status & BIT1) == BIT1) { // Collision error
+        irqRegister = 0x02;                  // RX complete
+        stopDecoders();
+        trf7970Reset();
+        resetIrqStatus();
+    }
+    else if (*irq_status == BIT6) {         // RX flag means that EOF has been received
+                                            // and the number of unread bytes is in FIFOstatus register
+        if (rxErrorFlag == 0x02) {
+            irqRegister = 0x02;
+            return;
+        }
+        *irq_status = FIFO_CONTROL;
+        spiReadSingle(irq_status, 1);       // Determine the number of bytes left in FIFO
+        *irq_status = 0x7F & *irq_status;
+        buf[rxtxState] = FIFO;              // Write the received bytes to the correct place in the buffer
+        spiReadContinuous(&buf[rxtxState], *irq_status);
+        rxtxState = rxtxState + *irq_status;
+        trf7970Reset();                     // Reset the FIFO after last byte has been read out
+        irqRegister = 0xFF;                 // Signal to the receive funnction that thiese are the last bytes
+    }
+    else if (*irq_status == 0x60) {         // RX active and 9 bytes already in FIFO
+        irqRegister = 0x01;
+        buf[rxtxState] = FIFO;
+        spiReadContinuous(&buf[rxtxState], 86); // Read 86 bytes from FIFO
+        rxtxState = rxtxState + 86;
+        if (irqPin) {                           // If IRQ pin high
+            readIrqStatus(irq_status);
+            // IRQ_CLR ???
+            if (*irq_status == 0x40) {                          // End of recieve
+                *irq_status = FIFO_CONTROL;
+                spiReadSingle(irq_status, 1);                   // Determine the number of bytes left in FIFO
+                *irq_status = 0x7F & *irq_status;
+                buf[rxtxState] = FIFO;                          // Write the received bytes to the correct place in the buffer
+                spiReadContinuous(&buf[rxtxState], *irq_status);
+                rxtxState = rxtxState + *irq_status;
+                irqRegister = 0xFF;                             // Signal to the receive funnction that these are the last bytes
+                trf7970Reset();                                 // Reset the FIFO after last byte has been read out
+            }
+            else if(*irq_status == 0x50) {                      // End of receive and error
+                irqRegister = 0x02;
+            }
+        }
+        else {
+            readIrqStatus(irq_status);
+            if(irq_status[0] == 0x00) {
+                irqRegister = 0xFF;
+            }
+        }
+    }
+    else if ((*irq_status & BIT4) == BIT4) {    // CRC error
+        if ((*irq_status & BIT5) == BIT5) {   
+            irqRegister = 0x01;                 // RX active
+            rxErrorFlag = 0x02;
+        }
+        if ((*irq_status & BIT6) == BIT6) {     // 4 Bit receive
+            buf[200] = FIFO;                    // Write the received bytes to the correct place in the buffer
+            spiReadContinuous(&buf[200], 1);
+            trf7970Reset();
+            irqRegister = 0x02;                 // End of RX
+            rxErrorFlag = 0x02;
+        }
+        else
+        {
+            irqRegister = 0x02;                 // End of RX
+        }
+    }
+    else if ((*irq_status & BIT2) == BIT2) {   // Byte framing error
+        if ((*irq_status & BIT5) == BIT5) {
+            irqRegister = 0x01;                 // RX active
+            rxErrorFlag = 0x02;
+        }
+        else
+            irqRegister = 0x02;                 // End of RX
+    }
+    else if ((*irq_status == BIT0)) {           // No response interrupt
+        irqRegister = 0x00;
+    }
+    else {                                      // Interrupt register not properly set
+        printf ("Interrupt Error\r\n");
+
+        irqRegister = 0x02;
+        stopDecoders();                         // Reset the FIFO after TX
+        trf7970Reset();
+        resetIrqStatus();
+        // IRQ_CLR; ???
+    }
+}   // End of howToHandleTrf7970Irq()
+
+void trf7970IrqHandler(void)
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+//  trf7970IrqHandler()
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+{
+    uint8_t    irqStatus[2], iso_control;
+
+    irqFlag = 0x02;
+    do {
+        //  Do I need to clear interrupt flag here?
+        iso_control = ISO_CONTROL;
+        spiReadSingle(&iso_control, 1);
+        readIrqStatus(irqStatus);
+        
+        printf("IRQ status: %X %X\r\n", irqStatus[0], irqStatus[1]);
+        
+        if (*irqStatus == 0xA0) {                   // TX active and only 3 bytes left in FIFO
+            break;
+        }
+        
+        if ((iso_control & BIT5) != BIT5) {         // RFID mode
+            howToHandleTrf7970Irq(irqStatus);
+        }
+        else {                                      // NFC mode
+            if ((iso_control & BIT2) == BIT2) {     // Tag emulation
+                tagFlag = 1;
+                nfcModeIrq(irqStatus);
+            }
+            else {
+                if ((iso_control & BIT4) == BIT4) { // Active mode
+                    nfcModeIrq(irqStatus);
+                }
+                else {                              // Passive mode
+                    targetIrq(irqStatus);
+                }
+            }
+        }
+    } while(irqPin);    // While IRQ pin is high **********
+}   // End of trf7970IrqHandler()