My attempts at getting the nRF8001 chip to play with the mbed

Dependencies:   Parallax_X-Band mbed

main.cpp

Committer:
ottaviano3
Date:
2015-07-25
Revision:
0:d75a1797ffd9

File content as of revision 0:d75a1797ffd9:

#include "mbed.h"

float version = 0.1;

// Serial to PC for outputs.
Serial pc(USBTX,USBRX);

// SPI Pins
SPI AdaBLE(p11,p12,p13);

// Input, RDYN active low, goes low when the BLE is ready to recieve data, or has data to send
DigitalIn AdaRdyN(p30);
// Output, REQN active low, put low to request right to send data.
DigitalOut AdaReqN(p27);
// Input, goes low when the BLE is busy recieving or sending data.
DigitalIn AdaAct(p29);
// Output, resets the module
DigitalOut AdaRst(p28);

// A function that loads configuration information into the nRF8001
void SetupBLE();
// A function that switches 8 bit MSB to LSB.
unsigned char BOReverse(unsigned char cmd);
// Function that writes setup lines.
bool SetupWriter(char setup[], int length);
// Puts device into connect mode.
void BLEConnectMode();

// Some well used temporary variables.
volatile int counter;
volatile unsigned char temp;

// Timeout for BLE connection
Timer timeout;

// Buffer to store SPI reads.
unsigned char buffer[100];

int main()
{
    ////////// Intialization \\\\\\\\\\

    // Serial PC Configuration \\
    // Set PC baud rate. Default 9600
    pc.baud(9600);

    // SPI Configuration \\
    // Set SPI frequency. nRF maximum is 3 Mhz as per datasheet page 26
    AdaBLE.frequency(2000000);
    // Set SPI mode 0, 8 bits. nRF uses SPI mode 0, LSB order. mbed uses MSB so a conversion function is nessesary.
    AdaBLE.format(8,0);

    // Pull Up RDYn line as per nRF8001 datasheet page 23
    //AdaRdyN.mode(PullUp); // !! Pin is already pulled up on the Adafruit breakout board by built in hardware. :)

    // Hold reset line high to bring device online.
    AdaRst = 1;

    // Wait 62 miliseconds per nRF8001 datasheet, page 23, for RDYn signal to be valid.
    wait_ms(62);

    // Print out dat sweet welcome message.
    pc.printf("\r====== Shit Where's My Phone Serial Debug Console ======\n\r");
    pc.printf("Version: %4.1f\n\r\n\r",version);

    // Run Device Setup \\

    // Message to serial
    pc.printf("Waiting for device to become ready: |");

    // Now we wait for the nRF to lower the RDYn signal.
    counter = 0;
    timeout.stop();
    timeout.reset();
    timeout.start();
    while (AdaRdyN != 0) {
        // Do nothing important, i update the display here in terminal.
        if (timeout.read() > 2) {
            error("\n\rnRF module never came online...");
        }
        // Wait for device to become ready.
        if (counter%3 == 0) {
            pc.printf("\b/");
        } else if (counter%3 == 1) {
            pc.printf("\b-");
        } else if (counter%3 == 2) {
            pc.printf("\b\\");
        } else {
            pc.printf("\b|");
        }
        counter++;
    }
    // nRF has signaled it has data for me to recieve.

    // Set REQn to ground then start clocking in data.
    AdaReqN = 0;

    BOReverse(AdaBLE.write(0x00)); // Discard this first byte as it is a debug byte.
    temp = BOReverse(AdaBLE.write(0x00)); // First byte defines message length. Since this is a bootup message it should always be 4 bytes long.

    // Clock in remaining bytes
    for (int i = 0; i < temp; i++) {
        buffer[i] = BOReverse(AdaBLE.write(0x00));
    }

    // Now set REQn back to high to close this transaction
    AdaReqN = 1;

    // Lets read this message.
    switch (buffer[0]) {
        case 0x81:
            pc.printf("\bDone!\n\r");
            break;
        default:
            error("\n\rStart packet not recieved!");
            break;
    }

    // Get operating mode. 0x01 = test, 0x02 = setup, 0x03 = standby
    unsigned char OpMode = buffer[1];
    // Check for HW error. 0x00 = no error, 0x01 = fatal error.
    unsigned char HWError = buffer[2];
    // Get DataCreditAvailiable, number of DataCommand buffers available.
    unsigned char DCAvail = buffer[3];

    // Print Operational Mode to terminal.
    pc.printf("Operational Mode: ");
    switch (OpMode) {
        case 0x01:
            pc.printf("Test\n\r");
            break;
        case 0x02:
            pc.printf("Setup\n\r");
            break;
        case 0x03:
            pc.printf("Standby\n\r");
            break;
        default:
            error("Invalid Operational Mode!");
            break;
    }

    // Warn if HW Error
    pc.printf("HW error last boot: ");
    switch (HWError) {
        case 0x00:
            pc.printf("No\n\r");
            break;
        case 0x01:
            pc.printf("Yes\n\r");
            break;
        default:
            error("Invalid Data Recieved");
            break;
    }

    // Print number of datacommand buffers avaliable.
    pc.printf("DataCommand buffers avaliable: %i\n\r",DCAvail);

    // Call setup routine
    SetupBLE();

    // Setup complete and device should be in standby mode!

    pc.printf("\n\rAbout to start advertising...\n\r");
    // Run connect to start pairing
    BLEConnectMode();

    while(1) {
        // Main runloop
        if (AdaRdyN == 0) {
            pc.printf("\n\r");
            AdaReqN = 0;
            BOReverse(AdaBLE.write(0x00));
            temp = BOReverse(AdaBLE.write(0x00));

            // Clock in remaining bytes
            for (int i = 0; i < temp; i++) {
                buffer[i] = BOReverse(AdaBLE.write(0x00));
                pc.printf("%02x ",buffer[i]);
            }
            AdaReqN = 1;
        }
    }
}

