Test application for the library FM24Vxx_I2C

Dependencies:   DebugLibrary FM24Vxx_I2C mbed

main.cpp

Committer:
Yann
Date:
2013-04-03
Revision:
2:dd6a152749c5
Parent:
1:e3c92ff30be3

File content as of revision 2:dd6a152749c5:

#include <string>
#include <iostream>
#include <iomanip>

#include "FM24Vxx_I2C.h"

struct UserChoice {
    char choice;
    unsigned char moduleId;
};

/*
 * Declare functions
 */
void AvailableIndicator(); // LED1 flashing for program while program is alive
UserChoice DisplayMenuAndGetChoice(); // Display and get the user choice
void RunStateMachine_WithStdStringValue(); // Write and read a string
void RunStateMachine_WithByteValue(); // Write and read a byte
void RunStateMachine_WithShortValue(CFM24VXX_I2C::Mode p_mode); // Write and read a short
void RunStateMachine_WithIntegerValue(CFM24VXX_I2C::Mode p_mode); // Write and read an integer
void RunStateMachine_WithStdVectorOfByteValue(); // Write and read a buffer of bytes
void RunStateMachine_WithLengthPlusStdVectorOfByteValue(); // Write and read a buffer of bytes
void ReadStdStringValue(const int p_address); // Read a string

enum States {
    Idle, // Idle state / Read memory operation done
    Write, // Write memory operation
    Written, // Write memory operation done
    Read // Read memory operation
};
States g_state; // Process states for memory operations

DigitalOut g_availableLed(LED1); // To verify if program in running
Ticker g_available; // LED1 will flash with a period of 2s
UserChoice g_userChoice; // Used to store user choice from displayed menu

CFM24VXX_I2C g_myFM24V10G(p28, p27, 0x00, p12); // Create an instance of the class CFM24VXX_I2C, p9/28: SDA, p10/29:SDL, p12: wired to WP input of FM24Vxx, address: A2=0,A1=1, on I2C bus

