#include #include #include "SdFat.h" SdFat SD; #define SD_CS_PIN SS /* +-----------+ +-----------------+ | | | ARDUINO | | VIA 6522 | | NANO | | | | | | PA0 |<------ bit 0 ------>| D2 | +-------\ | PA1 |<------ bit 1 ------>| D3 D10 |----- SS ------>| \ | PA2 |<------ bit 2 ------>| D4 D11 |----- MOSI ---->| SD | | PA3 |<------ bit 3 ------>| D5 D12 |<---- MISO -----| CARD | | PA4 |<------ bit 4 ------>| D6 D13 |----- SCK ----->| | | PA5 |<------ bit 5 ------>| D7 | +--------+ | PA6 |<------ bit 6 ------>| D8 | | PA7 |<------ bit 7 ------>| D9 | | | | | | PB7 |<---- MCU_STROBE ----| D14/A0 | | PB0 |--- CPU_STROBE ----->| D15/A1 | | | | | +-----------+ +-----------------+ */ // pin definitions #define BIT0 2 #define BIT1 3 #define BIT2 4 #define BIT3 5 #define BIT4 6 #define BIT5 7 #define BIT6 8 #define BIT7 9 /* 10,11,12,13 reserved for SD card */ #define MCU_STROBE 14 #define CPU_STROBE 15 // indicates that a timeout occurred during wait() int TIMEOUT = 0; void wait(int pin, int value) { unsigned long start_time = millis(); unsigned long elapsed; if(TIMEOUT) return; while(digitalRead(pin) != value) { elapsed = millis() - start_time; if(elapsed > 500) { TIMEOUT = 1; break; } } } const int DIR_INPUT = 0; const int DIR_OUTPUT = 1; int last_dir; // remember last data port pins direction void set_data_port_direction(int dir) { // check if no need to set pins if(dir == last_dir) return; if(dir == DIR_INPUT) { pinMode(BIT0, INPUT); pinMode(BIT1, INPUT); pinMode(BIT2, INPUT); pinMode(BIT3, INPUT); pinMode(BIT4, INPUT); pinMode(BIT5, INPUT); pinMode(BIT6, INPUT); pinMode(BIT7, INPUT); } else { pinMode(BIT0, OUTPUT); pinMode(BIT1, OUTPUT); pinMode(BIT2, OUTPUT); pinMode(BIT3, OUTPUT); pinMode(BIT4, OUTPUT); pinMode(BIT5, OUTPUT); pinMode(BIT6, OUTPUT); pinMode(BIT7, OUTPUT); } // remember direction last_dir = dir; } int receive_byte_from_cpu() { // set data port pins as INPUT pins set_data_port_direction(DIR_INPUT); // both strobes are 0 // CPU deposits data byte and sets strobe high wait(CPU_STROBE, HIGH); // read the data byte int data = (digitalRead(BIT0) << 0) | (digitalRead(BIT1) << 1) | (digitalRead(BIT2) << 2) | (digitalRead(BIT3) << 3) | (digitalRead(BIT4) << 4) | (digitalRead(BIT5) << 5) | (digitalRead(BIT6) << 6) | (digitalRead(BIT7) << 7); // after reading the byte, MCU sets strobe high digitalWrite(MCU_STROBE, HIGH); // CPU now sets strobe low wait(CPU_STROBE, LOW); // and MCU sets strobe low digitalWrite(MCU_STROBE, LOW); return data; } void send_byte_to_cpu(int data) { // set data port pins as OUTPUT pins set_data_port_direction(DIR_OUTPUT); // both strobes are 0 // put byte on the data port digitalWrite(BIT0, data & 1); digitalWrite(BIT1, data & 2); digitalWrite(BIT2, data & 4); digitalWrite(BIT3, data & 8); digitalWrite(BIT4, data & 16); digitalWrite(BIT5, data & 32); digitalWrite(BIT6, data & 64); digitalWrite(BIT7, data & 128); // after depositing data byte, MCU sets strobe high digitalWrite(MCU_STROBE, HIGH); // wait for CPU to set strobe high wait(CPU_STROBE, HIGH); // tells CPU byte we are finished digitalWrite(MCU_STROBE, LOW); // wait for CPU to set strobe low wait(CPU_STROBE, LOW); } // ********************************************************************************************* // ********************************************************************************************* // ********************************************************************************************* // ********************************************************************************************* // ********************************************************************************************* // ********************************************************************************************* // ********************************************************************************************* // ********************************************************************************************* const int CMD_READ = 0; const int CMD_WRITE = 1; const int CMD_DIR = 2; const int CMD_DEL = 11; const int CMD_LS = 12; const int CMD_CD = 13; const int CMD_MKDIR = 14; const int CMD_PWD = 19; const int CMD_RMDIR = 15; const int CMD_TEST = 20; const int ERR_RESPONSE = 255; const int OK_RESPONSE = 0; char filename[64]; char tmp[64]; char cd_path[64]; // fixed messages const char *FILE_NOT_FOUND = "?FILE NOT FOUND"; const char *CANT_OPEN_FILE = "?CAN'T OPEN FILE"; const char *ALREADY_EXISTS = "?FILE ALREADY EXISTS"; const char *CANT_CREATE_FILE = "?CAN'T CREATE FILE"; const char *WRITE_ERROR = "?WRITE ERROR"; const char *CANT_DELETE_FILE = "?CAN'T DELETE FILE"; const char *FILE_DELETED = " DELETED"; const char *DIR_NOT_FOUND = "?DIR NOT FOUND"; const char *CANT_REMOVE_DIR = "?CAN'T REMOVE DIR"; const char *DIR_REMOVED = " (DIR) REMOVED"; const char *DIR_ALREADY_EXISTS = "?DIR ALREADY EXISTS"; const char *CANT_MAKE_DIR = "?CAN'T MAKE DIR"; const char *DIR_CREATED = " (DIR) CREATED"; const char *CANT_CD_DIR = "?CAN'T CHANGE DIR"; const char *NOT_A_DIRECTORY = "?NOT A DIRECTORY"; void setup() { // debug on serial Serial.begin(9600); Serial.println(F("SDCARD library: SDFat.h")); // initialize SD card if (!SD.begin(SD_CS_PIN)) Serial.println(F("SD card initialization failed")); else Serial.println(F("SD card initialized")); // control pins setup pinMode(CPU_STROBE, INPUT); pinMode(MCU_STROBE, OUTPUT); digitalWrite(MCU_STROBE, LOW); // data pins setup last_dir = -1; // no previous data direction set_data_port_direction(DIR_INPUT); MatchState ms; char buf [100] = { "The quick " }; ms.Target (buf); char result = ms.Match ("f.x"); if(result >0) { Serial.println("match!"); } // set working directory to root strcpy(cd_path, "/"); } // ************************************************************************************** // ************************************************************************************** // ********************************* @CMD_DIR ****************************************** // ************************************************************************************** // ************************************************************************************** /* // recursive print directory void printDirectory(File dir, int numTabs) { while (true) { if(TIMEOUT) break; File entry = dir.openNextFile(); if (! entry) { // no more files break; } // indentazione delle sottodirectory for (uint8_t i = 0; i < numTabs; i++) { Serial.print('\t'); send_byte_to_cpu(32); send_byte_to_cpu(32); send_byte_to_cpu(32); } // nome del file char *msg; entry.getName(filename, 64); msg = filename; Serial.print(msg); for(int t=0; t> 8) & 0xFF); if(TIMEOUT) return; Serial.println(F("file size sent to CPU")); int bytes_sent = 0; while(myFile.available() && !TIMEOUT) { send_byte_to_cpu(myFile.read()); if(!TIMEOUT) bytes_sent++; } myFile.close(); if(TIMEOUT) { Serial.print(F("timeout, bytes sent: ")); Serial.println(bytes_sent); return; } Serial.println(F("file read ok")); } void send_string_to_cpu(char *msg) { while(1) { int c = *msg++; send_byte_to_cpu(c); if(TIMEOUT) break; if(c==0) break; } } // come send_string_to_cpu ma senza lo zero finale void print_string_to_cpu(char *msg) { while(1) { int c = *msg++; if(c==0) break; send_byte_to_cpu(c); if(TIMEOUT) break; } } void receive_string_from_cpu(char *msg) { while(1) { int c = receive_byte_from_cpu(); if(TIMEOUT) break; *msg++ = c; if(c==0) break; } } // ************************************************************************************** // ************************************************************************************** // ********************************* CMD_WRITE ***************************************** // ************************************************************************************** // ************************************************************************************** int receive_word_from_cpu() { int lo = receive_byte_from_cpu(); int hi = receive_byte_from_cpu(); int data = lo | (hi << 8); return data; } void comando_write() { Serial.println(F("command CMD_WRITE received from CPU")); // reads filename as 0 terminated string receive_string_from_cpu(filename); if(TIMEOUT) return; Serial.print(F("file to write: ")); Serial.println(filename); if(SD.exists(filename)) { Serial.println(F("file already exist")); send_byte_to_cpu(ERR_RESPONSE); send_string_to_cpu(ALREADY_EXISTS); return; } // open the file File myFile = SD.open(filename, FILE_WRITE); if(!myFile) { Serial.println(F("error opening file for write")); send_byte_to_cpu(ERR_RESPONSE); send_string_to_cpu(CANT_CREATE_FILE); return; } Serial.println(F("file opened for write on the SD card")); // ok response send_byte_to_cpu(OK_RESPONSE); if(TIMEOUT) return; Serial.println(F("first ok response sent to CPU")); // get file size low and high byte int size = receive_word_from_cpu(); if(TIMEOUT) return; Serial.print(F("received file size: ")); Serial.println(size); int error = 0; for(int t=0;t=1;t--) { int c = filename[t]; filename[t] = 0; if(c == '/') break; } } // CD / if(filename[0] == '/' && filename[1] == 0) { // changes to the root directory if(SD.chdir()) { // set root working directory strcpy(cd_path, filename); Serial.print(F("dir changed to:")); Serial.println(cd_path); send_byte_to_cpu(OK_RESPONSE); return; } else { Serial.println(F("error changing dir")); send_byte_to_cpu(ERR_RESPONSE); send_string_to_cpu(CANT_CD_DIR); return; } } // CD dirname if(SD.chdir(filename)) { // update working directory if(filename[0] == '/') { strcpy(cd_path, filename); // path is absolute, replace cwd } else { // path is relative, append to cwd if(cd_path[0] == '/' && cd_path[1] == 0) { cd_path[0] = 0; // avoid the double slash ("//DIR") when cwd is root } sprintf(tmp, "%s/%s", cd_path, filename); strcpy(cd_path, tmp); } Serial.print(F("dir changed to:")); Serial.println(cd_path); send_byte_to_cpu(OK_RESPONSE); return; } // errors send_byte_to_cpu(ERR_RESPONSE); // check if the directory exists if(!SD.exists(filename)) { Serial.println(F("dir not found")); send_string_to_cpu(DIR_NOT_FOUND); return; } File myFile = SD.open(filename); bool isDir = myFile.isDirectory(); myFile.close(); if(!isDir) { Serial.println(F("not a directory")); send_string_to_cpu(NOT_A_DIRECTORY); } else { Serial.println(F("error changing dir")); send_string_to_cpu(CANT_CD_DIR); } } // ************************************************************************************** // ************************************************************************************** // ********************************* @CMD_PWD ******************************************* // ************************************************************************************** // ************************************************************************************** void comando_pwd() { Serial.println(F("command PWD received from CPU")); send_string_to_cpu(cd_path); } // ************************************************************************************** // ************************************************************************************** // ********************************* LOOP ********************************************** // ************************************************************************************** // ************************************************************************************** void loop() { TIMEOUT = 0; int data = receive_byte_from_cpu(); if(TIMEOUT) return; unsigned long start_time = millis(); if(data == CMD_READ) comando_read(); else if(data == CMD_WRITE) comando_write(); else if(data == CMD_DEL) comando_del(); else if(data == CMD_RMDIR) comando_rmdir(); else if(data == CMD_MKDIR) comando_mkdir(); else if(data == CMD_CD) comando_cd(); else if(data == CMD_PWD) comando_pwd(); else if(data == CMD_DIR) comando_dir(data); else if(data == CMD_LS) comando_dir(data); else if(data == CMD_TEST) { while(!TIMEOUT) { int data = receive_byte_from_cpu(); send_byte_to_cpu(data ^ 0xFF); } } else { Serial.print(F("unknown command ")); Serial.print(data); Serial.println(F(" received")); } Serial.print(F("command processing time: ")); Serial.println(millis() - start_time); if(TIMEOUT) Serial.println(F("TIMEOUT during command")); }