Microchip 23K256 (SPI SRAM) sample code for https://www.switch-science.com/catalog/1072/ module.

Dependencies:   mbed

main.cpp

Committer:
discypus
Date:
2014-11-01
Revision:
2:0248049e65f1
Parent:
1:793321f410a9
Child:
3:65a33de8fa08

File content as of revision 2:0248049e65f1:

/*
 * test for 
 *  - Microchip SRAM 23K256 (SPI)
 *  - Intersil Red/Green/Blue Color Light Sensor (I2C, address = 1000 100x, hard-wires)
 *    - ISL29125 data sheet, p.7, Device Adressing 
 *  - 
 */

#include "mbed.h"

/** Serial port for DEBUG */
Serial pc(USBTX, USBRX);

InterruptIn mybutton(USER_BUTTON);

/** ユーザーボタンが押されたらtrue */
volatile bool is_pressed = false;

/**
 * USERボタン 割り込みハンドラ
 */
void 
pressed() {
    is_pressed = true;
}

/**
 * USERボタンが押されるまで待つ。
 */
void
wait_until_user_button_pressed() {
    while (!is_pressed) {
        __nop();
    }
    is_pressed = false;
    pc.printf("USER button is pressed\r\n");
}

/** */
SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK);

/** */
DigitalOut cs(SPI_CS);

/*
 * SPI COMMAND (Microchip 23K256 SRAM)
 * 1byte read/write 
 * page read/write 
 * sequential read/write
 * status/configuration register read/write
 */
enum Microchip23K256Commnd {
    READ  = 0x03u,
    WRITE = 0x02u,
    RDSR = 0x05u,
    WRSR = 0x01u,
};

/** SRAM Mode */
enum Microchip23K256Mode {
    MODE_MASK = 0xc0u,
    BYTE = 0x00u,
    PAGE = 0x80u,
    SEQUENTIAL = 0x40u,
};

/**
 * assert CS
 */
inline void
assert_CS() {
    cs = 0;
}

/**
 * negate CS
 */
inline void
negate_CS() {
    cs = 1;
}

/**
 * レジスタ読みだし
 * @return レジスタ値
 */
inline uint8_t
read_status_register() {
    assert_CS();
    spi.write(RDSR);
    const uint8_t status = spi.write(0x00);
    negate_CS();
    
    return status;
}

/**
 * レジスタ書き込み
 * @param[in] status
 */
inline void
write_status_register(const uint8_t status) {
    assert_CS();
    spi.write(WRSR);
    spi.write(status);
    negate_CS();
}

/**
 * モードを切り替える。
 * @param[in] mode モード
 * @return 切替前のモード
 * @invariant モード以外のフラグは変更しない。
 */
inline uint8_t
change_mode(const unsigned int next_mode) {
    const uint8_t previous_status = read_status_register();
    const uint8_t previous_mode = previous_status & MODE_MASK;
    if (next_mode != previous_mode) {
        const uint8_t next_status = (previous_status & ~MODE_MASK) | uint8_t(next_mode);
        write_status_register(next_status);
    }
    return previous_mode;
}

/**
 * 1byte読み出し
 * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する
 * @return データ
 * @pre byteモードに切り替えていること。
 */
uint8_t
read_byte(const uint16_t address) {
    const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
    const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;
    
    assert_CS();
    spi.write(READ);
    spi.write(address_high);
    spi.write(address_low);
    const uint8_t data = spi.write(0x00);
    negate_CS();

    return data;
}

/**
 * 1byte書き込み
 * @param[in] address アドレス 16bit。容量32KBなので、MSBは無視する
 * @param[in] data データ
 * @pre byteモードに切り替えていること。
 */
void
write_byte(const uint16_t address, const uint8_t data) {
    const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
    const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;

    assert_CS();
    spi.write(WRITE);
    spi.write(address_high);
    spi.write(address_low);
    spi.write(data);
    negate_CS();
}

/**
 * 連続読み出し
 * @pre pageモードかbyteモードに切り替えていること。
 */