int main() {
    unsigned char memoryPage = 0x00;

    // Launch available indicator
    g_available.attach(&AvailableIndicator, 2.0);
    
    g_myFM24V10G.WriteProtect(false);
    
    while (true) { // Interrupt driven processing
        g_state = Idle; // Set initial state
        g_userChoice = DisplayMenuAndGetChoice(); // Retrieve the user selection
        DEBUG("Page select is set to %d", memoryPage)
        switch (g_userChoice.choice) {
            case 'a':
                do {
                    RunStateMachine_WithStdStringValue();
                } while (g_state != Idle);
                break;
            case 'b':
                do {
                    RunStateMachine_WithByteValue();
                } while (g_state != Idle);
                break;
            case 'c':
                do {
                    RunStateMachine_WithShortValue(CFM24VXX_I2C::BigEndian);
                } while (g_state != Idle);
                break;
            case 'd':
                do {
                    RunStateMachine_WithShortValue(CFM24VXX_I2C::LittleEndian);
                } while (g_state != Idle);
                break;
            case 'e':
                do {
                    RunStateMachine_WithIntegerValue(CFM24VXX_I2C::BigEndian);
                } while (g_state != Idle);
                break;
            case 'f':
                do {
                    RunStateMachine_WithIntegerValue(CFM24VXX_I2C::LittleEndian);
                } while (g_state != Idle);
                break;
            case 'g':
                do {
                    RunStateMachine_WithStdVectorOfByteValue();
                } while (g_state != Idle);
                break;
            case 'h':
                do {
                    RunStateMachine_WithLengthPlusStdVectorOfByteValue();
                } while (g_state != Idle);
                break;
            case 'i':
                ReadStdStringValue(0x100);
                break;
            case 'j':
                ReadStdStringValue(0x100);
                break;
            case 'k':
#if defined(__DEBUG)
                g_myFM24V10G.DumpMemoryArea(0, 0x14);
#else // __DEBUG
                std::cout << "DEBUG mode is not set, nothing to do!\r" << std::endl;
#endif // __DEBUG
                break;
            case 'l':
                g_myFM24V10G.EraseMemoryArea(0, 0x14);
                break;
            case 'm':
                {
                    std::string test("Test");
                    g_myFM24V10G.Write(0x20, test);
                }
                break;
            case 'n':
                ReadStdStringValue(0x20);
                break;
            case 'o': {
                    const CFM24VXX_SN *sn = g_myFM24V10G.GetSerialNumber();
                    std::cout << "\tCustomerID\t\t: " << std::setw(4) << std::setfill('0') << std::hex << sn->GetCustomerID() << "\r" << std::endl;
                    std::cout << "\tChecksum\t\t: " << std::setw(2) << std::setfill('0') << std::hex << sn->GetChecksum() << "\r" << std::endl;
                }
                break;
            case 'p': {
                    const CFM24VXX_IDs *deviceId = g_myFM24V10G.GetDeviceID();
#ifdef __DEBUG
                    DEBUG("\tManufacturerID\t\t: %02x", deviceId->GetManufacturerID());
                    DEBUG("\tProductID\t\t: %02x", deviceId->GetProductID());
                    DEBUG("\tRevisionID\t\t: %02x", deviceId->GetRevisionID());
                    DEBUG("\tDensity\t\t\t: %02x", deviceId->GetDensity());
                    DEBUG("\tVariation\t\t: %02x", deviceId->GetVariation());
#else
                    std::cout << "\tManufacturerID\t\t: " << std::setw(2) << std::setfill('0') << std::hex << deviceId->GetManufacturerID() << "\r" << std::endl;
                    std::cout << "\tProductID\t\t: " << std::setw(2) << std::setfill('0') << std::hex << deviceId->GetProductID() << "\r" << std::endl;
                    std::cout << "\tRevisionID\t\t: " << std::setw(2) << std::setfill('0') << std::hex << deviceId->GetRevisionID() << "\r" << std::endl;
                    std::cout << "\tDensity\t\t\t: " << std::setw(2) << std::setfill('0') << std::hex << deviceId->GetDensity() << "\r" << std::endl;
                    std::cout << "\tVariation\t\t: " << std::setw(2) << std::setfill('0') << std::hex << deviceId->GetVariation() << "\r" << std::endl;
#endif // __DEBUG
                }
                break;
            case 's':
                memoryPage = (memoryPage + 1) % 2;
                DEBUG("New page select is set to %d", memoryPage)
                g_myFM24V10G.SelectMemoryPage(memoryPage);
                do {
                    RunStateMachine_WithStdStringValue();
                } while (g_state != Idle);                
                break;
           default:
                std::cout << "Invalid user choice\r" << std::endl;
                break;
         } // End of 'switch' statement
    } // End of 'while' statement
} // End of program - nerver reached

void AvailableIndicator()
{
    g_availableLed = !g_availableLed;
} // End of AvailableIndicator

UserChoice DisplayMenuAndGetChoice()
{
    static UserChoice userChoice;

    // Display the title
    std::cout << "\r" << std::endl << "FM24Vxx_I2C v0.2\r" << std::endl;
    // Display the menu
    std::cout << "\tWrite/Read with std::string:\t\t\ta\r" << std::endl;
    std::cout << "\tWrite/Read with a byte:\t\t\t\tb\r" << std::endl;
    std::cout << "\tWrite/Read with a short (Big Endian):\t\tc\r" << std::endl;
    std::cout << "\tWrite/Read with a short (Little Endian):\td\r" << std::endl;
    std::cout << "\tWrite/Read with an integer (Big Endian):\te\r" << std::endl;
    std::cout << "\tWrite/Read with an integer (Little Endian):\tf\r" << std::endl;
    std::cout << "\tWrite/Read with std::vector<byte>:\t\tg\r" << std::endl;
    std::cout << "\tWrite/Read with std::vector<byte> + length:\th\r" << std::endl;
    std::cout << "\tRead with std::string:\t\t\t\ti\r" << std::endl;
    std::cout << "\tRead a string is address 0x0000:\t\tj\r" << std::endl;
    std::cout << "\tHexadump from address 0x0000:\t\t\tk\r" << std::endl;
    std::cout << "\tErase from address 0x0000:\t\t\tl\r" << std::endl;
    std::cout << "\tWrite 'Test' at address 0x0020:\t\t\tm\r" << std::endl;
    std::cout << "\tRead from address 0x0020:\t\t\tn\r" << std::endl;
    std::cout << "\tGet serial number:\t\t\t\to\r" << std::endl;
    std::cout << "\tGet devide ID:\t\t\t\t\tp\r" << std::endl;
    std::cout << "\tSwitch page select:\t\t\t\ts\r" << std::endl;
    std::cout << "Enter your choice: " << std::flush;
    userChoice.choice = getchar();
    return userChoice;
}

