Hardware components | ||||||
![]() |
| × | 1 | |||
![]() |
| × | 1 | |||
![]() |
| × | 1 |
This is a work in progress project.
Arduino is great, I love it, is the "Lego" of electronics and automation. Here I am with this project: it puts together many MCU boards to compose a network of processors, NetP is its name. Boards communicate through i2c bus. I used Arduino Mini Pro boards working at 3.3V. You need a USB to serial FTDI board to pass sketches from Arduino IDE to Mini Pros. For the keyboard I had to use a TTL level converter from 3.3V to 5V.
Actually many things are already working and others still to be done. Others are to be "invented" :-) as per our wishes.
What is already done:The most evident part is the console: a keyboard and a scrolling display to interact with the local MCU Netp0 (Console) and through it to interact with other members of the local i2c network: Netp1 (SD), Netp2 (Updater) and Netp3 (Clock), etc.
Instead to use the display and the keyboard of the console you can connect a smartphone with bluetooth and do everything remotely from there; for this I set perfectly the app Serial Bluetooth Terminal 1.31 but you could use also other apps.
Every Netp MCU member got a specific i2c bus address (0x0a), a name (CONSOLE) an ID (p0) and a number (0). Of course other components can be present on the i2c bus: actually there are only an EEPROM and a Real Time Clock board. We must use a different i2c address for every member or component.
The system would be plug&play. Yes, you could connect a new Netp member and it will be recognised in the network (see "scan" command).
CONSOLE (p0) functionality:- scan: scan [inquiry i2c bus, i.e. scan, returns a list of active addresses on the bus in form "DDD (0xEE)"... ends with "'n' found"]
- ckpower: ckpower [inquiry power situation, i.e. ckpower, returns "v3=3.3 v5=5.0 vraw=7.0-12.0"]
- ?: ? [ask for the list of commands, i.e. ?, returns a list of available commands on board and the free memory]
- reset: reset [force the MPU to reset, i.e. reset]
- <pxname> <cmd>: [sends <cmd> to the processor <pxname>, i.e. SD dir /, returns result of <cmd> from processor <pxname>]
"Scan" command is executed every 30 seconds to allow plug&play. To know who is available just execute "scan" command to see names and addresses. To know what commands are implemented on the console just execute "?" command. To know what commands are implemented on SD member just execute "p1 ?" command. To have the list of files on SD just execute "p1 dir /"... and so on.
SD (p1) functionality:- ?: ? [ask for help, i.e. ?, returns a list of available commands on board and free memory]
- mw/mwa: mw <FileName>=<Value> [writes/modifies Value in file name, i.e. mw temp01=24 (FileName=Value), returns "written"] (mwa will append Value to the file)
- mr/mra: mr <FileName> [reads Value from corrisponding file name, i.e. mr temp01 (FileName is temp01, Value is 24, returns 'Value' or "not found"] (mra will read multilines Value from the file)
- reset: reset [resets MPU, i.e. reset]
- dir: dir <path> [reads file names starting from 'path', i.e. dir /], returns a list of file 'names' and 'size'... ends with 'n found']
- mkdir: mkdir <dirname> [build a new directory (and also relative subdirectories) i.e. mkdir /music, sdmkdir /logic/params/binary, returns "built" or "error"]
- rmdir: rmdir <dirname> [delete a dir, i.e. rmdir /music, returns "removed" or "error or not empty" ]
- rename: rename <OldFileName> <NewFileName> [renames a file, i.e. rename myfile.txt bestfile.txt, returns "renamed" or "not found"]
- del: del <FileName> [delete a file, i.e. del myfile.txt, returns "deleted" or "not found"]
- type: type <FileName> <Mode> [reads a file and displays in mode 0=CHR, 1=BIN, 2=HEX, i.e. type myfile.txt CHR, returns the content of the file... and filesize 'n' and bytes red 'n' at the end]
- eeupl: eeupl <Filename> [read a file and upload it to the EEPROM, write and verify all data, i.e. eeupl /mysketch.hex, returns upload, written, verified...]
Due to lack of memory some commands are disabled; I kept just the ones I really needed. My experience says to not force the use of memory near to the max otherwise you will have unpredictable behaviour or the MCU. On SD sketch I think to have squeezed the code to spare memory as possible. Maybe something can be done even better.
mw and mr commands operate on /MEMORY/ subdirectory, mwa and mra operates on /LOG/ subdirectory.
UPDATER (p2) functionality:- ?: ? [ask for help, i.e. ?, returns a list of available commands on board and free memory]
- reset: reset [resets MPU, i.e. reset]
- ?: ? [ask for help, i.e. ?, returns a list of available commands on board and free memory]
- reset: reset [resets MPU, i.e. reset]
- red: red <Mode> [switch on or off the red LED, i.e. red on, returns "ON" or "OFF"]
- green: green <Mode> [switch on or off the green LED, i.e. green on, returns "ON" or "OFF"]
- dht: dht [get temperature and humidity from DHT board, i.e. DHT, returns the values]
- gettemp: gettemp [get temperature from RTC board, i.e. gettemp, returns the temperature value]
- gettime: gettime [get time from RTC board, i.e. gettime, returns the time value as per DD/MM/YYYY HH:MM:SS]
- settime: settime [set the time to RTC board, i.e. settime 31/12/2018 10:20:30, returns the time value as per DD/MM/YYYY HH:MM:SS]
- 4 x Arduino Mini Pro 3.3v
- Micro SD Card adapter
- MicroSD memory card
- RTC zs-042 module
- DHT-11 sensor
- Protoboard power supply from 7-12V to 3.3V and 5V
- 4 x protoboards
- Red LED
- Green LED
- 2 x 470uF 25V capacitors
- 100nF capacitor
- HC05 bluetooth module
- FTDI USB-Serial converter
- Display 2.4" TFT LCD 240x320 RGB, driver IC ILI9341
- USB mini keyboard
- TTL level converter 3.3V <-> 5V for keyboard USB
- USB female + cable
- Active buzzer
- EEPROM i2c 1024
- Push button
- 100 ohm resistor
- 4 x 5k1 ohm resistors
- 2k2 ohm resistor
- 6k8 resistor
- 2 x 120 ohm resistor
- Many wires...
Netpx members communicate between them by the way of i2c BUS (Wire.h library) using a custom protocol made by messages and events.
From the console keyboard when you write a command, i.e. "SD dir /", first of all the name "SD" is converted into the real address (i.e. 0x0b) looking at netRegisterNames[] matrix, then sent to the BUS using askCommandOnPx(). On the other side is generated an event receiveEvent() and executed locally the requested command and its data sent back. The ID of these messages is chr(7) BEL byte.
Another message is sent to the BUS using whois() and Wire.requestFrom(), during scan command, for requesting the name and other information to a potential Netpx member at a specific address i.e. 0x0c. If no proper answer back it is considered as "other device". On the other side is generated an event netWhoIsEvent(). The ID of these messages is chr(5) ENQ byte.
What is to do (my wish list):First of all I would have a commands request queue: actually from the console you can send a command to be executed and wait for it until it is ended. If you send quickly two or more commands in a row probably all command after the first one will be ignored. So with this new functionality all commands will be written in a commands queue and executed one at a time in the right order.
Second I would have a scheduler, a list of commands to be executed at a specific time or every specific time, etc. This file as a list of commands should be editable interactively from the console.
Third, the most ambitious wish, is to store updated/new sketches in a specific directory of the SD and let the UPDATER provide to pass them to the EEPROM before to be installed to the final destination MCU. The destination MCU to be updated should provide by itself to read EEPROM and autoupdate; for this function is needed to modify the normal bootloader...
Any ideas or suggestions?When I have news, improvements, new parts, new ideas, etc. I will inform you in these pages. Please let me know what do you thing about this work in progress project.
Enjoy it!
News / Updates:19.03.2025: it looks like the Fritzing schematic is wrong regarding buzzer connection. The right one is pin 7 (not the 10)...
/* Arduino Net-P (i2c processors network) by Zonca Marco 2020
* 'netMyNAME' ("CLOCK ") max 8 char, 'netMyID' (p9) max 2 char,
* address='netMyAddress' (0x16) max 0xFF, 'netMyPx' (9)
*
* implemented commands (* = to do): HELP | ?, dht, gettemp, gettime, settime, red, green
*
*/
#include <Wire.h>
#include <ds3231.h> // RTC real time clock
#include <dht.h>
const int netMyPx = 9; // netMyPx 0-9
const int netMyAddress = 0x16; // i2c address 0x16=HEX 22=DEC
const char *netMyID = "p9"; // netMyID
const char *netMyNAME = "CLOCK "; // netMyNAME
const int GreenLedPin=8;
const int RedLedPin=9;
const int DHTPin=14;
const int ResetPin=17; // A3 put low for reset
char _CR[2]=""; // CR
char _BEL[2]=""; // BEL
char _ENQ[2]=""; // ENQ
char _ACK[2]=""; // ACK
char _SPACE[2]=""; // SPACE
char _MYADDR[2]=""; // netMyAddress
char lineString[65]="";
char recCommand[65]="";
byte recAddress=0;
byte recType=0;
char data[2]="";
bool isNetDataWaiting=false;
bool isKnownCommand = false;
bool isRedOn=false;
bool isGreenOn=false;
bool isBusy=false;
struct ts t; // RTC
dht DHT; // HG + Temp sensor
void setup() {
//Serial.begin(38400);
Wire.begin(netMyAddress);
Wire.onReceive(receiveEvent); // i2c event
Wire.onRequest(netWhoIsEvent); // i2c whois
_CR[0] = 13; // CR
_BEL[0] = 7; // BEL
_ENQ[0] = 5; // ENQ
_ACK[0] = 6; // ACK
_SPACE[0] = 32; // SPACE
_MYADDR[0] = netMyAddress;
pinMode(GreenLedPin, OUTPUT);
pinMode(RedLedPin, OUTPUT);
digitalWrite(RedLedPin,LOW);
digitalWrite(GreenLedPin,LOW);
DS3231_init(DS3231_INTCN); // RTC
DHT.read11(DHTPin); // DHT
} // end setup()
void loop() {
if (isNetDataWaiting == true) {
execNetCommand();
}
} // end loop()
void execNetCommand() { // executes received command
isBusy=true;
char park[65]="";
char command[65]="";
if (recType == _BEL[0]) { // char(7) = BEL command type
isKnownCommand=false;
if (s_compare(recCommand,"")==0) { // empty command just do nothing
isKnownCommand=true;
prompt();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,3); // red
if (s_compare(park,"red ") == 0) {
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),4,strlen(recCommand)-1);
if (strcmp(command, "on") == 0 || strcmp(command, "off") == 0 || strcmp(command, "?") == 0) {
isKnownCommand=true;
ledred(command);
}
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,5); // green
if (s_compare(park,"green ") == 0) {
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),6,strlen(recCommand)-1);
if (strcmp(command, "on") == 0 || strcmp(command, "off") == 0 || strcmp(command, "?") == 0) {
isKnownCommand=true;
ledgreen(command);
}
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,4); // reset
if (s_compare(park,"reset") == 0) {
isKnownCommand=true;
reset();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,2); // dht
if (s_compare(park,"dht") == 0) {
isKnownCommand=true;
dht();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,6); // gettemp
if (s_compare(park,"gettemp") == 0) {
isKnownCommand=true;
gettemp();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,6); // gettime
if (s_compare(park,"gettime") == 0) {
isKnownCommand=true;
gettime();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,7); // settime
if (s_compare(park,"settime ") == 0) {
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),8,strlen(recCommand)-1);
if (strlen(command) == 19) {
isKnownCommand=true;
settime(command);
}
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,0); // ?
if (s_compare(park,"?") == 0) {
isKnownCommand=true;
help();
}
if (isKnownCommand == false) {
s_assign(lineString,"unknown cmd",sizeof(lineString));
dispLine();
prompt();
}
} // endif recType
s_clear(recCommand,sizeof(recCommand));
recType=0;
recAddress=0;
isNetDataWaiting=false;
isBusy=false;
} // end execNetCommand()
void reset() { // ------------------------------------------------------------ RESET
analogWrite(ResetPin,LOW);
}
void help() { // ---------------------------------------------- HELP
s_assign(lineString, "red <on off ?>", sizeof(lineString));
dispLine();
s_assign(lineString, "green <on off ?>", sizeof(lineString));
dispLine();
s_assign(lineString, "dht", sizeof(lineString));
dispLine();
s_assign(lineString, "gettemp", sizeof(lineString));
dispLine();
s_assign(lineString, "gettime", sizeof(lineString));
dispLine();
s_assign(lineString, "settime <DD/MM/YYYY HH:MM:SS>", sizeof(lineString));
dispLine();
s_assign(lineString, "reset", sizeof(lineString));
dispLine();
sprintf(lineString,"(free=%d)",s_freemem());
dispLine();
prompt();
} // end help()
void ledred(const char *_s) { // ---------------------------------------------- RED
if (strcmp(_s, "on")==0) {
digitalWrite(RedLedPin,HIGH);
isRedOn=true;
}
if (strcmp(_s, "off")==0) {
digitalWrite(RedLedPin,LOW);
isRedOn=false;
}
if (isRedOn) {
sprintf(lineString, "%s","ON");
} else {
sprintf(lineString, "%s","OFF");
}
dispLine();
prompt();
} // end ledred()
void ledgreen(const char *_s) { // ---------------------------------------------- GREEN
if (strcmp(_s, "on")==0) {
digitalWrite(GreenLedPin,HIGH);
isGreenOn=true;
}
if (strcmp(_s, "off")==0) {
digitalWrite(GreenLedPin,LOW);
isGreenOn=false;
}
if (isGreenOn) {
sprintf(lineString, "%s","ON");
} else {
sprintf(lineString, "%s","OFF");
}
dispLine();
prompt();
} // end ledgreen()
void dht() { // ---------------------------------------------- DHT
float temp=0;
int iintt=0;
int idect=0;
int iinth=0;
int idech=0;
DHT.read11(DHTPin); // DHT
temp = DHT.temperature; // read DHT temp C
iintt=temp;
idect=float((temp-iintt)*100);
temp = DHT.humidity; // read DHT humidity
iinth=temp;
idech=float((temp-iinth)*100);
sprintf (lineString, "%d.%dC %d.%d", iintt, idect, iinth, idech);
s_concat(lineString,"%",sizeof(lineString));
dispLine();
prompt();
} // end gettemp()
void gettemp() { // ---------------------------------------------- GETTEMP
float temp=0;
int iint=0;
int idec=0;
temp = DS3231_get_treg(); // read RTC temp C
iint=temp;
idec=float((temp-iint)*100);
sprintf (lineString, "%d.%dC", iint, idec);
dispLine();
prompt();
} // end gettemp()
void gettime() { // ---------------------------------------------- GETTIME
DS3231_get(&t); // read RTC date & time
sprintf(lineString, "%02d/%02d/%04d %02d:%02d:%02d", t.mday, t.mon, t.year, t.hour, t.min, t.sec);
dispLine();
prompt();
} // end gettime()
void settime(const char* _s) { // ---------------------------------------------- SETTIME
char park[5]="";
s_substring(park, sizeof(park), _s, strlen(_s), 0,1);
t.mday=atoi(park);
s_substring(park, sizeof(park), _s, strlen(_s), 3,4);
t.mon=atoi(park);
s_substring(park, sizeof(park), _s, strlen(_s), 6,9);
t.year=atoi(park);
s_substring(park, sizeof(park), _s, strlen(_s), 11,12);
t.hour=atoi(park);
s_substring(park, sizeof(park), _s, strlen(_s), 14,15);
t.min=atoi(park);
s_substring(park, sizeof(park), _s, strlen(_s), 17,18);
t.sec=atoi(park);
DS3231_set(t); // write RTC
gettime(); // answer with new time
} // end settime()
void prompt() { // prompt, ready for commands
sprintf(lineString,"%d>\r",netMyPx);
dispLine();
} // end prompt()
void dispLine() { // print information
s_concat(lineString, _CR, sizeof(lineString));
txBackToSender(); // tx
s_clear(lineString, sizeof(lineString));
delay(100);
} // end dispLine()
void receiveEvent(int howMany) { // i2c event incoming requests
if (isBusy==false) {
int counter=0;
s_clear(recCommand, sizeof(recCommand)); // sender command
recAddress=0; // sender address
recType=0; // sender cmd type
if (howMany == 0) { // ignores empty requests
isNetDataWaiting=false;
} else {
while (Wire.available()) {
data[0]=Wire.read();
if (counter==0) { recType = data[0]; } // 1st char = cmd type
if (counter==1) { recAddress = data[0]; } // 2nd char = sender address
if (counter >1) { // other chars = command
s_concat(recCommand, data, sizeof(recCommand));
}
counter++;
}
isNetDataWaiting=true;
}
}//endisBusy
} // end receiveEvent()
void netWhoIsEvent() { // i2c event: 11 bytes = 1=char(5) ENQ, 2-9=netMyNAME 10=netMyPx 11=netMyAddress
if (isBusy==false) {
char ccommand[65]="";
char park[3]="";
s_assign(ccommand, _ENQ, sizeof(ccommand)); // ENQ
s_concat(ccommand, netMyNAME, sizeof(ccommand)); // netMyNAME
s_concat(ccommand, itoa(netMyPx,park,10), sizeof(ccommand)); // netMyPx
s_concat(ccommand, _MYADDR, sizeof(ccommand)); // netMyAddress
Wire.write(ccommand);
}
} // end netWhoIsEvent()
void txBackToSender() { // tx back to sender
char ccommand[65]="";
s_assign(ccommand, _ACK, sizeof(ccommand)); // ACK=answer data
s_concat(ccommand, _MYADDR, sizeof(ccommand)); // netMyAddress
s_concat(ccommand, lineString, sizeof(ccommand)); // data
Wire.beginTransmission (recAddress);
Wire.write (ccommand);
Wire.endTransmission (true);
} // end txBackToSender()
//------------------------------------------------------------------------- CLEAR
void s_clear(char *dest_source_string, const int dest_sizeof) { // fills-up with NUL=chr(0)
memset(dest_source_string, 0, dest_sizeof);
} // end s_clear()
//------------------------------------------------------------------------- ASSIGN
bool s_assign(char *dest_string, const char *source_string, const int dest_sizeof) { // copies source to dest
int _LenS=strlen(source_string); // how many bytes
if (_LenS > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcpy(dest_string, source_string);
return false; // ok 0
}
} // end s_assign()
//------------------------------------------------------------------------- SUBSTRING
bool s_substring(char *dest_string, const int dest_sizeof, const char *source_string,
const int source_sizeof, const int source_from, const int source_to) { // copies source(from, to) to dest
if ((source_from < 0) || (source_to < source_from) || ((source_to - source_from + 1) > (dest_sizeof - 1))
|| (source_to >= (source_sizeof-1)) || ((source_to - source_from + 1) > (strlen(source_string)))) {
dest_string[0]=0; // NUL
return true; // err 1
} else {
int _Count=0;
for (int i=source_from;i<(source_to+1);i++) {
dest_string[_Count]=source_string[i];
_Count++;
}
dest_string[_Count]=0; // ends with NUL
return false; // ok 0
}
} // end s_substring()
//------------------------------------------------------------------------- CONCAT
bool s_concat(char *dest_string, const char *source_string, const int dest_sizeof) { // append source to dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if ((_LenS + _LenD) > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcat(dest_string, source_string);
return false; // ok 0
}
} // end s_concat()
//------------------------------------------------------------------------- COMPARE
bool s_compare(const char *dest_string, const char *source_string) { // compares source with dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if (_LenS != _LenD) { // different length
return true; // are different 1
} else {
if (strcmp(dest_string, source_string) == 0) {
return false; // are the same 0
} else {
return true; // are different 1
}
}
} // end s_compare()
//------------------------------------------------------------------------- FREEMEM
int s_freemem() {
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);
} // end s_freemem()
/* Arduino Net-P (i2c processors network) by Zonca Marco 2020
* 'netMyNAME' ("UPDATER ") max 8 char, 'netMyID' (p8) max 2 char,
* address='netMyAddress' (0x15) max 0xFF, 'netMyPx' (8)
*
* implemented commands (* = to do): ?, reset
*
*/
#include <Wire.h>
const int netMyPx = 8; // netMyPx 0-9
const int netMyAddress = 0x15; // i2c address 0x15=HEX 21=DEC
const char *netMyID = "p8"; // netMyID
const char *netMyNAME = "UPDATER "; // netMyNAME
const int ResetPin=17; // A3 put low for reset
char _CR[2]=""; // CR
char _BEL[2]=""; // BEL
char _ENQ[2]=""; // ENQ
char _ACK[2]=""; // ACK
char _SPACE[2]=""; // SPACE
char _MYADDR[2]=""; // netMyAddress
char lineString[65]="";
char recCommand[65]="";
byte recAddress=0;
byte recType=0;
char data[2]="";
bool isNetDataWaiting=false;
bool isKnownCommand = false;
bool isBusy=false;
void setup() {
//Serial.begin(38400);
Wire.begin(netMyAddress);
Wire.onReceive(receiveEvent); // i2c event
Wire.onRequest(netWhoIsEvent); // i2c whois
_CR[0] = 13; // CR
_BEL[0] = 7; // BEL
_ENQ[0] = 5; // ENQ
_ACK[0] = 6; // ACK
_SPACE[0] = 32; // SPACE
_MYADDR[0] = netMyAddress;
} // end setup()
void loop() {
if (isNetDataWaiting == true) {
execNetCommand();
}
} // end loop()
void execNetCommand() { // executes received command
isBusy=true;
char park[65]="";
if (recType == _BEL[0]) { // char(7) = BEL command type
isKnownCommand=false;
if (s_compare(recCommand,"")==0) { // empty command just do nothing
isKnownCommand=true;
prompt();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,4); // reset
if (s_compare(park,"reset") == 0) {
isKnownCommand=true;
reset();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,0); // ?
if (s_compare(park,"?") == 0) {
isKnownCommand=true;
sdhelp();
}
if (isKnownCommand == false) {
s_assign(lineString,"unknown command",sizeof(lineString));
dispLine();
prompt();
}
} // endif recType
s_clear(recCommand,sizeof(recCommand));
recType=0;
recAddress=0;
isNetDataWaiting=false;
isBusy=false;
} // end execNetCommand()
void reset() { // ------------------------------------------------------------ RESET
analogWrite(ResetPin,LOW);
}
void sdhelp() { // ---------------------------------------------- HELP
s_assign(lineString, "reset", sizeof(lineString));
dispLine();
sprintf(lineString,"(free=%d)",s_freemem());
dispLine();
prompt();
} // end help()
void prompt() { // prompt, ready for commands
sprintf(lineString,"%d>",netMyPx);
dispLine();
} // end prompt()
void dispLine() { // print information
s_concat(lineString, _CR, sizeof(lineString));
txBackToSender(); // tx
s_clear(lineString, sizeof(lineString));
delay(100);
} // end dispLine()
void receiveEvent(int howMany) { // i2c event incoming requests
if (isBusy==false) {
int counter=0;
s_clear(recCommand, sizeof(recCommand)); // sender command
recAddress=0; // sender address
recType=0; // sender cmd type
if (howMany == 0) { // ignores empty requests
isNetDataWaiting=false;
} else {
while (Wire.available()) {
data[0]=Wire.read();
if (counter==0) { recType = data[0]; } // 1st char = cmd type
if (counter==1) { recAddress = data[0]; } // 2nd char = sender address
if (counter >1) { // other chars = command
s_concat(recCommand, data, sizeof(recCommand));
}
counter++;
}
isNetDataWaiting=true;
}
}//endisBusy
} // end receiveEvent()
void netWhoIsEvent() { // i2c event: 11 bytes = 1=char(5) ENQ, 2-9=netMyNAME 10=netMyPx 11=netMyAddress
if (isBusy==false) {
char ccommand[65]="";
char park[3]="";
s_concat(ccommand, _ENQ, sizeof(ccommand)); // ENQ
s_concat(ccommand, netMyNAME, sizeof(ccommand)); // netMyNAME
s_concat(ccommand, itoa(netMyPx,park,10), sizeof(ccommand)); // netMyPx
s_concat(ccommand, _MYADDR, sizeof(ccommand)); // netMyAddress
Wire.write(ccommand);
}
} // end netWhoIsEvent()
void txBackToSender() { // tx back to sender
char ccommand[65]="";
s_assign(ccommand, _ACK, sizeof(ccommand)); // ACK=answer data
s_concat(ccommand, _MYADDR, sizeof(ccommand)); // netMyAddress
s_concat(ccommand, lineString, sizeof(ccommand)); // data
Wire.beginTransmission (recAddress);
Wire.write (ccommand);
Wire.endTransmission (true);
} // end txBackToSender()
//------------------------------------------------------------------------- CLEAR
void s_clear(char *dest_source_string, const int dest_sizeof) { // fills-up with NUL=chr(0)
memset(dest_source_string, 0, dest_sizeof);
} // end s_clear()
//------------------------------------------------------------------------- ASSIGN
bool s_assign(char *dest_string, const char *source_string, const int dest_sizeof) { // copies source to dest
int _LenS=strlen(source_string); // how many bytes
if (_LenS > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcpy(dest_string, source_string);
return false; // ok 0
}
} // end s_assign()
//------------------------------------------------------------------------- SUBSTRING
bool s_substring(char *dest_string, const int dest_sizeof, const char *source_string,
const int source_sizeof, const int source_from, const int source_to) { // copies source(from, to) to dest
if ((source_from < 0) || (source_to < source_from) || ((source_to - source_from + 1) > (dest_sizeof - 1))
|| (source_to >= (source_sizeof-1)) || ((source_to - source_from + 1) > (strlen(source_string)))) {
dest_string[0]=0; // NUL
return true; // err 1
} else {
int _Count=0;
for (int i=source_from;i<(source_to+1);i++) {
dest_string[_Count]=source_string[i];
_Count++;
}
dest_string[_Count]=0; // ends with NUL
return false; // ok 0
}
} // end s_substring()
//------------------------------------------------------------------------- CONCAT
bool s_concat(char *dest_string, const char *source_string, const int dest_sizeof) { // append source to dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if ((_LenS + _LenD) > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcat(dest_string, source_string);
return false; // ok 0
}
} // end s_concat()
//------------------------------------------------------------------------- COMPARE
bool s_compare(const char *dest_string, const char *source_string) { // compares source with dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if (_LenS != _LenD) { // different length
return true; // are different 1
} else {
if (strcmp(dest_string, source_string) == 0) {
return false; // are the same 0
} else {
return true; // are different 1
}
}
} // end s_compare()
//------------------------------------------------------------------------- FREEMEM
int s_freemem() {
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);
} // end s_freemem()
/* Arduino Net-P (i2c processors network) by Zonca Marco 2020
* 'netMyNAME' ("CONSOLE ") max 8 char, 'netMyID' (p0) max p9, address='netMyAddress' max 0xFF, 'netMyPx' (0)
*
* implemented commands (* = to do): scan, ckpower, ?, <pxname> <cmd>, reset
*
* scan: scan [inquiry i2c bus,
* i.e. scan
* returns a list of active addresses on the bus in form "DDD (0xEE)"...
* ends with "'n' found"]
* ckpower: ckpower [inquiry power situation
* i.e. ckpower
* returns "v3=3.3 v5=5.0 vraw=7.0-12.0"]
* ?: ? [ask for the list of commands
* i.e. ?
* returns a list of available commands on board]
* reset: reset [force the MPU to reset
* i.e. reset]
*
* <pxname> <cmd>: [sends <cmd> to the processor <pxname>
* i.e. SD dir /
* returns result of <cmd> from processor <pxname>]
*
*/
#include <Adafruit_GFX_AS.h> // Core graphics library customized
#include <Adafruit_ILI9341_AS.h> // Hardware-specific library customized
#include <SPI.h>
#include <SoftwareSerial.h>
#include <Wire.h>
#include <NewTone.h>
#include <PS2Keyboard.h>
// tft pins used for the MINI PRO, we must use hardware SPI
#define _sclk 13
#define _miso 12 // Not used
#define _mosi 11
#define _cs 10
#define _rst 8
#define _dc 9
// Must use hardware SPI for speed
Adafruit_ILI9341_AS tft = Adafruit_ILI9341_AS(_cs, _dc, _rst);
// The scrolling area must be a integral multiple of TEXT_HEIGHT
#define TEXT_HEIGHT 16 // Height of text to be printed and scrolled
#define BOT_FIXED_AREA 0 // Number of lines in bottom fixed area (lines counted from bottom of screen)
#define TOP_FIXED_AREA 16 // Number of lines in top fixed area (lines counted from top of screen)
#define btTX 4 // to "TX-O" pin of bluetooth terminal
#define btRX 5 // to "RX-I" pin of bluetooth terminal
#define btSPEED 38400 // communication speed both serial/keyboard and bluetooth
SoftwareSerial bluetooth(btTX, btRX); // bluetooth terminal TX+RX
PS2Keyboard keyboard;
// The initial y coordinate of the top of the scrolling area
uint16_t yStart = TOP_FIXED_AREA;
// yArea must be a integral multiple of TEXT_HEIGHT
uint16_t yArea = 320-TOP_FIXED_AREA-BOT_FIXED_AREA;
// The initial y coordinate of the top of the bottom text line
uint16_t yDraw = 320 - BOT_FIXED_AREA - TEXT_HEIGHT;
// Keep track of the drawing x coordinate
uint16_t xPos = 0;
// For the byte we read from the serial port and display
char data[2] = "";
// We have to blank the top line each time the display is scrolled, but this takes up to 13 milliseconds
// for a full width line, meanwhile the serial buffer may be filling... and overflowing
// We can speed up scrolling of short text lines by just blanking the character we drew
// We keep all the strings pixel lengths to optimise the speed of the top line blanking
int blank[19];
// other staff
char lineString[65]="";
char command[65]="";
char recCommand[65]="";
byte recAddress=0;
byte recType=0;
char park[65]="";
char netRegisterNames[10][10]={};
bool displayAlsoOnSerial = false;
bool isKnownCommand = false;
bool isNetDataWaiting = false;
bool isBusy=false;
byte netRegisterAddrs[10] = {};
unsigned long prevSCANBUSmillis=0;
const int buzzerPin = 7;
const int vin3Pin = 14;
const int vin5Pin = 15;
const int vin12Pin = 16;
const int netMyPx = 0; // netMyPx 0-9
const int netMyAddress = 0x0a; // i2c address
const char *netMyID = "p0"; // netMyID
const char *netMyNAME = "CONSOLE "; // netMyNAME
const int ps2DataPin = 2;
const int ps2IRQpin = 3;
const int SCANBUSinterval = 30000;
const int ResetPin=17; // A3 put low for reset
char _CR[2]=""; // CR
char _BEL[2]=""; // BEL
char _ENQ[2]=""; // ENQ
char _ACK[2]=""; // ACK
char _SPACE[2]=""; // SPACE
char _MYADDR[2]=""; // netMyAddress
void setup() {
//Serial.begin(btSPEED); // serial/keyboard RX only
bluetooth.begin(btSPEED); // bluetooth terminal TX/RX
keyboard.begin(ps2DataPin, ps2IRQpin);
Wire.begin(netMyAddress);
Wire.onReceive(receiveEvent); // i2c event
_CR[0] = 13; // CR
_BEL[0] = 7; // BEL
_ENQ[0] = 5; // ENQ
_ACK[0] = 6; // ACK
_SPACE[0] = 32; // SPACE
_MYADDR[0] = netMyAddress;
netRegisterAddrs[0]=netMyAddress;
s_trimall(park,netMyNAME,sizeof(park));
s_assign(netRegisterNames[0],park,sizeof(netRegisterNames[0])); // 0 it is me
// Setup the TFT display
tft.init();
tft.setRotation(0);
tft.fillScreen(ILI9341_BLACK);
// Setup scroll area
setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
// Top banner
tft.setTextColor(ILI9341_BLACK, ILI9341_GREEN);
tft.fillRect(0,0,240,16, ILI9341_GREEN);
s_assign(park," Net-P Console ",sizeof(park));
tft.drawCentreString(park,120,0,2);
// Change colour for scrolling zone
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
// Zero the array
for (byte i = 0; i<18; i++) blank[i]=0;
delay(2000); // lets other Px to start before "scanbus"
scanbus(false);
sprintf(lineString,"%s\r","Ready");
dispLine();
NewTone(buzzerPin,200,50);
prompt();
}
void loop(void) {
if ((prevSCANBUSmillis+SCANBUSinterval) < millis()) { // plug & play 'px'
scanbus(false);
prevSCANBUSmillis=millis();
}
if (bluetooth.available() > 0) { // one character from bluetooth terminal if any
data[0]=bluetooth.read();
if (displayAlsoOnSerial==true) { // usually false
//Serial.print((char)data[0]); // to serial/keyboard
if (data[0] == '\r') { // cr=cr+lf
//Serial.print('\n');
}
}
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
dispData(); // send to display
evaluateCommands(); // send to evaluate commands
}
if (keyboard.available()) { // one character from ps2 serial keyboard if any
data[0] = keyboard.read();
tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK);
bluetooth.print((char)data[0]); // send to bluetooth terminal
dispData(); // send to display
evaluateCommands(); // send to evaluate commands
}
if (isNetDataWaiting==true) {
execNetCommand();
}
} // end loop()
void evaluateCommands() { // evaluate commands
byte x=0;
byte ln=0;
char cmd[65]="";
if (data[0] == 13) { // CR (eol) pressed
isKnownCommand=false;
if (s_compare(command,"")==0) { // empty command just do nothing
isKnownCommand=true;
prompt();
}
s_substring(park,sizeof(park),command,sizeof(command),0,4); // reset
if (s_compare(park,"reset") == 0) {
isKnownCommand=true;
reset();
}
s_substring(park,sizeof(park),command,sizeof(command),0,3); // scanbus
if (s_compare(park,"scan") == 0) {
isKnownCommand=true;
scanbus(true); // true=displays results, false=mute
}
s_substring(park,sizeof(park),command,sizeof(command),0,6); // checkpower
if (s_compare(park,"ckpower") == 0) {
isKnownCommand=true;
checkpower();
}
s_substring(park,sizeof(park),command,sizeof(command),0,0); // ?
if (s_compare(park,"?") == 0) {
isKnownCommand=true;
help();
}
for (x=0;x<10;x++) { // search processor's name for command
if (x!=netMyPx && netRegisterNames[x][0] != 0) { // not me, not unknown
s_assign(park,netRegisterNames[x],sizeof(park));
s_concat(park," ",sizeof(park));
ln=strlen(park);
s_substring(cmd,sizeof(cmd),command,sizeof(command),0,(ln-1));
if (s_compare(cmd,park) == 0) { // known processor name
isKnownCommand=true;
s_substring(cmd,sizeof(cmd),command,sizeof(command),ln,strlen(command)-1); // clean command for target processor
askCommandOnPx(_BEL[0], x, netRegisterAddrs[x], cmd); // 7=BEL=cmdtype
}
}
}
if (isKnownCommand == false) {
sprintf(lineString,"%s\r","unknown cmd");
dispLine();
prompt();
}
s_clear(command,sizeof(command));
}
if (data[0] > 31 && data[0] < 127) { // only visible ASCII chars (127=DEL)
s_concat(command,data,sizeof(command));
}
} // end evaluateCommands()
void dispData() { // display single character at a time
if (data[0] == _CR[0] || xPos>231) {
xPos = 0;
yDraw = scroll_line(); // It takes about 13ms to scroll 16 pixel lines
}
if (data[0] > 31 && data[0] < 127) { // only visible ASCII chars (127=DEL)
xPos += tft.drawChar(data[0],xPos,yDraw,2);
blank[(18+(yStart-TOP_FIXED_AREA)/TEXT_HEIGHT)%19]=xPos; // Keep a record of line lengths
}
} // end dispData()
void terminalData() { // send to terminal, serial and bluetooth, single char at a time
if (displayAlsoOnSerial==true) { // usually false
//Serial.print((char)data[0]); // to serial/keyboard
if (data[0] == _CR[0]) { // cr=cr+lf
//Serial.print('\n');
}
}
bluetooth.print((char)data[0]); // send to bluetooth terminal
} // end terminalData()
void dispLine() { // prepare single char by single char
byte i=0; // for display and serial and bluetooth terminal (for internal generated text)
for (i=0; i<strlen(lineString); i++) {
data[0]=lineString[i];
tft.setTextColor(ILI9341_GREEN, ILI9341_BLACK);
dispData();
terminalData();
}
s_clear(lineString, sizeof(lineString));
} // end dispString()
void help() { // provide a list of available commands
sprintf(lineString,"%s\r","scan");
dispLine();
sprintf(lineString,"%s\r","ckpower");
dispLine();
sprintf(lineString,"%s\r","<pxname> <cmd>");
dispLine();
sprintf(lineString,"%s\r","reset");
dispLine();
sprintf(lineString,"(free=%d)\r",s_freemem());
dispLine();
prompt();
} // end help()
void prompt() { // prompt, ready for commands
sprintf(lineString,"%d>\r",netMyPx);
dispLine();
} // end prompt()
void checkpower() { // calculate voltages onboard 3v, 5v and raw (12v)
float n=0; // sprintf does not work with float
float n1=0; // then I print separate int.dec parts of numbers
int v3i=0;
int v3d=0;
int v5i=0;
int v5d=0;
int vrawi=0;
int vrawd=0;
n = analogRead(vin3Pin); // v3
n1=(((6.60 * n) / 1023.00));
n=(n1 + ((n1 * 1.0) /100)); // arbitrary correction in %)
v3i=n;
v3d=float((n-v3i)*100);
n = analogRead(vin5Pin); // v5
n1=(((6.60 * n) / 1023.00));
n=(n1 + ((n1 * 1.0) /100)); // arbitrary correction in %)
v5i=n;
v5d=float((n-v5i)*100);
n = analogRead(vin12Pin); // vraw
n1=(((13.2 * n) / 1023.00));
n=(n1 + ((n1 * 3.0) /100)); // arbitrary correction in %)
vrawi=n;
vrawd=float((n-vrawi)*100);
sprintf(lineString, "v3=%d.%02d v5=%d.%02d vraw=%d.%02d\r",v3i,v3d,v5i,v5d,vrawi,vrawd);
dispLine();
prompt();
} // end checkpower
void reset() { // ------------------------------------------------------------ RESET
analogWrite(ResetPin,LOW);
}
void scanbus(bool isInteractive) { // scans i2c bus for active addresses
byte count = 0; // true=interactive and force refresh, false=mute and ask for new only
byte i=0;
int px=0;
if (isInteractive==true) { // shows it and clear Register -> force refresh
sprintf(lineString,"%s\r","Scanning...");
dispLine();
for (px=0;px<10;px++) { // clear Register
netRegisterAddrs[px] = 0;
s_clear(netRegisterNames[px],sizeof(netRegisterNames[px]));
}
}
for (i = 8; i < 128; i++) { // addresses 0-7 are reserved (7 bits address)
Wire.beginTransmission (i);
delay (10);
if (Wire.endTransmission (true) == 0 || i==netMyAddress) { // it blocks here if no i2c available! put pullup resistors and check if a device is blocking to GND pins
sprintf(lineString,"%3d (0x%02X) ",i,i);
if (i==netMyAddress) {
netRegisterAddrs[netMyPx] = netMyAddress;
s_trimall(netRegisterNames[netMyPx],netMyNAME,sizeof(netRegisterNames[netMyPx]));
s_concat(lineString,netMyID,sizeof(lineString));
s_concat(lineString," ",sizeof(lineString));
s_concat(lineString,netRegisterNames[netMyPx],sizeof(lineString));
s_concat(lineString," [me]",sizeof(lineString));
} else {
px=whois(int(i)); // check address
if (px < 10) { // 0-9 is a "p", 99 is unknown
sprintf(park,"p%d %s",px,netRegisterNames[px]);
s_concat(lineString,park,sizeof(lineString));
}
}
s_concat(lineString,_CR,sizeof(lineString));
if (isInteractive==true) { dispLine(); }; // shows it
count++;
}
}
if (isInteractive==true) { // shows it
sprintf(lineString,"%d found\r",count);
dispLine();
prompt();
}
} // end scanbus()
void askCommandOnPx(const int cmdtype, const int px, const int addrs, const char *cmd) { // ask target processor to execute a command
char ccommand[65]="";
s_assign(ccommand, _BEL, sizeof(ccommand)); // BEL
s_concat(ccommand, _MYADDR, sizeof(ccommand)); // netMyAddress
s_concat(ccommand, cmd, sizeof(ccommand)); // cmd
prompt();
Wire.beginTransmission (addrs); // ask
Wire.write(ccommand);
Wire.endTransmission (true);
} // end asksd()
int whois(int address) { // ask name+ID on i2c net, expecting char(5) ENQ as 1st byte
byte i=0;
char xtype=0;
int xid=0;
char xaddr=0;
char park1[65]="";
s_clear(park,sizeof(park));
s_clear(park1,sizeof(park1));
Wire.requestFrom(address, 11); // send request, dest address + nr of bytes
delay(10);
i=0;
while(Wire.available()) { // read answer
data[0]=Wire.read();
i++;
if (i==1) { xtype=data[0]; }; // byte 1 = answer type must be char(5) ENQ
if (i>1 && i<10) { // bytes 2-9 = name
park[i-2] = data[0];
}
if (i==10) { xid=atoi(data); }; // byte 10=id
if (i==11) { xaddr=data[0]; }; // byte 11=address
}
if ((xtype == _ENQ[0]) && (int(xaddr) == address) && (xid < 10)) { // must be a "p"= 0-9, and 10th byte = address, or unknown/wrong answer
netRegisterAddrs[int(xid)] = xaddr; // mem id and address
s_trimall(park1,park,sizeof(park1));
s_assign(netRegisterNames[int(xid)],park1,sizeof(netRegisterNames[int(xid)]));
return xid; // recognized address as "p"
} else {
return 99; // unknown address or answer
}
} // end whois()
void execNetCommand() { // executes received command
isBusy=true;
s_clear(park, sizeof(park));
s_clear(command, sizeof(command));
if (recType == _BEL[0]) { // char(7) = BEL command type ---------------- BEL=incoming request
isKnownCommand=false;
if (s_compare(recCommand,"")==0) { // empty command just do nothing
isKnownCommand=true;
prompt();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,0); // ?
if (s_compare(park,"?") == 0) {
isKnownCommand=true;
help();
}
if (isKnownCommand == false) {
s_assign(lineString,"unknown cmd",sizeof(lineString));
dispLine();
prompt();
}
} // endif recType=BEL
if (recType == _ACK[0]) { // char(6) = ACK command type ---------------- ACK=incoming answer
s_assign(lineString,recCommand,sizeof(lineString));
dispLine();
} // endif recType=ACK
s_clear(recCommand,sizeof(recCommand));
recType=0;
recAddress=0;
isNetDataWaiting=false;
isBusy=false;
} // end execNetCommand()
void receiveEvent(int howMany) { // i2c event incoming requests
if (isBusy==false) {
int counter=0;
s_clear(recCommand, sizeof(recCommand)); // sender command
recAddress=0; // sender address
recType=0; // sender cmd type
if (howMany == 0) { // ignores empty requests
isNetDataWaiting=false;
} else {
while (Wire.available()) {
data[0]=Wire.read();
if (counter==0) { recType = data[0]; } // 1st char = cmd type
if (counter==1) { recAddress = data[0]; } // 2nd char = sender address
if (counter >1) { // other chars = command
s_concat(recCommand, data, sizeof(recCommand));
}
counter++;
}
isNetDataWaiting=true;
}
}//endisBusy
} // end receiveEvent()
//------------------------------------------------------------------------- CLEAR
void s_clear(char *dest_source_string, const int dest_sizeof) { // fills-up with NUL=chr(0)
memset(dest_source_string, 0, dest_sizeof);
} // end s_clear()
//------------------------------------------------------------------------- ASSIGN
bool s_assign(char *dest_string, const char *source_string, const int dest_sizeof) { // copies source to dest
int _LenS=strlen(source_string); // how many bytes
if (_LenS > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcpy(dest_string, source_string);
return false; // ok 0
}
} // end s_assign()
//------------------------------------------------------------------------- SUBSTRING
bool s_substring(char *dest_string, const int dest_sizeof, const char *source_string,
const int source_sizeof, const int source_from, const int source_to) { // copies source(from, to) to dest
if ((source_from < 0) || (source_to < source_from) || ((source_to - source_from + 1) > (dest_sizeof - 1))
|| (source_to >= (source_sizeof-1)) || ((source_to - source_from + 1) > (strlen(source_string)))) {
dest_string[0]=0; // NUL
return true; // err 1
} else {
int _Count=0;
for (int i=source_from;i<(source_to+1);i++) {
dest_string[_Count]=source_string[i];
_Count++;
}
dest_string[_Count]=0; // ends with NUL
return false; // ok 0
}
} // end s_substring()
//------------------------------------------------------------------------- CONCAT
bool s_concat(char *dest_string, const char *source_string, const int dest_sizeof) { // append source to dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if ((_LenS + _LenD) > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcat(dest_string, source_string);
return false; // ok 0
}
} // end s_concat()
//------------------------------------------------------------------------- COMPARE
bool s_compare(const char *dest_string, const char *source_string) { // compares source with dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if (_LenS != _LenD) { // different length
return true; // are different 1
} else {
if (strcmp(dest_string, source_string) == 0) {
return false; // are the same 0
} else {
return true; // are different 1
}
}
} // end s_compare()
//------------------------------------------------------------------------- TRIMALL
bool s_trimall(char *dest_string, const char *source_string, const int dest_sizeof) { // eliminate all 'spaces' from source to dest
int _LenS=strlen(source_string); // how many bytes max
if (_LenS > (dest_sizeof - 1)) {
return true; // err 1
} else {
int _Count=0;
for (int i=0;i<(_LenS);i++) {
if (source_string[i] != _SPACE[0]){
dest_string[_Count]=source_string[i];
_Count++;
}
}
dest_string[_Count]=0; // ends with NUL
return false; // ok 0
}
} // end s_trimall()
//------------------------------------------------------------------------- FREEMEM
int s_freemem() {
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);
} // end s_freemem()
// ##############################################################################################
// Call this function to scroll the display one text line
// ##############################################################################################
int scroll_line() {
int yTemp = yStart; // Store the old yStart, this is where we draw the next line
// Use the record of line lengths to optimise the rectangle size we need to erase the top line
tft.fillRect(0,yStart,blank[(yStart-TOP_FIXED_AREA)/TEXT_HEIGHT],TEXT_HEIGHT, ILI9341_BLACK);
// Change the top of the scroll area
yStart+=TEXT_HEIGHT;
// The value must wrap around as the screen memory is a circular buffer
if (yStart >= 320 - BOT_FIXED_AREA) yStart = TOP_FIXED_AREA + (yStart - 320 + BOT_FIXED_AREA);
// Now we can scroll the display
scrollAddress(yStart);
return yTemp;
}
// ##############################################################################################
// Setup a portion of the screen for vertical scrolling
// ##############################################################################################
// We are using a hardware feature of the display, so we can only scroll in portrait orientation
void setupScrollArea(uint16_t TFA, uint16_t BFA) {
tft.writecommand(ILI9341_VSCRDEF); // Vertical scroll definition
tft.writedata(TFA >> 8);
tft.writedata(TFA);
tft.writedata((320-TFA-BFA)>>8);
tft.writedata(320-TFA-BFA);
tft.writedata(BFA >> 8);
tft.writedata(BFA);
}
// ##############################################################################################
// Setup the vertical scrolling start address
// ##############################################################################################
void scrollAddress(uint16_t VSP) {
tft.writecommand(ILI9341_VSCRSADD); // Vertical scrolling start address
tft.writedata(VSP>>8);
tft.writedata(VSP);
}
/* Arduino Net-P (i2c processors network) by Zonca Marco 2020
* 'netMyNAME' ("SD ") max 8 char, 'netMyID' (p1) max 2 char,
* address='netMyAddress' max 0xFF, 'netMyPx' (1)
*
* implemented commands (* = to do): mr, mw
* dir, mkdir, rmdir, del, type, size, rename*, reset, ?
*
* (m... commands work on \MEMORY\Px\ directory, plain text file 'cr'+'lf' terminating line/record)
* (sd... commands work on SD memory card)
*
* ?: ? [ask for help
* i.e. ?
* returns a list of available commands on board and free memory]
*
* mw/mwa: mw <FileName>=<Value> [writes/modifies Value in file name
* i.e. mw temp01=24 (FileName=Value)
* returns "written"] (mwa will append Value to the file)
* mr/mra: mr <FileName> [reads Value from corrisponding file name
* i.e. mr temp01 (FileName is temp01, Value is 24)
* returns 'Value' or "not found"] (mra will read multilines Value from the file)
*
* reset: reset [resets MPU
* i.e. reset]
* dir: dir <path> [reads file names starting from 'path'
* i.e. dir /]
* returns a list of file 'names' and 'size'... ends with 'n found']
* mkdir: mkdir <dirname> [build a new directory (and also relative subdirectories)
* i.e. mkdir /music, sdmkdir /logic/params/binary
* returns "built" or "error"]
* rmdir: rmdir <dirname> [delete a dir
* i.e. rmdir /music
* returns "removed" or "error or not empty" ]
* rename: rename <OldFileName> <NewFileName> [renames a file
* i.e. rename myfile.txt bestfile.txt
* returns "renamed" or "not found"]
* del: del <FileName> [delete a file
* i.e. del myfile.txt
* returns "deleted" or "not found"]
* type: type <FileName> <Mode> [reads a file and displays in mode 0=CHR, 1=BIN, 2=HEX
* i.e. type myfile.txt CHR
* returns the content of the file ... and filesize 'n' and bytes red 'n' at the end]
* eeupl: eeupl <Filename> [read a file and upload it to the EEPROM, write and verify all data
* i.e. eeupl /mysketch.hex
* returns upload, written, verified...]
*
* SD card attached to SPI bus as follows:
* ---------------------------------------
* MOSI - pin 11
* MISO - pin 12
* CLK - pin 13
* CS - pin 10 see 'chipSelect' below
*/
#include <Wire.h>
#include <SdFat.h>
const int netMyPx = 1; // netMyPx 0-9
const int netMyAddress = 0x0b; // i2c address 0x0b=HEX 11=DEC
const char *netMyID = "p1"; // netMyID
const char *netMyNAME = "SD "; // netMyNAME 8 bytes
const char *memDIR = "/MEMORY/"; // memory directory
const char *logDIR = "/LOG/"; // log directory
const int chipSelect = 10; // CS
const int eprom1addr=80; // 1st eprom address (80, 81, etc. (DEC))
const int eprom1pgsz=16; // 1st eprom memory page size (16, 128, etc.)
const long eprom1size=256; // 1st eprom size (258, 1024, etc.)
const int ResetPin=17; // A3 put low for reset
char _CR[2]=""; // CR
char _LF[2]=""; // LF
char _BEL[2]=""; // BEL
char _ENQ[2]=""; // ENQ
char _ACK[2]=""; // ACK
char _NUL[2]=""; // NUL
char _SPACE[2]=""; // SPACE
char _MYADDR[2]=""; // netMyAddress
char lineString[65]="";
char recCommand[65]="";
char data[2]="";
byte recAddress=0;
byte recType=0;
bool isNetDataWaiting=false;
bool isKnownCommand=false;
bool sdOpened=false;
bool isBusy=false;
SdFat sd;
void setup() {
// Serial.begin(38400);
Wire.begin(netMyAddress);
Wire.onReceive(receiveEvent); // i2c event
Wire.onRequest(netWhoIsEvent); // i2c whois
_CR[0] = 13; // CR
_LF[0] = 10; // LF
_BEL[0] = 7; // BEL
_ENQ[0] = 5; // ENQ
_ACK[0] = 6; // ACK
_NUL[0] = 0; // NUL
_SPACE[0] = 32; // SPACE
_MYADDR[0] = netMyAddress;
if (!sd.begin(chipSelect,SPI_FULL_SPEED)) { // in case try SPI_HALF_SPEED
sdOpened=false;
} else {
sdOpened=true;
}
} // end setup()
void loop() {
if (isNetDataWaiting == true) {
execNetCommand();
}
} // end loop()
void sdreset() { // ------------------------------------------------------------ RESET
analogWrite(ResetPin,LOW);
}
void sddelete(const char *_s) { // ---------------------------------------------- DELETE
if (!sd.exists(_s)) { // check if file does exist
s_assign(lineString,"not found!",sizeof(lineString));
dispLine();
} else {
if (!sd.remove(_s)) { // remove file
s_assign(lineString,"error!",sizeof(lineString));
dispLine();
} else {
s_assign(lineString,"deleted",sizeof(lineString));
dispLine();
}
}
prompt();
} // end sddelete()
void sdeeupload(const char *_s) { // ------------------------------------------- EEUPLOAD
File file;
long count=0;
long uc=0;
byte err=0;
byte EE=0;
long fsize=0;
bool isDone=false;
byte EErr=0;
while (isDone==false) {
if (!sd.exists(_s)) { // check if name exists // ---------------- preliminary checks
s_assign(lineString,"nm not found",sizeof(lineString));
dispLine();
isDone=true;
break;
}
file=sd.open(_s);
if (!file.isOpen()) {
s_assign(lineString,"nm open!",sizeof(lineString));
dispLine();
isDone=true;
break;
}
fsize=file.fileSize();
if (fsize > (eprom1size-16-1)) { // must be less then size-header-NUL
s_assign(lineString,"too big!",sizeof(lineString));
dispLine();
file.close();
isDone=true;
break;
}
sprintf(lineString,"(%ld) upload...",fsize); // ----------------------------- write
dispLine();
while (file.available()) {
data[0]=file.read();
EE=data[0];
uc=count+16;
writeEEPROM (eprom1addr, uc, EE, &EErr);
if (EErr!=0) {
sprintf(lineString,"error (%d) wr EE!",EErr);
dispLine();
file.close();
isDone=true;
break; //break this while, later the main while
}
count++;
}//endwhile
file.close();
if (isDone==true) {break;} // breaks main while
EE=_NUL[0]; // --------------------------------------------- write finish with a NUL
uc=count+16; // count already+1
writeEEPROM (eprom1addr, uc, EE, &EErr);
if (EErr!=0) {
sprintf(lineString,"error (%d) NUL EE!",EErr);
dispLine();
isDone=true;
break;
}
sprintf(lineString,"(%ld) written...",count);
dispLine();
file=sd.open(_s); // -------------------------------------------------------------- verify
if (!file.isOpen()) {
s_assign(lineString,"error opn nm!",sizeof(lineString));
dispLine();
isDone=true;
break;
}
count=0;
while (file.available()) {
data[0]=file.read();
uc=count+16;
EE=readEEPROM (eprom1addr, uc, &EErr);
if (EErr!=0) {
sprintf(lineString,"error (%d) rd EE!",EErr);
dispLine();
file.close();
isDone=true;
break;
}
if (byte(data[0])!=EE) {
sprintf(lineString,"diff vrf (%ld) in EE!",count);
dispLine();
file.close();
isDone=true;
break; //break this while, later the main while
}
count++;
}//endwhile
file.close();
if (isDone==true) { break; } // breaks main while
uc=count+16; // ----------------------------------------------- verify finish NUL
EE=readEEPROM (eprom1addr, uc, &EErr);
if (EErr!=0) {
sprintf(lineString,"error (%d) vrf EE!",EErr);
dispLine();
isDone=true;
break;
} else {
if (EE!=byte(_NUL[0])) {
sprintf(lineString,"(%ld) not NUL EE!",uc);
dispLine();
isDone=true;
break;
}
}
sprintf(lineString,"(%ld) verified",count);
dispLine();
isDone=true;
}//whileisDone
prompt();
} // end sdeeupload()
void sdmr(const char *_s, const boolean _all) { // ---------------------------------------- MR / MRA
byte cnt=0;
if (!sd.exists(_s)) { // check if name exists
s_assign(lineString,"not found",sizeof(lineString));
dispLine();
} else {
File file;
file=sd.open(_s);
if (!file.isOpen()) {
s_assign(lineString,"open!",sizeof(lineString));
dispLine();
}
s_clear(lineString,sizeof(lineString));
while (file.available()) {
data[0]=file.read();
if (data[0]!=_CR[0] && data[0]!=_LF[0]) {
s_concat(lineString,data,sizeof(lineString));
cnt++;
}
if (cnt > (sizeof(lineString)-1)) {
s_assign(lineString,"too long!",sizeof(lineString));
dispLine();
break;
}
if (_all==true && data[0]==_LF[0]) { // multiline-log reading MRA
cnt += 2; // include CR+LF counting
dispLine();
}
}
file.close();
if (_all==false) { dispLine(); }
sprintf(lineString,"(%d) bytes",cnt);
dispLine();
}
prompt();
} // end sdmw()
void sdmw(const char *_s, const char *_v, const boolean _append) { // -------------------------- MW / MWA
if (_append==false && sd.exists(_s)) { // check if name exists then delete it (MW only)
if (!sd.remove(_s)) {
s_assign(lineString,"rm error!",sizeof(lineString));
dispLine();
}
}
SdFile file(_s, O_WRONLY | O_CREAT | O_APPEND);
if (!file.isOpen()) {
s_assign(lineString,"opening!",sizeof(lineString));
dispLine();
} else {
file.println(_v);
file.close();
if (_append==false) {
s_assign(lineString,"written",sizeof(lineString));
} else {
s_assign(lineString,"added",sizeof(lineString));
}
dispLine();
}
prompt();
} // end sdmw()
void sddir(const char *_s) { // ----------------------------- DIR
int fcount=0;
int dcount=0;
long fsize=0;
SdFile root;
SdFile file;
bool isDone=false;
char fname[14]="";
while (isDone==false) {
if (!root.open(_s)) { // dir starting from 'path'
s_assign(lineString,"not found!",sizeof(lineString));
dispLine();
isDone=true;
break;
}
while (file.openNext (&root, O_RDONLY)) {
if (!file.isHidden()) {
if (file.isDir()) {
file.getName(fname,13);
s_assign(lineString,fname,sizeof(lineString));
s_concat(lineString," <dir>",sizeof(lineString));
dispLine();
dcount++;
}
if (file.isFile()) {
file.getName(fname,13);
fsize=file.fileSize();
s_assign(lineString,fname,sizeof(lineString));
s_concat(lineString," (",sizeof(lineString));
sprintf(fname,"%ld",fsize);
s_concat(lineString,fname,sizeof(lineString));
s_concat(lineString,")",sizeof(lineString));
dispLine();
fcount++;
}
}//end !file.hidden
file.close();
} //end whileOpenNext
root.close();
s_assign(lineString,"(dir=",sizeof(lineString));
sprintf(fname,"%d",dcount);
s_concat(lineString,fname,sizeof(lineString));
s_concat(lineString," file=",sizeof(lineString));
sprintf(fname,"%d",fcount);
s_concat(lineString,fname,sizeof(lineString));
s_concat(lineString,")",sizeof(lineString));
dispLine();
isDone=true;
}//end while isDone
prompt();
} // end sddir()
void sdhelp() { // ---------------------------------------------- HELP
sprintf(lineString,"%s","dir <path>");
dispLine();
sprintf(lineString,"%s","mr|mra <nm>");
dispLine();
sprintf(lineString,"%s","mw|mwa <nm>=<val>");
dispLine();
sprintf(lineString,"%s","del <nm>");
dispLine();
sprintf(lineString,"%s","eeupl <nm>");
dispLine();
sprintf(lineString,"%s","reset");
dispLine();
sprintf(lineString,"(free=%d)",s_freemem());
dispLine();
prompt();
} // end help()
void prompt() { // prompt, ready for commands
sprintf(lineString,"%d>\r",netMyPx);
dispLine();
} // end prompt()
void dispLine() { // print information
s_concat(lineString, _CR, sizeof(lineString));
txBackToSender(); // tx
s_clear(lineString, sizeof(lineString));
delay(100);
} // end dispLine()
void receiveEvent(int howMany) { // i2c event incoming requests
if (isBusy==false) {
int counter=0;
s_clear(recCommand, sizeof(recCommand)); // sender command
recAddress=0; // sender address
recType=0; // sender cmd type
if (howMany == 0) { // ignores empty requests
isNetDataWaiting=false;
} else {
while (Wire.available()) {
data[0]=Wire.read();
if (counter==0) { recType = data[0]; } // 1st char = cmd type
if (counter==1) { recAddress = data[0]; } // 2nd char = sender address
if (counter >1) { // other chars = command
s_concat(recCommand, data, sizeof(recCommand));
}
counter++;
}
isNetDataWaiting=true;
}
}//endifbusy
} // end receiveEvent()
void netWhoIsEvent() { // i2c event: 11 bytes = 1=char(5) ENQ, 2-9=netMyNAME 10=netMyPx 11=netMyAddress
if (isBusy==false) {
char ccommand[65]="";
char park[3]="";
s_concat(ccommand, _ENQ, sizeof(ccommand)); // ENQ=answer whois
s_concat(ccommand, netMyNAME, sizeof(ccommand)); // netMyNAME
s_concat(ccommand, itoa(netMyPx,park,10), sizeof(ccommand)); // netMyPx
s_concat(ccommand, _MYADDR, sizeof(ccommand)); // netMyAddress
Wire.write(ccommand);
}
} // end netWhoIsEvent()
void txBackToSender() { // tx back to sender
char ccommand[65]="";
s_assign(ccommand, _ACK, sizeof(ccommand)); // ACK=answer data
s_concat(ccommand, _MYADDR, sizeof(ccommand)); // netMyAddress
s_concat(ccommand, lineString, sizeof(ccommand)); // data
Wire.beginTransmission (recAddress);
Wire.write (ccommand);
Wire.endTransmission (true);
} // end txBackToSender()
void execNetCommand() { // executes received command
isBusy=true;
char park[65]="";
char command[65]="";
int x=0;
int its=-1;
if (recType == _BEL[0]) { // char(7) = BEL command type
isKnownCommand=false;
if (s_compare(recCommand,"")==0) { // empty command just do nothing
isKnownCommand=true;
prompt();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,0); // ?
if (s_compare(park,"?") == 0) {
isKnownCommand=true;
sdhelp();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,4); // reset
if (s_compare(park,"reset") == 0) {
isKnownCommand=true;
sdreset();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,2); // mw
if (s_compare(park,"mw ") == 0) {
for (x=0; x<strlen(recCommand);x++) { // search for "="
s_substring(data,sizeof(data),recCommand,sizeof(recCommand),x,x);
if (strcmp(data,"=") == 0) {
its=x;
}
}
if (its >= 0) {
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),3,its-1); // filename
s_assign(command,memDIR,sizeof(command)); // memDIR
s_concat(command,park,sizeof(command)); // memDIR+filename
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),its+1,strlen(recCommand)-1); // value
isKnownCommand=true;
sdmw(command,park,false);
}
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,3); // mwa (append)
if (s_compare(park,"mwa ") == 0) {
for (x=0; x<strlen(recCommand);x++) { // search for "="
s_substring(data,sizeof(data),recCommand,sizeof(recCommand),x,x);
if (strcmp(data,"=") == 0) {
its=x;
}
}
if (its >= 0) {
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),4,its-1); // filename
s_assign(command,logDIR,sizeof(command)); // logDIR
s_concat(command,park,sizeof(command)); // logDIR+filename
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),its+1,strlen(recCommand)-1); // value
isKnownCommand=true;
sdmw(command,park,true);
}
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,2); // mr
if (s_compare(park,"mr ") == 0) {
isKnownCommand=true;
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),3,strlen(recCommand)-1); // filename
s_assign(command,memDIR,sizeof(command)); // memDIR
s_concat(command,park,sizeof(command)); // memDIR+filename
sdmr(command,false);
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,3); // mra (multiline/log)
if (s_compare(park,"mra ") == 0) {
isKnownCommand=true;
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),4,strlen(recCommand)-1); // filename
s_assign(command,logDIR,sizeof(command)); // logDIR
s_concat(command,park,sizeof(command)); // logDIR+filename
sdmr(command,true);
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,3); // del
if (s_compare(park,"del ") == 0) {
isKnownCommand=true;
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),4,strlen(recCommand)-1);
sddelete(command);
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,5); // eeupload
if (s_compare(park,"eeupl ") == 0) {
isKnownCommand=true;
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),6,strlen(recCommand)-1);
sdeeupload(command);
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,3); // dir file
if (s_compare(park,"dir ") == 0) {
isKnownCommand=true;
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),4,strlen(recCommand)-1);
sddir(command);
}
if (isKnownCommand == false) {
s_assign(lineString,"unknown command",sizeof(lineString));
dispLine();
prompt();
}
} // endif recType
s_clear(recCommand,sizeof(recCommand));
recType=0;
recAddress=0;
isNetDataWaiting=false;
isBusy=false;
} // end execNetCommand()
// reading eeprom
byte readEEPROM (const int _disk, const unsigned int _addr, byte *EErr ) {
*EErr=0;
byte _rxbyte=0;
Wire.beginTransmission(_disk);
Wire.write(_addr);
if (Wire.endTransmission() == 0) {
Wire.requestFrom(_disk,1);
if (Wire.available()) {
_rxbyte = Wire.read();
} else {
*EErr = 1; //"READ no data available"
}
} else {
*EErr = 2; //"READ eTX error"
}
Wire.endTransmission (true);
return _rxbyte;
}
// writing eeprom
void writeEEPROM (const int _disk, const unsigned int _addr, byte _txbyte, byte *EErr) {
*EErr=0;
Wire.beginTransmission(_disk);
Wire.write(_addr);
Wire.write(_txbyte);
if (Wire.endTransmission() != 0) {
*EErr = 3; //"WRITING eTX error"
}
Wire.endTransmission (true);
delay(5);
}
//------------------------------------------------------------------------- CLEAR
void s_clear(char *dest_source_string, const int dest_sizeof) { // fills-up with NUL=chr(0)
memset(dest_source_string, 0, dest_sizeof);
} // end s_clear()
//------------------------------------------------------------------------- ASSIGN
bool s_assign(char *dest_string, const char *source_string, const int dest_sizeof) { // copies source to dest
int _LenS=strlen(source_string); // how many bytes
if (_LenS > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcpy(dest_string, source_string);
return false; // ok 0
}
} // end s_assign()
//------------------------------------------------------------------------- SUBSTRING
bool s_substring(char *dest_string, const int dest_sizeof, const char *source_string,
const int source_sizeof, const int source_from, const int source_to) { // copies source(from, to) to dest
if ((source_from < 0) || (source_to < source_from) || ((source_to - source_from + 1) > (dest_sizeof - 1))
|| (source_to >= (source_sizeof-1)) || ((source_to - source_from + 1) > (strlen(source_string)))) {
dest_string[0]=0; // NUL
return true; // err 1
} else {
int _Count=0;
for (int i=source_from;i<(source_to+1);i++) {
dest_string[_Count]=source_string[i];
_Count++;
}
dest_string[_Count]=0; // ends with NUL
return false; // ok 0
}
} // end s_substring()
//------------------------------------------------------------------------- CONCAT
bool s_concat(char *dest_string, const char *source_string, const int dest_sizeof) { // append source to dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if ((_LenS + _LenD) > (dest_sizeof - 1)) {
return true; // err 1
} else {
strcat(dest_string, source_string);
return false; // ok 0
}
} // end s_concat()
//------------------------------------------------------------------------- COMPARE
bool s_compare(const char *dest_string, const char *source_string) { // compares source with dest
int _LenS=strlen(source_string); // how many bytes source
int _LenD=strlen(dest_string); // how many bytes dest
if (_LenS != _LenD) { // different length
return true; // are different 1
} else {
if (strcmp(dest_string, source_string) == 0) {
return false; // are the same 0
} else {
return true; // are different 1
}
}
} // end s_compare()
//------------------------------------------------------------------------- FREEMEM
int s_freemem() {
extern int __heap_start,*__brkval;
int v;
return (int)&v - (__brkval == 0 ? (int)&__heap_start : (int) __brkval);
} // end s_freemem()
//*************************************************************************************
/*
void sdtype(String filename, byte mode) { // ----------------------------- TYPE
char data=0; // sdtype, displays the content of a file
int count=0; // mode 0=CHAR 1=BIN 2=HEX
byte vert=0;
bool isAlreadyAtNL=true;
String STemp="";
STemp.reserve(64);
File SDfile;
if (!SD.exists(filename)) { // check if file does exist
lineString="SD file not found!";
dispLine(lineString);
} else {
SDfile = SD.open(filename); // open file
while(SDfile.available()) { // read all file, byte by byte
data = (SDfile.read());
switch (mode) {
case 0: // CHAR
lineString=String(data);
dispChar(lineString);
break;
case 1: // BIN
STemp="00000000"+String(data,BIN); // fill with non significant bits
lineString=STemp.substring(STemp.length()-9,STemp.length())+" ";
dispChar(lineString);
vert ++;
if (vert == 3) {
dispLine(""); // newline
isAlreadyAtNL=true;
vert=0;
} else {
isAlreadyAtNL=false;
}
break;
case 2: // HEX
STemp="00"+String(data,HEX)+" "; // fill with non significant 0
lineString=STemp.substring(STemp.length()-3,STemp.length())+" ";
dispChar(lineString);
vert ++;
if (vert == 8) {
dispLine(""); // newline
isAlreadyAtNL=true;
vert=0;
} else {
isAlreadyAtNL=false;
}
break;
}
count ++;
} //end while
if (isAlreadyAtNL==false) {dispLine("");}; // empty line at the end
lineString="file size ("+String(SDfile.size(),DEC)+"), bytes read ("+String(count,DEC)+")"; // file size
dispLine(lineString);
SDfile.close();
}
prompt();
} // end sdtype()
if (recCommand.substring(0,4) == "type") {
isKnownCommand=true;
command=recCommand.substring(5,recCommand.length()-4);
if (recCommand.substring(recCommand.length()-3,recCommand.length())=="CHR") { x=0; };
if (recCommand.substring(recCommand.length()-3,recCommand.length())=="BIN") { x=1; };
if (recCommand.substring(recCommand.length()-3,recCommand.length())=="HEX") { x=2; };
sdtype(command,x);
}
void sdfilesize(const char *_s) { // ------------------------------------------- FILESIZE
File file;
bool isDone=false;
long fsize=0;
while (isDone==false) {
if (!sd.exists(_s)) { // check if name exists
s_assign(lineString,"nm not found",sizeof(lineString));
dispLine();
isDone=true;
break;
}
file=sd.open(_s);
if (!file.isOpen()) {
s_assign(lineString,"nm open!",sizeof(lineString));
dispLine();
isDone=true;
break;
}
fsize=file.fileSize();
sprintf(lineString,"size=%ld",fsize);
dispLine();
isDone=true;
}//endwhile
prompt();
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,4); // size
if (s_compare(park,"size ") == 0) {
isKnownCommand=true;
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),5,strlen(recCommand)-1);
sdfilesize(command);
}
void sdrmdir(const char *_s) { // ----------------------------- RMDIR
if (!sd.exists(_s)) { // check if dir exists
s_assign(lineString,"not found!",sizeof(lineString));
dispLine();
} else {
if (sd.rmdir(_s)) { // deletes dir
s_assign(lineString,"removed",sizeof(lineString));
dispLine();
} else {
s_assign(lineString,"not empty!",sizeof(lineString));
dispLine();
}
}
prompt();
} // end sdrmdir()
void sdmkdir(const char *_s) { // ----------------------------- MKDIR
if (sd.exists(_s)) { // check if dir already exists
s_assign(lineString,"nm exists!",sizeof(lineString));
dispLine();
} else {
if (sd.mkdir(_s)) { // builds dir
s_assign(lineString,"made",sizeof(lineString));
dispLine();
} else {
s_assign(lineString,"nm error!",sizeof(lineString));
dispLine();
}
}
prompt();
} // end sdmkdir()
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,5); // mkdir
if (s_compare(park,"mkdir ") == 0) {
isKnownCommand=true;
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),6,strlen(recCommand)-1);
sdmkdir(command);
}
s_substring(park,sizeof(park),recCommand,sizeof(recCommand),0,5); // rmdir
if (s_compare(park,"rmdir ") == 0) {
isKnownCommand=true;
s_substring(command,sizeof(command),recCommand,sizeof(recCommand),6,strlen(recCommand)-1);
sdrmdir(command);
}
*/
Comments
Please log in or sign up to comment.