/*****************************************/ /* シリアル受信データバッファ */ /* "rxbff3a" */ /*****************************************/ // 2020-03-20 EEPROM 24LC1025を2つにして256kバイトに // 2024-12-24 ★1 24LC1025を2つ増設 512kバイトに // 26 TX時のボーレートを115.2kにup(JP1 onで) // 27 EEPROMアクセスを"Wire.h"から独自のものに ★2 // 受信したシリアルデータをEEPROMに保存 // 送信スイッチでその内容を出力 // PD0 i シリアル入力 // PD1 o シリアル出力 // PD2 o 2 送信LED (Lでon) // PD3 o 3 記録LED (Lでon) // PD4 i 4 送信SW (Lでon) // PD5 i 5 記録開始SW (Lでon) // PD6 o 6 (!!!) シリアル受信タイミングチェック // PD7 o 7 (!!!) 1mS割り込みタイミングチェック // PC0 o A0 (未使用) // PC1 o A1 (未使用) // PC2 o A2 (未使用) // PC3 o A3 (未使用) // PC4 - EEPROM SDA // PC5 - EEPROM SCL // PB0 i 8 JP1:on(L)でTX時のボーレートを115.2kにup // PB1 o 9 (!!!) 内蔵EEPROM処理タイミングチェック // PB2 o 10 (!!!) シリアル送信タイミングチェック // PB3 o 11 (未使用) // PB4 o 12 (未使用) // PB5 o 13 [LED] (未使用) /***** タイトルと日付 *****/ const char pgm_ttl1[] PROGMEM = "rxbff3a "; // タイトル const char pgm_ttl2[] PROGMEM = "2024-12-27"; // 日付 // 0123456789012345 PGM_P pgm_ttl[] = { pgm_ttl1, pgm_ttl2, }; /***** ライブラリ ****/ #include // 1msタイマー割り込み // 外付けEEPROM // http://playground.arduino.cc/Code/I2CEEPROM //#include // I2C ★2 #define EEP_SIZE 0x80000 // EEPROM サイズ 512kバイトに増設★1 // 外付けEEPROMのバイト数 #define EEP_PAGE 128 // EEPROM ページサイズ // 連続書き込みできるバイト数 // 開始は任意のアドレスでok // #include // EEPROM includeしなくてok? /***** 配列のデータ数を返すマクロ *****/ #define DIMSIZ(a) (sizeof(a)/sizeof(*a)) /***** I/Oマクロ *****/ // LED on/off #define LED_TX_ON (PORTD &= ~(1 << PD2)) // 送信LED #define LED_TX_OFF (PORTD |= (1 << PD2)) #define LED_MEM_ON (PORTD &= ~(1 << PD3)) // 記録中LED #define LED_MEM_OFF (PORTD |= (1 << PD3)) // SW,JP入力 on,offチェック(onで1) #define INP_SW_TX ((~PIND) & (1 << PD4)) // 送信開始SW Lでオン #define INP_SW_MEM ((~PIND) & (1 << PD5)) // 記録開始SW Lでオン #define CK_JP1 ((~PINB) & (1 << PB0)) // TX時のボーレートを115.2kにup // タイミング確認 #define PD6_H (PORTD |= (1 << PD6)) // (!!!)PD6 H/L 12pin #define PD6_L (PORTD &= ~(1 << PD6)) // シリアル受信タイミングチェック #define PD7_H (PORTD |= (1 << PD7)) // (!!!)PD7 H/L 13pin #define PD7_L (PORTD &= ~(1 << PD7)) // 1mS割り込みタイミングチェック #define PB1_H (PORTB |= (1 << PB1)) // (!!!)PB1 H/L 15pin #define PB1_L (PORTB &= ~(1 << PB1)) // 内蔵EEPROM処理タイミングチェック #define PB2_H (PORTB |= (1 << PB2)) // (!!!)PB2 H/L 16pin #define PB2_L (PORTB &= ~(1 << PB2)) // シリアル出力タイミングチェック /***** タイマーデータ *****/ volatile byte f_1ms; // 1msありフラグ volatile byte tm_1ms; // 1msダウンカウントタイマー max 255ms volatile byte tm_eep; // EEPROM 確認 1msタイマー max 255ms volatile byte tm_txw; // 送信待ちタイマー max 255ms volatile byte tm_10ms; // 10msダウンカウントタイマー max 2.55s volatile byte tm_memled; // 記録中LED点滅用 10msタイマー volatile byte tm_1sec; // 1secダウンカウントタイマー max 255s volatile byte tm_mcntsv; // データ数保存1secタイマー max 255s /***** スイッチデータ,フラグ *****/ // 割り込みで設定されるのは除外 typedef struct{ uint8_t swmem:1; // 記録SW on フラグ(短押し) uint8_t swclr:1; // 記録クリア(長押し) uint8_t swtx:1; // データ送信SW uint8_t swtxa:1; // 全データ送信SW }flag; flag f; // フラグの実体 byte f_memon; // 記録実行中フラグ byte f_mcntsv; // mem_cnt自動セーブフラグ /***** 記録データ *****/ uint32_t mem_cnt; // 記録データ数(EEPROMの容量まで) byte mem_bff[64]; // I2C EEPROM記録用バッファ ★2 // wire.hの中で「BUFFER_LENGTH 32」 // と連続読み書きの大きさが指定されている // これよりアドレスの2バイトを引いた数 uint32_t tx_cnt; // 送信データ数 (記憶した文字数) uint32_t tx_ptr; // 送信データポインタ // 記録データ出力用 word mrd_cnt; // EEPROM読み出しカウンタ word mrd_ptr; // EEPROM読み出し用ポインタ byte mrd_bff[64]; // I2C EEPROM読み出し用バッファ ★2 // バッファ読み出しを使う byte cnt_txchr; // シリアル出力文字カウンタ // CR以外でカウントアップ // CRでクリア // シリアル受信用 割込での受信バッファは64バイト // EEPROM書き込み待ち時間に溜めるためのバッファ byte rx_bff[512]; // シリアル受信バッファ word rx_cnt; // 受信データ数 word rx_wrp; // 受信データ書き込みポインタ word rx_rdp; // 受信データ読み出しポインタ /***** 内蔵EEPROM アドレス *****/ uint32_t EEMEM EA_MEMCNT; // 記録データ数 (long) uint8_t EEMEM EA_MEMON; // 記録on/offフラグ (byte) /********************************/ /* タイマー割り込み */ /********************************/ /***** タイマー2 1mS割り込み *****/ // 計測時間はメインで計時 void tm2int(void) { static byte cnt10 = 0; static byte cnt100 = 0; PD7_H; // 13pin H (!!!) // 1msタイマー f_1ms = 1; // 1msあり if(tm_1ms) tm_1ms--; // 1msダウンカウントタイマー if(tm_eep) tm_eep--; // EEPROM 確認 if(tm_txw) tm_txw--; // 送信待ち // 10msタイマー cnt10++; if(cnt10 >= 10){ // 10ms cnt10 = 0; if(tm_10ms) tm_10ms--; // 10msダウンカウント if(tm_memled) tm_memled--; // LED点滅タイマー // 1secタイマー cnt100++; if(cnt100 >= 100){ // 1sec cnt100 = 0; if(tm_1sec) tm_1sec--; if(tm_mcntsv) tm_mcntsv--; // データ数セーブタイミング } } PD7_L; // 13pin L (!!!) } /********************************/ /* スイッチ入力チェック */ /********************************/ /***** スイッチ入力チェック *****/ // 1msサイクルで処理 // 長押し判定を行う void swchk(void) { static uint8_t exc1 = 0; // TX SW 実行区分 static uint8_t exc2 = 0; // MEM SW 実行区分 static uint16_t tm1 = 0; // TX SW タイマー static uint16_t tm2 = 0; // MEM SW タイマー // TXスイッチ if(tm1) tm1--; // タイマー -1 switch(exc1){ case 0: // オン待ち if(INP_SW_TX){ // on ? tm1 = 10; // 10ms exc1++; } break; case 1: // 10ms安定 if(INP_SW_TX){ // on 継続 if(tm1 == 0){ // タイムアップ tm1 =2000; // 2秒 exc1++; } } else{ // offした exc1 = 0; // オン待ちに戻す } break; case 2: // 長押し判定 if(INP_SW_TX){ // on 継続 if(tm1 == 0){ // 2秒経過 f.swtxa = 1; // 長押しオン(全データ送信) exc1++; } } else{ // offした f.swtx = 1; // 送信スイッチ exc1++; } break; case 3: // オフを待つ if(!INP_SW_TX){ // off ? exc1 = 0; // オン待ちに戻す } break; } // MEMスイッチ,長押しとチョン押しを判断 if(tm2) tm2--; // 1msタイマー switch(exc2){ case 0: // オン待ち if(INP_SW_MEM){ // on ? tm2 = 10; // 10ms exc2++; } break; case 1: // 10ms安定 if(INP_SW_MEM){ // on 継続 if(tm2 == 0){ // タイムアップ tm2 = 2000; // 2秒 exc2++; } } else{ // off exc2= 0; // オン待ちに戻す } break; case 2: // 長押し判定 if(INP_SW_MEM){ // on 継続 if(tm2 == 0){ // タイムアップ f.swclr = 1; // 長押しでクリアSW exc2++; } } else{ // offした f.swmem = 1; // 短押しで記録on/offSW exc2++; } break; case 3: // オフを待つ if(!INP_SW_MEM){ // オフになった exc2 = 0; // オン待ちに戻す } break; } } /***************************/ /* LED点灯,点滅 */ /***************************/ // 記録実行していないときは消灯 // 記録中は点滅回数でバッファ容量を報知 // メモリがいっぱいなら0.2秒周期で点滅 // <20% H_______H________H____ // <40% H_H_______H_H_________ // <60% H_H_H_______H_H_H_____ // <80% H_H_H_H_______H_H_H_H_ // <100% H_H_H_H_H_______H_H_H_ // =100% H_H_H_H_H_H_H_H_H_H_H_ // 0 1 2 3 4 5 6 7 0 1 2 /***** 記録中LED 点滅処理 *****/ // 1msサイクルで呼び出し // tm_memledはタイマー割込でダウンカウント(10ms) void blinkmemled(void) { static byte tgl = 0; // on/offトグル状態 static byte cnt = 0; // 点滅回数 byte b; if(f_memon == 0){ // 記録していない LED_MEM_OFF; // LED off tm_memled = 0; tgl = 0; cnt = 0; } else{ // 記録中 0.2秒サイクルで高速点滅 if(tm_memled == 0){ // タイムアップ if(mem_cnt >= EEP_SIZE){ // mem最大? tgl ^= 1; // トグル if(tgl){ LED_MEM_ON; // LED on tm_memled = 2; // 20ms } else{ LED_MEM_OFF; // off tm_memled = 18; // 180ms } } else{ // まだ余裕あり 点滅回数変える b = (byte)((5 * mem_cnt) / EEP_SIZE); // b=0~4 if(tgl == 0){ tm_memled = 5; // 50ms if(b >= cnt) LED_MEM_ON; // LED on else LED_MEM_OFF; // off } else{ tm_memled = 25; // 250ms LED_MEM_OFF; // LED off } tgl ^= 1; // トグル反転 if(tgl == 0){ cnt++; // 点滅カウント if(cnt >= (b + 4)) cnt = 0; // 0~7 } } } } } /********************************/ /* TWIモジュールのアクセス */ /********************************/ // ATmega328PのTWIハードウェアを制御 // TWINT=1を待つのに割り込みを使わなない // タイムアウトチェックカウンタを設けて異常でも抜けるように /***** TWI 初期化 *****/ // TWI周波数を設定 200kHzで // SDA,SCLのプルアップ抵抗は4.7kΩ // 400kHzにするなら2.2kΩあたりに void twiInit(void ) { // ATmega328P設定 TWSR &= 0b11111100; // プリスケーラ 1/1に // ++----- TWPS1,0 TWBR = 32; // クロック200kHzに // SCL = 16MHz / (16+(2*TWBR)) // 400kHzなら12に TWCR = 0b00000100; // |||||| +----- TWIE 割込は使わない // |||||+------- TWEN TWI動作許可 // ||||+-------- TWWC // |||+--------- TWSTO // ||+---------- TWSTA // |+----------- TWEA ACK応答許可 // +------------ TWINT } /***** TWI 読み書き開始 *****/ // rw: 0:read 1:write void twiStart(uint8_t adrs, uint8_t rw) { uint16_t tt; // time out check counter uint8_t a; // 内部で処理するアドレス a = adrs << 1; // 左シフト if(rw == 0) a |= 1; // rw:0で読み出しモードに TWCR = 0b10100100; // |||||| +----- TWIE 割込は使わない // |||||+------- TWEN TWI動作許可 // ||||+-------- TWWC // |||+--------- TWSTO // ||+---------- TWSTA 開始 // |+----------- TWEA // +------------ TWINT TWINTクリア tt = 2000; // 2000 loop while(tt){ // time out? if((TWCR & (1 << TWINT))) break; // TWINT=1を待つ tt--; } TWDR = a; // アドレス+R/W (1:read) TWCR = 0b10000100; // |||||| +----- TWIE 割込は使わない // |||||+------- TWEN TWI動作許可 // ||||+-------- TWWC // |||+--------- TWSTO // ||+---------- TWSTA // |+----------- TWEA // +------------ TWINT TWINTクリア tt = 2000; // 2000 loop while(tt){ // time out? if((TWCR & (1 << TWINT))) break; // TWINT=1を待つ tt--; } } /***** TWI 終了 *****/ void twiStop(void) { TWCR = 0b10010100; // |||||| +----- TWIE 割込は使わない // |||||+------- TWEN TWI動作許可 // ||||+-------- TWWC // |||+--------- TWSTO 終了 // ||+---------- TWSTA // |+----------- TWEA // +------------ TWINT TWINTクリア } /***** TWI データ書き込み *****/ void twiWrite(uint8_t data) { uint16_t tt; // time out check counter TWDR = data; TWCR = 0b10000100; // |||||| +----- TWIE 割込は使わない // |||||+------- TWEN TWI動作許可 // ||||+-------- TWWC // |||+--------- TWSTO // ||+---------- TWSTA // |+----------- TWEA // +------------ TWINT TWINTクリア tt = 2000; // 2000 loop while(tt){ // time out? if((TWCR & (1 << TWINT))) break; // TWINT=1を待つ tt--; } } /***** TWI データ読み出し *****/ // aknk: 0:ACK, 1:NACK指定 uint8_t twiRead(uint8_t aknk) { uint16_t tt; // time out check counter uint8_t cmnd; // コマンド cmnd = 0b10000100; // |||||| +----- TWIE 割込は使わない // |||||+------- TWEN TWI動作許可 // ||||+-------- TWWC // |||+--------- TWSTO // ||+---------- TWSTA // |+----------- TWEA ←ACK,NACK // +------------ TWINT TWINTクリア if(aknk == 0) cmnd |= (1 << TWEA); // aknk=0でACK TWCR = cmnd; // コマンド tt = 2000; // 2000 loop while(tt){ // time out? if((TWCR & (1 << TWINT))) break; // TWINT=1を待つ tt--; } return TWDR; // 読み出しデータ } /*******************************/ /* 外付けEEPRON */ /*******************************/ // 書き込み完了待ちはタイマーtm_eepをチェック // tm_eep は1msタイマー割り込みでダウンカウント // タイムアップの間、他の処理ができる /***** EEPROM 1バイト書き込み *****/ void eepWrite(byte devadrs, word eeadrs, byte data) { while(tm_eep); // 書き込み時間待ち twiStart(devadrs, 1); // 書き込みstart twiWrite((byte)(eeadrs >> 8)); // MSB twiWrite((byte)(eeadrs & 0xFF)); // LSB twiWrite(data); // データ書き込み1バイト twiStop(); tm_eep = 5 + 1; // 5ms 書込みwait時間 } /***** EEPROM ページ書き込み *****/ // *data 書き込むデータを入れたバッファ // n:データ数 void eepWriteP(byte devadrs, word eeadrs, byte *data, int n) { int i; while(tm_eep); // 書き込み時間待ち twiStart(devadrs, 1); // 書き込みstart twiWrite((byte)(eeadrs >> 8)); // MSB twiWrite((byte)(eeadrs & 0xFF)); // LSB for(i = 0; i < n; i++){ // loop twiWrite(data[i]); // データ書き込み } twiStop(); tm_eep = 5 + 1; // 5ms 書込みwait時間 } /***** EEPROM 1バイト読み出し *****/ byte eepRead(byte devadrs, word eeadrs) { byte d; while(tm_eep); // 書き込み時間待ち twiStart(devadrs, 1); // 書き込みstart twiWrite((byte)(eeadrs >> 8)); // MSB twiWrite((byte)(eeadrs & 0xFF)); // LSB twiStart(devadrs, 0); // 読み出しstart d = twiRead(1); // NACK 読み出し twiStop(); return d; // 読み出した1バイト } /***** EEPROM ページ読み出し *****/ // *data 読み出しデータを書き込むバッファ // n:データ数 // 最後のデータはNAKで読み出し void eepReadP(byte devadrs, word eeadrs, byte *data, int n) { int i; byte ank; // ACK:0,NAK:1区分 最後がNAKで while(tm_eep); // 書き込み時間待ち twiStart(devadrs, 1); // 書き込みstart twiWrite((byte)(eeadrs >> 8)); // MSB twiWrite((byte)(eeadrs & 0xFF)); // LSB twiStart(devadrs, 0); // 読み出しstart for(i = 0; i < n; i++){ // loop if(i == (n - 1)) ank = 1; // 最後はNAKに else ank = 0; // 最初はACKから data[i] = twiRead(ank); // ACK,NAKで読み出し } twiStop(); } #if 0 // ★2 /***** EEPROM 1バイト書き込み *****/ void eepWrite(int deviceaddress, unsigned int eeaddress, byte data ) { int rdata = data; while(tm_eep); // 書き込み時間待ち Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.write(rdata); Wire.endTransmission(); tm_eep = 5; // 5ms 書込みwait時間 } /***** EEPROM ページ書き込み *****/ void eepWriteP(int deviceaddress, unsigned int eeaddresspage, byte* data, byte length ) { byte c; while(tm_eep); // 書き込み時間待ち Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddresspage >> 8)); // MSB Wire.write((int)(eeaddresspage & 0xFF)); // LSB for ( c = 0; c < length; c++){ Wire.write(data[c]); } Wire.endTransmission(); tm_eep = 5; // 5ms 書込みwait時間 } /***** EEPROM 1バイト読み出し *****/ byte eepRead(int deviceaddress, unsigned int eeaddress ) { byte rdata = 0xFF; while(tm_eep); // 書き込み時間待ち Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(deviceaddress,1); if (Wire.available()) rdata = Wire.read(); return rdata; } /***** EEPROM ページ読み出し *****/ void eepReadP(int deviceaddress, unsigned int eeaddress, byte *buffer, int length ) { byte c = 0; while(tm_eep); // 書き込み時間待ち Wire.beginTransmission(deviceaddress); Wire.write((int)(eeaddress >> 8)); // MSB Wire.write((int)(eeaddress & 0xFF)); // LSB Wire.endTransmission(); Wire.requestFrom(deviceaddress,length); for ( c = 0; c < length; c++ ){ if (Wire.available()) buffer[c] = Wire.read(); } } #endif /***** 24LC1025 チップアドレス *****/ // 64k x 4, 256kバイトのエリア // 512kバイトに増設 ★1 // r/wビットはアドレスに含まない // 7 6 5 4 3 2 1 0 // 1 0 1 0 B0 A1 A0 R/W const byte eep_adrs[] PROGMEM ={ 0x50, // 0:0101 0000 ブロック0 + 0 00000~ 0x54, // 1:0101 0100 ブロック1 + 0 10000~ 0x51, // 2:0101 0001 ブロック0 + 1 20000~ 0x55, // 3:0101 0101 ブロック1 + 1 30000~ 0x52, // 4:0101 0010 ブロック0 + 2 40000~★1 0x56, // 5:0101 0110 ブロック1 + 2 50000~ 0x53, // 6:0101 0011 ブロック0 + 3 60000~ 0x57, // 7:0101 0111 ブロック1 + 3 70000~ }; // ||+--- A0 // |+---- A1 // +----- B0 /***** EEPROMチップアドレスを得る ****/ // in 19bitのEEPROM アドレス ★1 // out 1バイトチップアドレス byte eepchipadrs(uint32_t adrs) { return pgm_read_byte(&eep_adrs[(adrs >> 16) & 7]); // 3→7 ★1 } /*********************************/ /* 内蔵EEPROM読み書き */ /*********************************/ /***** 記録数読み出し *****/ // 内蔵EEPROM uint32_t eprdmemcnt(void) { PB1_H; // 15pin H (!!!) return eeprom_read_dword(&EA_MEMCNT); // 4バイト PB1_L; // 15pin L (!!!) } /***** 記録数書き込み *****/ // 内蔵EEPROM void epwrmemcnt(uint32_t d) { PB1_H; // 15pin H (!!!) eeprom_update_dword(&EA_MEMCNT, d); // wirteではなくupdateで PB1_L; // 15pin L (!!!) } /****** 記録数を内蔵EEPROMにセーブ *****/ // mem_cntをEEPROMに残す void savememcnt(void) { #if 0 uint32_t d; d = eprdmemcnt(); // 現データ数 if(d != mem_cnt) epwrmemcnt(mem_cnt); // データ数を内蔵EEPROMに #endif epwrmemcnt(mem_cnt); // データ数を内蔵EEPROMに(update) f_mcntsv = 0; // 自動mem_cntセーブしない } /***************************/ /* SETUP */ /***************************/ /***** SET UP *****/ void setup() { // I/Oイニシャル PORTB = 0b00000001; // data/pull up DDRB = 0b00111110; // port指定 // |||||+---- PB0 IO8 in JP1:TX時のボーレートを115.2kにup // ||||+----- PB1 IO9 out (!!!)内蔵EEPROM処理タイミングチェック // |||+------ PB2 IO10 out (!!!)シリアル出力タイミングチェック // ||+------- PB3 IO11 out - // |+-------- PB4 IO12 out - // +--------- PB5 IO13 out (LED) PORTC = 0b00110000; // data/pull up DDRC = 0b00001111; // port指定 // |||||+---- PC0 AD0 out - // ||||+----- PC1 AD1 out - // |||+------ PC2 AD2 out - // ||+------- PC3 AD3 out - // |+-------- PC4 AD4 - EEPROM SDA // +--------- PC5 AD5 - EEPROM SC PORTD = 0b00110011; // data/pull up DDRD = 0b11001110; // port指定 // |||||||+---- PD0 IO0 in RXD // ||||||+----- PD1 IO1 out TXD // |||||+------ PD2 IO2 out 送信LED (Lでon) // ||||+------- PD3 IO3 out 記録LED (Lでon) // |||+-------- PD4 IO4 in 送信SW (Lでon) // ||+--------- PD5 IO5 in 記録開始SW (Lでon) // |+---------- PD6 IO6 out (!!!)シリアル受信タイミングチェック // +----------- PD7 IO7 out (!!!)1mS割り込みタイミングチェック // タイマー計時 MsTimer2::set(1, tm2int); // 1msサイクル割り込み処理 MsTimer2::start(); // I2C EEPOM 24LC1025 128k bytes (1024page/128bytes)を2コ ★1 // 512kバイトに増設 // EEPROMアクセスを独自のものに ★2 // Wire.begin(); // I2C // Wire.setClock(200000L); // 100kHz→200kHzに ちょい早く twiInit(); // TWIを初期化 // シリアル通信 Serial.begin(9600); // 9600BPSで // 1秒待ってLEDをオフ tm_10ms = 100; while(tm_10ms); LED_TX_OFF; // 送信LED off LED_MEM_OFF; // 記録中LED off // 記録数をチェック mem_cnt = eprdmemcnt(); // 記録データ数を内蔵EEPROMから読み出し // Serial.println(mem_cnt); f_memon = eeprom_read_byte(&EA_MEMON); // 記録中状態を復帰 } /*****************************************/ /* 記録実行処理 */ /*****************************************/ /***** 受信データ外付けEEPROM記録処理 *****/ // 受信データがあればいったんrx_bffに溜める void memrxd(void) { byte b, c; word i, k; // シリアル受信, rx_bffに溜める if(Serial.available() > 0) { // シリアルデータあり if(f_memon){ // 記録中 if(rx_cnt < sizeof(rx_bff)){ // バッファに空きあり? PD6_H; // 12pin H (!!!) c = Serial.read(); // 1文字受信 rx_bff[rx_wrp] = c; // バッファにストア rx_wrp++; if(rx_wrp >= sizeof(rx_bff)) rx_wrp = 0; rx_cnt++; // バッファ内文字数+1 PD6_L; // 12pin L (!!!) } } else{ // 記録していないとき Serial.read(); // 受信して捨てる } } // 外付けEEPROMに記録 if((f_memon != 0) && // 記録中 (tm_eep == 0) && // 書き込み待ち終了 (rx_cnt != 0) && // 受信データあり (mem_cnt < EEP_SIZE)){ // EEPROMに空きあり if((mem_cnt + rx_cnt) >= EEP_SIZE) // 最大数超過 k = EEP_SIZE - mem_cnt; else k = rx_cnt; // 書き込みデータ数 i = EEP_PAGE - (mem_cnt & (EEP_PAGE - 1)); // EEPROMページをチェック if(k > i) k = i; // ページ内書き込み可バイト数 i = sizeof(mem_bff); if(k > i) k = i; // 転送バッファ最大 for(i = 0; i < k; i++){ // 受信バッファから書き込みバッファへ mem_bff[i] = rx_bff[rx_rdp]; rx_rdp++; if(rx_rdp >= sizeof(rx_bff)) rx_rdp = 0; } rx_cnt -= k; // 受信バッファ文字数 LED_TX_ON; // 送信LED on b = eepchipadrs(mem_cnt); // チップアドレスを得る eepWriteP(b, (word)mem_cnt, mem_bff, k); // 外付けEEPROM書き込み mem_cnt += k; // データ数 f_mcntsv = 1; // mem_cntを自動セーブ tm_mcntsv = 180; // 3分 LED_TX_OFF; // 送信LED off // Serial.println(mem_cnt); } // 自動でメモリー数を内蔵EEPROMに if((f_mcntsv) && (tm_mcntsv == 0)){ // タイムアップ savememcnt(); // 記録数を内蔵EEPROMにセーブ } } /***** 記録実行区分 *****/ byte mem_exc; // 測定実行区分 #define MEM_STBY 0 // スタンバイ #define MEM_TX1 1 // 送信 /***** スタンバイ *****/ void memstby(void) { // 送信スイッチ(長押しで全データ送出) if(f.swtx || f.swtxa){ // 記録データ送信, TX短押 + TX長押 LED_TX_ON; // 送信LED点灯 f_memon = 0; // 記録停止 savememcnt(); // 記録数を内蔵EEPROMにセーブ if(f.swtx){ // TX短押:現記録データ送信 f.swtx = 0; tx_cnt = mem_cnt; // 送信データ数 } if(f.swtxa){ // TX長押:全記録データ送信 f.swtxa = 0; tx_cnt = EEP_SIZE; // 全データ数で } // JP1 onで通信速度を115.2kBPSにup if(CK_JP1){ // JP1 on? tm_1ms = 250; while(tm_1ms); // 0.25秒待ち Serial.end(); // いったん通信終了 Serial.begin(115200); // 115.2kBPSにスピードアップ } tx_ptr = 0; // 送信データポインタ mrd_cnt = 0; // EEPROM読み出しカウンタ mrd_ptr = 0; // 読み出しポインタ クリア cnt_txchr = 0; // CR出力チェックカウンタ tm_txw = 50; // 時間待ち mem_exc = MEM_TX1; // 送信処理へ return; } // 記録スイッチ短押し, mem状態トグル if(f.swmem){ // 記録開始 f.swmem = 0; f_memon ^= 1; // 記録フラグ反転 eeprom_write_byte(&EA_MEMON, f_memon); // EEPROMに保存 savememcnt(); // 記録数を内蔵EEPROMにセーブ return; } // 記録スイッチ長押し if(f.swclr){ // クリアして記録開始 f.swclr = 0; mem_cnt = 0; // 記録データ数クリア savememcnt(); // 記録数(=0)を内蔵EEPROMにセーブ rx_cnt = rx_wrp = rx_rdp = 0; // シリアル受信バッファ while(Serial.available() > 0){ // シリアルデータあれば Serial.read(); // 受信して捨てる } f_memon = 1; // 記録開始フラグセット eeprom_write_byte(&EA_MEMON, f_memon); // EEPROMに保存 return; } } /***** 記録データ送信 *****/ // EEPROMに保存された文字を送信 // CR検出ならちょっと時間待ち // tm_txwはタイマー割込でダウンカウント // cnt_txchrは文字受信で+1 // JP1 on(115.2kBPS)ならページ読み出しで void memtx1(void) { byte b, c; word k; if(tx_cnt == 0){ // 送信データなしでおわり if(CK_JP1){ // JP1 onして速度upしていた tm_1ms = 250; while(tm_1ms); // 0.25秒待ち Serial.end(); // いったん通信終了して Serial.begin(9600); // 9600BPSに戻す } tm_1ms = 250; mem_exc++; // memtx2に } else{ // データあり if(tm_txw == 0){ // タイムアップ? (CR検出時間待ち) if(CK_JP1){ // JP1 offなら115.2kBPS if(mrd_cnt == 0){ // 読み出しバッファ空 if(tx_cnt > sizeof(mrd_bff)){ // 残バイト数 mrd_cnt = sizeof(mrd_bff); // バッファ目一杯で } else{ // バッファに入れば mrd_cnt = tx_cnt; // 未送信残数で } k = EEP_PAGE - (tx_ptr & (EEP_PAGE - 1)); // EEPROMページをチェック if(mrd_cnt > k) mrd_cnt = k; // ページ内読み込み可能バイト数 LED_TX_OFF; // 送信LEDオフ b = eepchipadrs(tx_ptr); // チップアドレス eepReadP(b, (word)tx_ptr, mrd_bff, mrd_cnt); // 外付けEEPROMページ読み出し mrd_ptr = 0; // 読み出しポインタ ゼロから LED_TX_ON; // 送信LEDオン } c = mrd_bff[mrd_ptr]; // バッファから1文字 mrd_ptr++; // ポインタを進めて mrd_cnt--; // カウンタを-1 } else{ // JP1 offなら9600BPS LED_TX_OFF; // 送信LEDオフ b = eepchipadrs(tx_ptr); // チップアドレスを得る c = eepRead(b, (word)tx_ptr); // 1文字リード LED_TX_ON; // 送信LEDオン } // 1文字出力 // CR検出で時間待ちを入れる PB2_H; // (!!!)16pin Serial.write(c); // 1文字出力 PB2_L; // (!!!) if(cnt_txchr < 255) cnt_txchr++; // 文字数+1 if(c == '\r'){ // CR ? if(CK_JP1){ // JP1 onで速度upしてる(115.2k) tm_txw = cnt_txchr / 16; // 16文字で1ms } else{ // 9600BPS tm_txw = cnt_txchr; // 1文字1msでwait } cnt_txchr = 0; // 文字数クリア } tx_ptr++; // 送信データポインタを進めて tx_cnt--; // データカウンタを-1 } } // 送信SWで中断 if(f.swtx){ // 送信SW f.swtx = 0; tx_cnt = 0; // 残データ数を0に } } /***** 記録データ送信完了 *****/ void memtx2(void) { if(tm_1ms == 0){ f_memon = eeprom_read_byte(&EA_MEMON); // 記録状態を復活 LED_TX_OFF; // 送信LEDオフ mem_exc = MEM_STBY; // スタンバイに } } /********************************/ /* 記録実行テーブル */ /********************************/ /***** 記録実行 *****/ void (*memexc[])(void)={ memstby, // * 0 : スタンバイ memtx1, // * 1 : 送信 memtx2, // 2 : 送信完了 }; /**********************************/ /*  LOOP */ /**********************************/ /***** LOOP *****/ void loop() { if(f_1ms){ // 1msあり f_1ms = 0; swchk(); // スイッチ入力チェック blinkmemled(); // 記録中LED点滅処理 } memexc[mem_exc](); // 記録実行 memrxd(); // 受信データ外付けEEPROM記録処理 } /*===== end of "rxbff3a" =====*/