void RunStateMachine_WithStdStringValue()
{
    DEBUG_ENTER("RunStateMachine_WithStdStringValue")
    
    switch (g_state) {
        case Idle:
            g_state = Write;
            break;
        case Write: {
                DEBUG("Writing data...");
                time_t ctTime;
                ctTime = time(NULL);  
                std::string str("Current time is: ");
                str += ctime(&ctTime);
                str += " UTC";
                std::cout << "RunStateMachine_WithStdStringValue: Write '" << str << "'\r" << std::endl;
                if (!g_myFM24V10G.Write(0x40, str)) { // Write the string, including the length indicator
#ifdef __DEBUG
                    DEBUG_FATAL("RunStateMachine_WithStdStringValue: write failed at address 256")
#else // __DEBUG
                    std::cout << "RunStateMachine_WithStdStringValue: write failed at address 256\r" << std::endl;
#endif // __DEBUG
                    g_state = Idle;
                } else {
                    g_state = Written;
                }
            }
            break;
        case Written:
            g_state = Read;
            wait(1.0); // To prevent I2C bus capacity memeory
            break;
        case Read: {
                DEBUG("Reading datas...");
                std::string readtext;
                if (!g_myFM24V10G.Read(0x40, readtext)) { // Read the string, including the length indicator
#ifdef __DEBUG
                    DEBUG_FATAL("RunStateMachine_WithStdStringValue: write failed at address 256")
#else // __DEBUG
                    std::cout << "RunStateMachine_WithStdStringValue: write failed at address 256\r" << std::endl;
#endif // __DEBUG
                } else {
                    std::cout << "RunStateMachine_WithStdStringValue: Read: " << readtext << "\r" << std::endl;
                }
            }
            g_state = Idle;
            break;
        default:
            std::cout << "RunStateMachine_WithStdStringValue: Default!\r" << std::endl;
            g_state = Idle;
            break;
    }

    DEBUG_LEAVE("RunStateMachine_WithStdStringValue")
}

void RunStateMachine_WithByteValue() {
    DEBUG_ENTER("RunStateMachine_WithByteValue")
    
    switch (g_state) {
        case Idle:
            g_state = Write;
            break;
        case Write:
            DEBUG("Writing data...")
            std::cout << "RunStateMachine_WithByteValue: Write 0xaa\r" << std::endl;
            if (!g_myFM24V10G.Write(128, (unsigned char)0xaa)) {
#ifdef __DEBUG
                DEBUG_FATAL("RunStateMachine_WithByteValue: write failed at address 128")
#else // __DEBUG
                std::cout << "RunStateMachine_WithByteValue: write failed at address 128\r" << std::endl;
#endif // __DEBUG
                g_state = Idle;
            } else {
                g_state = Written;
            }
            break;
        case Written:
            g_state = Read;
            wait(1.0); // To prevent I2C bus capacity memeory
            break;
        case Read: {
                DEBUG("Reading datas...")
                unsigned char value = 0x00;
                if (!g_myFM24V10G.Read(128, &value)) {
#ifdef __DEBUG
                    DEBUG_FATAL("RunStateMachine_WithByteValue: Read operation failed at address 128")
#else // __DEBUG
                    std::cout << "RunStateMachine_WithByteValue: Read operation failed at address 128\r" << std::endl;
#endif // __DEBUG
                } else {
                    std::cout << "RunStateMachine_WithByteValue: Read '0x" << std::setw(2) << std::setfill('0') << std::ios::hex << value << "'\r" << std::endl;
                }
            }
            g_state = Idle;
            break;
        default:
            std::cout << "RunStateMachine_WithByteValue: Default!\r" << std::endl;
            g_state = Idle;
            break;
    }

    DEBUG_LEAVE("RunStateMachine_WithByteValue")
}