void BLEConnectMode()
{
    // Set REQn to ground
    AdaReqN = 0;
    timeout.stop();
    timeout.reset();
    timeout.start();
    while (AdaRdyN == 1) { /* wait until nRF sets RDYn line low */
        if (timeout.read() > 2) {
            error("\n\rError: No rights to send.");
        }
    }
    // Lenght of packet
    AdaBLE.write(BOReverse(0x05));
    // Connect packet header
    AdaBLE.write(BOReverse(0x0F));
    // Set bluetooth announce in seconds.
    AdaBLE.write(BOReverse(0x1E)); // !! Reverse order of bits since LSB
    AdaBLE.write(BOReverse(0x00)); // 0x1E is 30 seconds
    // Set advertisement interval. This setting * 0.625 msec = interval
    AdaBLE.write(BOReverse(0x20)); // !! Reverse order of bits since LSB
    AdaBLE.write(BOReverse(0x03)); // 0x0620 is 1600, 1 second interval.

    // Set REQn high to end transaction
    AdaReqN = 1;

    // Wait for command response event packet

    // Now we wait for the response packet to signal a successful transfer.
    timeout.stop();
    timeout.reset();
    timeout.start();
    while (AdaRdyN == 1) { /* wait until nRF sets RDYn line low */
        if (timeout.read() > 2) {
            error("\n\rError: No response packet recieved.");
        }
    }

    // Now set REQn to ground and clock in data
    AdaReqN = 0;

    // discard first byte
    BOReverse(AdaBLE.write(0x00));
    // get length data
    temp = BOReverse(AdaBLE.write(0x00));

    // Clock in remaining bytes
    for (int i = 0; i < temp; i++) {
        buffer[i] = BOReverse(AdaBLE.write(0x00));
    }

    // Read data
    if (buffer[0] != 0x84) {
        error("\n\rNot CommandResponseEvent!");
    }

    if (buffer[1] != 0x0F) {
        error("\n\rNot the correct CommandResponseEvent!");
    }

    switch (buffer[2]) {
        case 0x00:
            // Sucess lets continue
            // Now set REQn high to end transaction
            AdaReqN = 1;
            break;
        default:
            // Error failled to announce
            error("\n\rFailed announce!");
            break;
    }

    pc.printf("Bluetooth announcement successful! Look for it in peer device.\n\r");
    return;
}