void
read_bytes(const uint16_t address, uint8_t __restrict data[], const uint16_t size) {
    const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
    const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;

    assert_CS();
    spi.write(READ);
    spi.write(address_high);
    spi.write(address_low);
    for (uint16_t i = 0; i < size; ++i) {
        data[i] = spi.write(0x00);
    }
    negate_CS();
}

/**
 * 連続書き込み
 * @pre pageモードかbyteモードに切り替えていること。
 */
void
write_bytes(const uint16_t address, const uint8_t __restrict data[], const uint16_t size) {
    const uint8_t address_high = (address >> (8 * 1)) & 0xFFu;
    const uint8_t address_low  = (address >> (8 * 0)) & 0xFFu;

    assert_CS();
    spi.write(WRITE);
    spi.write(address_high);
    spi.write(address_low);
    for (uint16_t i = 0; i < size; ++i) {
        spi.write(data[i]);
    }
    negate_CS();
}

/*
 *
 */


/** 動作確認用 SPI buffer */
uint8_t buf[256] = {};

/**
 * 動作確認用。TODO: テストコードにすること。
 */
void
try_byte_access() {
    const uint8_t size = 16;
    
    change_mode(BYTE);

    // write data
    for (int i = 0; i < size; i++) {
        write_byte(i, i);
    }

    // read data
    for (int i = 0; i < size; i++) {
        buf[i] = read_byte(i);
    }

    // show data (to SERIAL)
    pc.printf("byte access test: result\r\n");
    for (int i = 0; i < size; i++) {
        pc.printf("  %04x : %02x\r\n", i, buf[i]);
    }
}

/**
 * 動作確認用。TODO: テストコードにすること。
 */
void
try_page_access() {
    const uint16_t address = 0x1000;
    const uint16_t size = 32;

    change_mode(PAGE);

    // write
    for (uint16_t i = 0; i < size; ++i) {
        buf[i] = i;
    }
    write_bytes(address, buf, size);

    // read
    for (uint16_t i = 0; i < size; ++i) {
        buf[i] = 0;
    }

    read_bytes(address, buf, size);

    // show data (to SERIAL)
    pc.printf("page access test: result\r\n");
    for (int i = 0; i < size; i++) {
        pc.printf("  %04x : %02x\r\n", address + i, buf[i]);
    }
}

/**
 * 動作確認用。TODO: テストコードにすること。
 */
void
try_sequential_access() {
    const uint16_t address = 0x2000;
    const uint16_t size = 256;

    change_mode(SEQUENTIAL);

    // write
    for (uint16_t i = 0; i < size; ++i) {
        buf[i] = i;
    }

    write_bytes(address, buf, size);

    // read
    for (uint16_t i = 0; i < size; ++i) {
        buf[i] = 0;
    }

    read_bytes(address, buf, size);

    // show data (to SERIAL)
    pc.printf("sequential access test: result\r\n");
    for (int i = 0; i < size; i++) {
        pc.printf("  %04x : %02x\r\n", address + i, buf[i]);
    }
}


void
try_single_byte_access() {
    cs = 0;
    spi.write(0x02u);
    spi.write(0);
    spi.write(0);
    spi.write(0x5a);
    cs = 1;
    
    cs = 0;
    spi.write(0x03u);
    spi.write(0);
    spi.write(0);
    const uint8_t value = spi.write(0);
    cs = 1;

    pc.printf("read: 0x%02x\r\n", value);
}


/**
 * 動作確認用。TODO: テストコードにすること。
 */
int
main()
{
    mybutton.fall(&pressed);

    wait_until_user_button_pressed();

    // initialize
    spi.format(8, 0);   // 8bit, mode=0
    spi.frequency(20 * 1000 * 1000);    // max 20MHz
    negate_CS();

    // test
    pc.printf("TEST START\r\n");

    wait_until_user_button_pressed();
    try_single_byte_access();

    wait_until_user_button_pressed();
    try_byte_access();

    try_page_access();

    wait_until_user_button_pressed();
    try_sequential_access();

    pc.printf("TEST END\r\n\r\n");

    return 0;
}