void RunStateMachine_WithShortValue(CFM24VXX_I2C::Mode p_mode) {
    DEBUG_ENTER("RunStateMachine_WithShortValue")
    
    switch (g_state) {
        case Idle:
            g_state = Write;
            break;
        case Write:
            DEBUG("Writing data...")
            std::cout << "RunStateMachine_WithShortValue: Write 0xbeef\r" << std::endl;
            if (!g_myFM24V10G.Write(64, (short)0xbeef, p_mode)) { // See http://en.wikipedia.org/wiki/Hexspeak for more ideas on hexadecimal wording!!!
                DEBUG_FATAL("RunStateMachine_WithShortValue: write failed at address 64")
                g_state = Idle;
            } else {
                g_state = Written;
            }
            break;
        case Written:
            g_state = Read;
            wait(1.0); // To prevent I2C bus capacity memeory
            break;
        case Read: {
                DEBUG("Reading datas...");
                short value = 0;
                if (!g_myFM24V10G.Read(64, &value, p_mode)) {
#ifdef __DEBUG
                DEBUG_FATAL("RunStateMachine_WithShortValue: write failed at address 64")
#else // __DEBUG
                std::cout << "RunStateMachine_WithShortValue: write failed at address 64\r" << std::endl;
#endif // __DEBUG
                } else {
                    std::cout << "RunStateMachine_WithShortValue: Read '0x" << std::setw(4) << std::setfill('0') << std::hex << value << "' / '" << (unsigned short)value << "'\r" << std::endl;
                }
            }
            g_state = Idle;
            break;
        default:
            std::cout << "RunStateMachine_WithShortValue: Default!\r" << std::endl;
            g_state = Idle;
            break;
    }

    DEBUG_LEAVE("RunStateMachine_WithShortValue")
}

void RunStateMachine_WithIntegerValue(CFM24VXX_I2C::Mode p_mode) {
    DEBUG_ENTER("RunStateMachine_WithIntegerValue")
    
    switch (g_state) {
        case Idle:
            g_state = Write;
            break;
        case Write:
            DEBUG("Writing data...")
            std::cout << "RunStateMachine_WithIntegerValue: Write 0xdeaddead\r" << std::endl;
            if (!g_myFM24V10G.Write(0, (int)0xdeaddead, p_mode)) {
                DEBUG_FATAL("RunStateMachine_WithIntegerValue: write failed at address 32")
                g_state = Idle;
            } else {
                g_state = Written;
            }
            break;
        case Written:
            g_state = Read;
            wait(1.0); // To prevent I2C bus capacity memeory
            break;
        case Read: {
                DEBUG("Reading datas...")
                int value = 0;
                if (!g_myFM24V10G.Read(0, &value, p_mode)) {
#ifdef __DEBUG
                    DEBUG_FATAL("RunStateMachine_WithIntegerValue: write failed at address 32")
#else // __DEBUG
                    std::cout << "RunStateMachine_WithIntegerValue: write failed at address 32\r" << std::endl;
#endif // __DEBUG
                } else {
                    std::cout << std::setw(8) << std::setfill('0') << std::hex << "RunStateMachine_WithIntegerValue: Read '0x" << value << "'/ '" << (unsigned int)value << "'\r" << std::endl;
                }
            }
            g_state = Idle;
            break;
        default:
            std::cout << "RunStateMachine_WithIntegerValue: Default!\r" << std::endl;
            g_state = Idle;
            break;
    }

    DEBUG_LEAVE("RunStateMachine_WithIntegerValue")
}

