IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。

Dependencies:   mbed

参考URL http://www.cyberchabudai.org/index.php/entry?tag=IJFW

Revision:
0:43cce7b453d0
Child:
1:11f73f269fdc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/I2c2mem/I2c2mem.cpp	Thu Apr 28 11:23:24 2016 +0000
@@ -0,0 +1,291 @@
+#include "I2c2mem.h"
+#include "mbed.h"
+#include "I2CSlave2.h"
+#include "FatfsIJFW.h"
+
+const int PROGRAM_BYTES_MAX = 1024;
+const int PROGRAM_NUM_MAX = 128;
+const int DATA_BYTES_MAX = 512;
+const char* DATA_FILENAME = "ijdata.dat";
+const int DATA_FILENUM_MAX = 1023;
+
+const int RETURN_NORMAL = 1;
+const int RETURN_ERROR = 0;
+
+
+I2c2mem::I2c2mem(I2CSlave2* _i2cs, FatfsIJFW* _fs, DigitalOut* _ledcard)
+    : i2cs(_i2cs), fs(_fs), ledcard(_ledcard) {
+    buffer = new char[PROGRAM_BYTES_MAX];
+    address = 0;    
+    count = 0;
+    dataBytesCount = 0;
+    dataFileNum = 0;
+}
+
+
+I2c2mem::~I2c2mem(){
+    delete [] buffer;
+}
+
+
+// Write a BASIC program to memory card
+int I2c2mem::writeProgram(int flag){
+    ledcard->write(1);
+
+    // Receive I2C data (
+    char bufi2c[36];
+    int length = i2cs->read(bufi2c, 36) - 1;
+
+    if (length == 2 || length == 34) {
+        if (count == 0) {
+            // Calculate memory address in EEPROM
+            address = 0x10000 * flag;   // This flag expresses 64-127 block
+            address |= (bufi2c[0] << 8) | bufi2c[1];
+            // BAS file
+            int filenum = ((address / PROGRAM_BYTES_MAX) % PROGRAM_NUM_MAX) + 100;
+            sprintf(filename, "ij%03d.bas", filenum);
+        }
+    } else {    // Not match 2 nor 34
+        i2cs->stop();
+        count = 0;
+        return RETURN_ERROR;
+    }
+
+    if (length == 34) {
+        for (int i = 0; i < 32; i++) {
+            buffer[count + i] = bufi2c[i + 2];
+        }
+        count += 32;
+
+        if (count >= PROGRAM_BYTES_MAX) {
+            count = 0;
+            fs->mount();
+            int res = fs->open(filename, MODE_OVERWRITE);
+            if (res != FR_OK) {
+                return RETURN_ERROR;
+            }
+
+            fs->write(buffer, PROGRAM_BYTES_MAX);
+            fs->close();
+        }
+    }
+    
+    ledcard->write(0);
+    return RETURN_NORMAL;
+}
+
+
+// Read a BASIC program from memory card
+int I2c2mem::readProgram() {
+    ledcard->write(1);
+
+    if (count == 0) {
+        fs->mount();
+        int res = fs->open(filename, MODE_RO);
+        if (res != FR_OK) {
+            i2cs->stop();
+            return RETURN_ERROR;
+        }
+        if (fs->read(buffer, PROGRAM_BYTES_MAX) != PROGRAM_BYTES_MAX) {
+            fs->close();
+            i2cs->stop();
+            return RETURN_ERROR;
+        }
+        fs->close();
+    }
+    
+    char bufi2c[32];
+    for (int i = 0; i < 32; i++) {
+        bufi2c[i] = buffer[count + i];
+    }
+
+    if (i2cs->write(bufi2c, 32) != 32) {
+        i2cs->stop();
+        count = 0;
+        return RETURN_ERROR;
+    }
+    count += 32;
+    
+    if (count >= PROGRAM_BYTES_MAX) {
+        i2cs->stop();
+        count = 0;
+    }
+    
+    ledcard->write(0);
+    return RETURN_NORMAL;
+}
+
+
+// Write a I2C data to memory card
+int I2c2mem::writeData()
+{
+    ledcard->write(1);
+
+    // Data from master
+    char bufi2c[DATA_BYTES_MAX+2];
+    int length = i2cs->read(bufi2c, DATA_BYTES_MAX+2) - 1;
+    // The reason of "DATA_BYTES_MAX+2" is the one is "command byte" 
+    // from IchigoJam and the other is caused by behavior of i2c_api
+
+    if (length == 1) {      // when "i2cr" instruction
+        count = 1;
+        return RETURN_NORMAL;
+    } else {
+        count = 0;
+    }
+
+    length--;   // decresement the number of command bytes
+    if (length > DATA_BYTES_MAX) {
+        length = DATA_BYTES_MAX;
+    }
+
+    // Write data to memory card
+    fs->mount();
+    int res = fs->open(DATA_FILENAME, MODE_OVERWRITE);
+    if (res != FR_OK) {
+        return RETURN_ERROR;
+    }
+    fs->write(&bufi2c[1], length);
+    fs->close();
+    
+    ledcard->write(0);
+    return RETURN_NORMAL;
+}
+
+
+// Read a I2C data to memory card
+int I2c2mem::readData()
+{
+    ledcard->write(1);
+
+    if (count != 1) {
+        i2cs->stop();
+        count = 0;
+        return RETURN_ERROR;
+    }
+
+    // Read data from memory card
+    fs->mount();
+    int res = fs->open(DATA_FILENAME, MODE_RO);
+    if (res != FR_OK) {
+        return RETURN_ERROR;
+    }
+
+    int length = fs->filesize();
+    if (length > DATA_BYTES_MAX) {
+        length = DATA_BYTES_MAX;
+    }
+
+    char bufi2c[DATA_BYTES_MAX];
+    if (fs->read(bufi2c, length) != length) {
+        fs->close();
+        return RETURN_ERROR;
+    }
+    fs->close();
+
+    // Send to master
+    i2cs->write(bufi2c, length);
+
+    count = 0;
+    ledcard->write(0);
+    return RETURN_NORMAL;
+}
+
+
+// Write a I2C data to memory card card (Continuous writting mode)
+int I2c2mem::writeDataContinuous()
+{
+    // Data from master
+    char bufi2c[DATA_BYTES_MAX+2];
+    int length = i2cs->read(bufi2c, DATA_BYTES_MAX+2) - 1;
+
+    length--;   // decresement the number of command bytes
+    if (length > DATA_BYTES_MAX) {
+        length = DATA_BYTES_MAX;
+    }
+
+    for (int i = 0; i < length; i++) {
+        buffer[dataBytesCount + i] = bufi2c[i + 1];
+    }
+    
+    dataBytesCount += length;
+    if (dataBytesCount < DATA_BYTES_MAX) {
+        return RETURN_NORMAL;
+    }
+
+    // Write data to memory card
+    ledcard->write(1);
+    fs->mount();
+    fs->mkdir("data");
+
+    sprintf(filename, "/data/%04d.dat", dataFileNum);
+    int res = fs->open(filename, MODE_APPEND);
+    if (res != FR_OK) {
+        return RETURN_ERROR;
+    }
+
+    int datafilesize = fs->filesize();
+    if (datafilesize > 1024*1024) {
+        fs->close();
+        dataFileNum++;
+        if (dataFileNum > DATA_FILENUM_MAX) {
+            dataFileNum = 0;
+        }
+        sprintf(filename, "/data/%04d.dat", dataFileNum);
+        res = fs->open(filename, MODE_OVERWRITE);
+        if (res != FR_OK) {
+            return RETURN_ERROR;
+        }
+    }
+
+    fs->write(buffer, dataBytesCount);
+    fs->close();
+    dataBytesCount = 0;
+    ledcard->write(0);
+    
+    return RETURN_NORMAL;
+}
+
+
+int I2c2mem::reset()
+{
+    i2cs->stop();
+
+    // If there is data remaining in the buffer, it is written to memory card.
+    if (dataBytesCount != 0) {
+        ledcard->write(1);
+        fs->mount();
+
+        sprintf(filename, "/data/%04d.dat", dataFileNum);
+        int res = fs->open(filename, MODE_APPEND);
+        if (res != FR_OK) {
+            return RETURN_ERROR;
+        }
+
+        int datafilesize = fs->filesize();
+        if (datafilesize > 1024*1024) {
+            fs->close();
+            dataFileNum++;
+            if (dataFileNum > DATA_FILENUM_MAX) {
+                dataFileNum = 0;
+            }
+            sprintf(filename, "/data/%04d.dat", dataFileNum);
+            res = fs->open(filename, MODE_OVERWRITE);
+            if (res != FR_OK) {
+                return RETURN_ERROR;
+            }
+        }
+
+        fs->write(buffer, dataBytesCount);
+        fs->close();
+        ledcard->write(0);
+    }
+
+    address = 0;    
+    count = 0;
+    dataBytesCount = 0;
+    dataFileNum = 0;
+
+    return RETURN_NORMAL;
+}
+