interrupt handling

Dependencies:  

interruptStuff.cpp

Committer:
rwclough
Date:
2015-03-05
Revision:
2:bd5afc5aa139
Child:
3:eaae5433ab45

File content as of revision 2:bd5afc5aa139:

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
    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()