IJFW - IchigoJamのBASICプログラムをメモリカード(MMCまたは互換カード)に保存したり読み出したりできるプログラム。メモリカードにファームウェアのファイルを置くだけで、電源ON時に自動的に書き換える機能も搭載(一応こちらがメイン)。LPC1114FN28専用。
参考URL http://www.cyberchabudai.org/index.php/entry?tag=IJFW
Diff: I2c2mem/I2c2mem.cpp
- 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; +} +