unsigned char BOReverse(unsigned char cmd)
{
    return (((cmd * 0x0802LU & 0x22110LU) | (cmd * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16);
}

bool SetupWriter(unsigned char setup[], int length)
{
    // Set REQn line to groud to request right to send.
    AdaReqN = 0;
    // reset timeout timer
    timeout.stop();
    timeout.reset();
    timeout.start();
    while (AdaRdyN == 1) { /* wait until nRF sets RDYn line low */
        if (timeout.read() > 2) {
            error("\n\rError: No rights to send.");
        }
    }
    // Right to send recieved, Write setup strings
    for (int i = 0; i < (length); i++) {
        AdaBLE.write(BOReverse(setup[i]));
    }

    // Set REQn high to finish this transaction
    AdaReqN = 1;

    // Reset Timer
    timeout.stop();
    timeout.reset();
    timeout.start();
    temp = 0x00;

    // Now we wait for the response packet to signal a successful transfer.
    while (AdaRdyN == 1) { /* wait until nRF sets RDYn line low */
        if (timeout.read() > 2) {
            error("\n\rError: No response packet recieved.");
        }
    }

    // Now set REQn to ground and clock in data
    AdaReqN = 0;

    // discard first byte
    BOReverse(AdaBLE.write(0x00));
    // get length data
    temp = BOReverse(AdaBLE.write(0x00));

    // Clock in remaining bytes
    for (int i = 0; i < temp; i++) {
        buffer[i] = BOReverse(AdaBLE.write(0x00));
    }

    if (buffer[0] != 0x84) {
        error("\n\rNot CommandResponseEvent!");
    }

    if (buffer[1] != 0x06) {
        error("\n\rNot the correct CommandResponseEvent!");
    }

    switch (buffer[2]) {
        case 0x01:
            // Sucess lets continue
            // Now set REQn high to end transaction
            AdaReqN = 1;
            return true;
        case 0x02:
            // We finished writing settings!
            AdaReqN = 1;
            return true;
        case 0x88:
            // CRC mismatch
            error("\n\r\n\rACI_STATUS_ERROR_CRC_MISMATCH - CRC Mismatch Error\n\rThis is caused by not accurately entering the strings from nRFgo Studio.");
        default:
            // Error not expected
            error("\n\rUnexpected Response!");
            break;
    }

    // Should never be reached but just in case.
    return false;
}

void SetupBLE()
{
    // Write setup data arrays (Generated in nRFgo Studio)
    unsigned char setup1[] = {0x07,0x06,0x00,0x00,0x03,0x02,0x42,0x07};
    unsigned char setup2[] = {0x1f,0x06,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x06,0x00,0x00,
                              0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
                             };
    unsigned char setup3[] = {0x1f,0x06,0x10,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                              0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x03,0x90,0x01,0xff
                             };
    unsigned char setup4[] = {0x1f,0x06,0x10,0x38,0xff,0xff,0x02,0x58,0x0a,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
                              0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
                             };
    unsigned char setup5[] = {0x05,0x06,0x10,0x54,0x00,0x00};
    unsigned char setup6[] = {0x1f,0x06,0x20,0x00,0x04,0x04,0x02,0x02,0x00,0x01,0x28,0x00,0x01,0x00,0x18,0x04,0x04,0x05,0x05,0x00,
                              0x02,0x28,0x03,0x01,0x02,0x03,0x00,0x00,0x2a,0x04,0x04,0x14
                             };
    unsigned char setup7[] = {0x1f,0x06,0x20,0x1c,0x04,0x00,0x03,0x2a,0x00,0x01,0x53,0x57,0x4d,0x46,0x69,0x63,0x73,0x65,0x6d,0x69,
                              0x2e,0x63,0x6f,0x6d,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04
                             };
    unsigned char setup8[] = {0x1f,0x06,0x20,0x38,0x05,0x05,0x00,0x04,0x28,0x03,0x01,0x02,0x05,0x00,0x01,0x2a,0x06,0x04,0x03,0x02,
                              0x00,0x05,0x2a,0x01,0x01,0x00,0x00,0x04,0x04,0x05,0x05,0x00
                             };
    unsigned char setup9[] = {0x1f,0x06,0x20,0x54,0x06,0x28,0x03,0x01,0x02,0x07,0x00,0x04,0x2a,0x06,0x04,0x09,0x08,0x00,0x07,0x2a,
                              0x04,0x01,0xff,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x04,0x04
                             };
    unsigned char setup10[] = {0x1f,0x06,0x20,0x70,0x02,0x02,0x00,0x08,0x28,0x00,0x01,0x01,0x18,0x04,0x04,0x10,0x10,0x00,0x09,0x28,
                               0x00,0x01,0x84,0xb1,0x91,0xcc,0x05,0xd8,0x27,0xb0,0x1b,0x48
                              };
    unsigned char setup11[] = {0x1f,0x06,0x20,0x8c,0x6e,0xec,0x0f,0x18,0xfd,0x5a,0x04,0x04,0x13,0x13,0x00,0x0a,0x28,0x03,0x01,0x02,
                               0x0b,0x00,0x84,0xb1,0x91,0xcc,0x05,0xd8,0x27,0xb0,0x1b,0x48
                              };
    unsigned char setup12[] = {0x1f,0x06,0x20,0xa8,0x6e,0xec,0x19,0x2a,0xfd,0x5a,0x06,0x04,0x02,0x01,0x00,0x0b,0x2a,0x19,0x02,0x10,
                               0x04,0x04,0x13,0x13,0x00,0x0c,0x28,0x03,0x01,0x02,0x0d,0x00
                              };
    unsigned char setup13[] = {0x1f,0x06,0x20,0xc4,0x84,0xb1,0x91,0xcc,0x05,0xd8,0x27,0xb0,0x1b,0x48,0x6e,0xec,0x1a,0x2a,0xfd,0x5a,
                               0x06,0x04,0x02,0x01,0x00,0x0d,0x2a,0x1a,0x02,0x00,0x04,0x04
                              };
    unsigned char setup14[] = {0x1f,0x06,0x20,0xe0,0x13,0x13,0x00,0x0e,0x28,0x03,0x01,0x02,0x0f,0x00,0x84,0xb1,0x91,0xcc,0x05,0xd8,
                               0x27,0xb0,0x1b,0x48,0x6e,0xec,0x1b,0x2a,0xfd,0x5a,0x06,0x04
                              };
    unsigned char setup15[] = {0x0d,0x06,0x20,0xfc,0x03,0x02,0x00,0x0f,0x2a,0x1b,0x02,0x00,0x00,0x00};
    unsigned char setup16[] = {0x13,0x06,0x50,0x00,0x84,0xb1,0x91,0xcc,0x05,0xd8,0x27,0xb0,0x1b,0x48,0x6e,0xec,0x00,0x00,0xfd,0x5a};
    unsigned char setup17[] = {0x06,0x06,0xf0,0x00,0x03,0x7f,0xc3};

    pc.printf("Starting to write settings...");
    // Setup 1
    if (!SetupWriter(setup1,sizeof(setup1)/sizeof(setup1[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("1,");

    // Setup 2
    if (!SetupWriter(setup2,sizeof(setup2)/sizeof(setup2[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("2,");

    // Setup 3
    if (!SetupWriter(setup3,sizeof(setup3)/sizeof(setup3[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("3,");

    // Setup 4
    if (!SetupWriter(setup4,sizeof(setup4)/sizeof(setup4[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("4,");

    // Setup 5
    if (!SetupWriter(setup5,sizeof(setup5)/sizeof(setup5[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("5,");

    // Setup 6
    if (!SetupWriter(setup6,sizeof(setup6)/sizeof(setup6[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("6,");

    // Setup 7
    if (!SetupWriter(setup7,sizeof(setup7)/sizeof(setup7[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("7,");

    // Setup 8
    if (!SetupWriter(setup8,sizeof(setup8)/sizeof(setup8[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("8,");

    // Setup 9
    if (!SetupWriter(setup9,sizeof(setup9)/sizeof(setup9[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("9,");

    // Setup 10
    if (!SetupWriter(setup10,sizeof(setup10)/sizeof(setup10[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("10,");

    // Setup 11
    if (!SetupWriter(setup11,sizeof(setup11)/sizeof(setup11[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("11,");
    
    // Setup 12
    if (!SetupWriter(setup12,sizeof(setup12)/sizeof(setup12[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("12,");
    
    // Setup 13
    if (!SetupWriter(setup13,sizeof(setup13)/sizeof(setup13[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("13,");
    
    // Setup 14
    if (!SetupWriter(setup14,sizeof(setup14)/sizeof(setup14[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("14,");
    
    // Setup 15
    if (!SetupWriter(setup15,sizeof(setup15)/sizeof(setup15[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("15,");
    
    // Setup 16
    if (!SetupWriter(setup16,sizeof(setup16)/sizeof(setup16[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("16,");
    
    // Setup 17
    if (!SetupWriter(setup17,sizeof(setup17)/sizeof(setup17[1]))) {
        error("\n\rWrite Failed!");
    }
    pc.printf("17");
    // Done writing setup strings phew!

    // Wait for DeviceStartedEvent
    pc.printf("\n\rWaiting for device to accept settings: |");

    // Now we wait for the nRF to lower the RDYn signal.
    counter = 0;
    timeout.stop();
    timeout.reset();
    timeout.start();
    while (AdaRdyN != 0) {
        // Do nothing important, i update the display here in terminal.
        if (timeout.read() > 2) {
            error("\n\rnRF module never came back after settings where written...");
        }
        // Wait for device to become ready.
        if (counter%3 == 0) {
            pc.printf("\b/");
        } else if (counter%3 == 1) {
            pc.printf("\b-");
        } else if (counter%3 == 2) {
            pc.printf("\b\\");
        } else {
            pc.printf("\b|");
        }
        counter++;
    }
    // nRF has signaled it has data for me to recieve.

    // Set REQn to ground then start clocking in data.
    AdaReqN = 0;

    BOReverse(AdaBLE.write(0x00)); // Discard this first byte as it is a debug byte.
    temp = BOReverse(AdaBLE.write(0x00)); // First byte defines message length. Since this is a bootup message it should always be 4 bytes long.

    // Clock in remaining bytes
    for (int i = 0; i < temp; i++) {
        buffer[i] = BOReverse(AdaBLE.write(0x00));
    }

    // Now set REQn back to high to close this transaction
    AdaReqN = 1;

    // Lets read this message.
    switch (buffer[0]) {
        case 0x81:
            pc.printf("\bDone!\n\r");
            break;
        default:
            error("\n\rStart packet not recieved!");
            break;
    }

    // Get operating mode. 0x01 = test, 0x02 = setup, 0x03 = standby
    unsigned char OpMode = buffer[1];

    // Print Operational Mode to terminal.
    pc.printf("Operational Mode: ");
    switch (OpMode) {
        case 0x01:
            pc.printf("Test\n\r");
            break;
        case 0x02:
            pc.printf("Setup\n\r");
            break;
        case 0x03:
            pc.printf("Standby\n\r");
            break;
        default:
            error("Invalid Operational Mode!");
            break;
    }

    // Wait for Dev
    pc.printf("Settings written!\n\r");

    return;
}