////////BPwCLIv1.1//////
////////CLI CLASS //////////////////////////////
// Define the callback function signature
typedef void (*CallbackFunction)(int num);
class CLI{
public:
//ten commands //command and ten parameters //any number of modes
#define NUMCOMMANDS 10
#define NUMPARAMS 10
String commandlinearray[1+NUMPARAMS];
String commandslist[NUMCOMMANDS];
int cmdnum, cmdmode;//command number, command mode
bool commandvalid, executed;
String helpstring; String errormsg="";//for help, error messages etc
CallbackFunction callback;
//CLI ROUTINES////////////////////
void readinputcommand(){
if (Serial.available() > 0) {
commandvalid=false;
String commandline = Serial.readStringUntil('\r'); // read the command entered in the serial monitor until newline character
cleararray();
int np=0;
int i = commandline.indexOf(' ');
while(i != -1) {
String p = commandline.substring(0, i);
commandlinearray[np]=p;
np++;
commandline = commandline.substring(i + 1);
i = commandline.indexOf(' ');
}
commandlinearray[np]=commandline;//Last token
printcommandline();
//command is the first token of the commandlinearray
String command = commandlinearray[0];// use this to call custom functions one for each command
cmdnum = -1;
for (int n=0;n<NUMCOMMANDS;n++){
if (command==commandslist[n]) cmdnum = n;
}
if (cmdnum == -1){
errormsg="Invalid Command or no space after command";
Serial.println(errormsg);
commandvalid=false;
}else{
commandvalid=true;
}
executed=true;
}
}
void cleararray(){
for(int x=0;x<NUMCOMMANDS;x++)commandlinearray[x]="";
}
void printcommandline(){
for(int x=0;x<1+NUMPARAMS;x++){
Serial.print(commandlinearray[x]);
if (commandlinearray[x+1]!="")Serial.print(" ");
}
}
void clirun(){
readinputcommand();
if (commandvalid){
callback(cmdnum);
cleararray();
commandvalid=false;
}
}
};/////////////END OF CLI CLASS//////////////////////////////////
///// DEBUG STUFF ////////////////////////////////
//////////////////////////////////////////////////
class BPDEBUGGER{
//IMPORTANT THIS CLASS EXPECTS YOU TO CREATE AN OBJECT NAMED bp
#define BPDEBUGGERDOC "https://docs.google.com/document/d/1n0r7_nqzqog4-LxEut5lkxUAUwDTn0wvq2oc11CFJAY/edit"
#define DEBUG true
//#define DEBUG false
#if DEBUG
#define NL {Serial.print("\n");}
#define PRINTS(s) { Serial.print(F(s)); }
#define PRINT(s,v) { Serial.print(F(s)); Serial.print(v); NL }
#define PRINTX(s,v) { Serial.print(F(s)); Serial.print(v, HEX); NL}
#define BP bp.breakpoint(__LINE__);
#define BPx(func) func; BP;
#define BPS(s) NL PRINTS(s) BP;
#define BPSV(s,v) NL PRINT(s,v) BP;
#define BPDELAY(n) bp.bpdelay = n;BP
#define BPIF(e) if(e) BP
#else
#define NL
#define PRINTS(s)
#define PRINT(s,v)
#define PRINTX(s,v)
#define BP
#define BPx(func)
#define BPS(s)
#define BPSV(s,v)
#define BPDELAY(n)
#define BPIF(e)
#endif
//DEBUG varaiables
public:
CLI* cmd;//pointer to cli object
unsigned long bpstarttime, bpdelay = 5000;//bp timers millis
unsigned long bpcontinuetime, bptimebetweenbps;//bp timers micros
bool buttonpressed=false, bpxcmd = false;//bp exit command
bool isatbreakpoint;//true when bp is in effect. can control isr activity
String bpmessage = " This is a Breakpoint Help Message \r\n documentation at BPDEBUGGERDOC";
BPDEBUGGER(){
}
void breakpoint(int bpline){
PRINT("BREAKPOINT Line ", bpline);
isatbreakpoint = true;
bpstarttime = millis();//global FOR DEBUGGING STATS
//unsigned long bpcontinuetime,bptimebetweenbps; //global
bptimebetweenbps = micros()-bpcontinuetime;//
while(true){
cmd->clirun();//REFERENCE TO CLI OBJECT THROUGH POINTER CMD
//add bpdelay to time cmd completed commandprcessing
if (cmd->executed){bpstarttime=millis();cmd->executed=false;}
if (bpcontinue()) {
bpcontinuetime=micros();//save breakpoint exit time
isatbreakpoint = false;
return;
}
}
}
bool bpcontinue(){
//check if timeout
if (millis()>bpstarttime + bpdelay){
if (bpdelay==0) return false;
Serial.println("\nBreakpoint Timeout .. Continuing\n");
return true;
}
//check if bpx command
if (bpxcmd) {
bpxcmd = false;//consume the bpxcmd flag
Serial.println("\nBreakoint Continue command received .. Continuing\n");
return true;
}
//check if continue button is pressed
if(buttonpressed){
delay(20);buttonpressed=false;
Serial.println("\nBreakpoint Continue Button Pressed .. Continuing\n");
return true;
}
return false;
}
void help(){Serial.println(BPDEBUGGERDOC);}
};
///////////// END OF DEBUG STUFF //////////////
/////////////////////////////////////////////////////////////////
CLI cmd;//INSTATIATE COMMAND LINE INTERFACE
BPDEBUGGER bp;//INSTANTIATE THE BREAKPOINT DEBUGGER
//bool bpxcmd;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
Serial.println("Testing BPwCLI v1.1 improved");
commandslistsetup();//SET UP LIST OF COMMANDS
cmd.callback=commandexec;//SET UP CALLBACK FUNCTION
bp.cmd = &cmd;//CONNECT CLI TO BPDEBUGGER
}
void loop() {
// put your main code here, to run repeatedly:
cmd.clirun();//RUN CLI IF NEEDED IN THE APP
BP
//BPIF(bpxcmd) //CONDITIONAL BREAKPOINT
}
////////////////////////////////////////////////////////
//CLI routines
////////////////////////////////////////////////////////
void commandslistsetup(){
//SET UP COMMANDS HERE
cmd.commandslist[0]= "help";
cmd.commandslist[1]= "set";
cmd.commandslist[2]= "list";
cmd.commandslist[3]= "mode";
cmd.commandslist[4]= "bpx";
cmd.helpstring = "Commands: ?, set, list, mode, bpx [leave space after command or last parameter ]";
}
void commandexec(int cmdnum){
//HANDLE COMMANDS HERE
if(cmdnum==0){help();}//help
if(cmdnum==1){setparam();}//set param value
if(cmdnum==2){listparams();}//--list
if(cmdnum==3){switchmode();}//--mode n
if(cmdnum==4){bpexit();}//--bpx
}
void help(){
Serial.println(cmd.helpstring);
}
void setparam(){
String p, v;
p=cmd.commandlinearray[1];
v=cmd.commandlinearray[2];
if ((p=="")||(v=="")) Serial.println("parameter count error");
//CODE TO SET ALL VARS TO BE PLACED HERE
//if(p=="bpxcmd"){bpxcmd=str2bool(v);}//way to set boolean
//if(p=="mode"){cmd.cmdmode=commandlinearray[1].toInt();}
}
bool str2bool(String v){
if (v=="1") return true;
if (v=="true") return true;
if (v=="0") return false;
if (v=="false") return false;
}
void listparams(){
//CREATE WATCHLIST HERE
Serial.println();
Serial.print("cmd.cmdmode = "); Serial.println(cmd.cmdmode);
}
void switchmode(){
//mode n command
cmd.cmdmode=cmd.commandlinearray[1].toInt();
}
void bpexit(){
bp.bpxcmd = true;
}