void RunStateMachine_WithStdVectorOfByteValue() {
    DEBUG_ENTER("RunStateMachine_WithStdVectorOfByteValue")
    
    switch (g_state) {
        case Idle:
            g_state = Write;
            break;
        case Write: {
                std::vector<unsigned char> datas;
                datas.push_back(0xfe);
                datas.push_back(0xed);
                datas.push_back(0xfa);
                datas.push_back(0xce);
                DEBUG("Writing data...")
                std::cout << "RunStateMachine_WithStdVectorOfByteValue: Write {0xfe, 0xed, 0xfa, 0xce}\r" << std::endl;
                if (!g_myFM24V10G.Write(0, datas, false)) { // Write the full buffer, not including the length indication
                    DEBUG_FATAL("RunStateMachine_WithStdVectorOfByteValue: write failed at address 16")
                    g_state = Idle;
                } else {
                    g_state = Written;
                }
            }
            break;
        case Written:
            g_state = Read;
            wait(1.0); // To prevent I2C bus capacity memeory
            break;
        case Read: {
                DEBUG("Reading datas...")
                std::vector<unsigned char> datas(4);
                if (!g_myFM24V10G.Read(0, datas, false)) { // Read bytes, without the lenght indication, buffer size shall be set before the call
#ifdef __DEBUG
                    DEBUG_FATAL("RunStateMachine_WithStdVectorOfByteValue: write failed at address 16")
#else // __DEBUG
                    std::cout << "RunStateMachine_WithStdVectorOfByteValue: write failed at address 16\r" << std::endl;
#endif // __DEBUG
                } else {
                    std::cout << "RunStateMachine_WithStdVectorOfByteValue: Read {" << "', '" << datas[0] << "', '" << datas[1] << "', '" << datas[2] << "', '" << datas[3] <<"'}\r" << std::endl;
                }
            }
            g_state = Idle;
            break;
        default:
            std::cout << "RunStateMachine_WithStdVectorOfByteValue: Default!\r" << std::endl;
            g_state = Idle;
            break;
    }

    DEBUG_LEAVE("RunStateMachine_WithStdVectorOfByteValue")
}

void RunStateMachine_WithLengthPlusStdVectorOfByteValue() {
    DEBUG_ENTER("RunStateMachine_WithLengthPlusStdVectorOfByteValue")
    
    switch (g_state) {
        case Idle:
            g_state = Write;
            break;
        case Write: {
                DEBUG("Writing data...")
                std::vector<unsigned char> datas;
                datas.push_back(0xde);
                datas.push_back(0x5e);
                datas.push_back(0xa5);
                datas.push_back(0xed);
                std::cout << "RunStateMachine_WithLengthPlusStdVectorOfByteValue: Write {0xde, 0x5e, 0xa5, 0xed}\r" << std::endl;
                if (!g_myFM24V10G.Write(0, datas)) { // Write the full buffer, including the length indication
                    DEBUG_FATAL("RunStateMachine_WithLengthPlusStdVectorOfByteValue: write failed at address 8")
                    g_state = Idle;
                } else {
                    g_state = Written;
                }
            }
            break;
        case Written:
            g_state = Read;
            wait(1.0); // To prevent I2C bus capacity memeory
            break;
        case Read: {
                DEBUG("Reading datas...")
                std::vector<unsigned char> datas;
                if (!g_myFM24V10G.Read(8, datas)) { // Read bytes, including the lenght indication, buffer size is not set before the call
#ifdef __DEBUG
                    DEBUG_FATAL("RunStateMachine_WithStdVectorOfByteValue: write failed at address 8")
#else // __DEBUG
                    std::cout << "RunStateMachine_WithStdVectorOfByteValue: write failed at address 8\r" << std::endl;
#endif // __DEBUG
                } else {
                    std::cout << "RunStateMachine_WithLengthPlusStdVectorOfByteValue: Read bytes:\r" << std::endl;
                    vector<unsigned char>::iterator it;
                    for (it = datas.begin() ; it < datas.end(); it++) {
                         std::cout << "0x" << std::setw(2) << std::setfill('0') << std::hex << *it << " ";
                    }
                    std::cout << "\r" << std::endl;
                }
            }
            g_state = Idle;
            break;
        default:
            std::cout << "RunStateMachine_WithLengthPlusStdVectorOfByteValue: Default!\r" << std::endl;
            g_state = Idle;
            break;
    }

    DEBUG_LEAVE("RunStateMachine_WithLengthPlusStdVectorOfByteValue")
}

void ReadStdStringValue(const int p_address) {
    DEBUG_ENTER("ReadStdStringValue: %d", p_address)

    DEBUG("Reading datas...");
    std::string readtext;
    if (!g_myFM24V10G.Read(p_address, readtext)) { // Read the string, including the length indicator
#ifdef __DEBUG
        DEBUG_FATAL("ReadStdStringValue: write failed at address 256")
#else // __DEBUG
        std::cout << "ReadStdStringValue: write failed at address 256\r" << std::endl;
#endif // __DEBUG
    } else {
        std::cout << "ReadStdStringValue: Read:'" << readtext << "'\r" << std::endl;
    }

    DEBUG_LEAVE("ReadStdStringValue")
}