aboutsummaryrefslogtreecommitdiff
path: root/src/Monitor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Monitor.cpp')
-rwxr-xr-xsrc/Monitor.cpp312
1 files changed, 312 insertions, 0 deletions
diff --git a/src/Monitor.cpp b/src/Monitor.cpp
new file mode 100755
index 0000000..fd77089
--- /dev/null
+++ b/src/Monitor.cpp
@@ -0,0 +1,312 @@
+/*---------------------------------------------------------------------Monitor.h
+ * Author: Joseph Wayne Dumoulin, Donald Delmar Davis, Suspect Devices
+ *
+ * Liscence: "Simplified BSD License"
+ *
+ * Copyright (c) 2016, Donald Delmar Davis, Suspect Devices
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in thedocumentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *-----------------------------------------------------------------------------
+ * The idea here is to create an automation freindly monitor protocol and debug
+ * interface. Because this needs to be efficient (and flexible) I have chosen a
+ * very simple interface which will access and may manipulate a devices public
+ * variables.
+ *
+ * Basic Syntax for the monitor is
+ * XXX[?!:] <variable stuff> <CR>
+ * where:
+ * XXX is a 3 letter command or variable.
+ * ! execute command or store value
+ * ? get value
+ * :<20 char timestamp>, value returned.
+ *
+ * keywords are described in keywords.h
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "Monitor.h"
+#include "Clock.h"
+
+/*
+ * +1 is for the trailing null.
+ */
+const char keywords[((NKEYWORDS)*3)+1] = KEYWORDS;
+#define KWHELPLEN 26
+
+char kwhelp[((NKEYWORDS+1) * KWHELPLEN)+1] = HELPTEXT;
+char updateBuffer[MAX_RETURN_VALUE]; //allocate this once use it often.
+actionptr actions[NKEYWORDS];
+
+
+void Monitor::update(const char *data, const char *format, ...) {
+ va_list blarg;
+ updateBuffer[0]=data[0];updateBuffer[1]=data[1];updateBuffer[2]=data[2];updateBuffer[3]=':';
+ timeStamp(updateBuffer+4);
+ updateBuffer[23]=POST_TIMESTAMP_DELIMETER;
+ va_start(blarg, format);
+ vsnprintf(updateBuffer+24, MAX_RETURN_VALUE-24, format, blarg);
+ va_end(blarg);
+ if (!commandMode()) {
+ MONITOR_UART.println(updateBuffer);
+ MONITOR_UART.flush();
+ }
+};
+
+Monitor monitor;
+
+void Monitor::fatal(int newstate, const char *format, ...) {
+ va_list blarg;
+ update("FTL", format, blarg);
+ va_end(blarg);
+ //update("FTL","Fatal Error, New State = %s", soh, stateName(soh)); //maybe move this to setstate.
+ //sendActionOut();
+ //stateChange(soh);
+};
+
+void Monitor::debug(const char *format, ...) {
+ va_list blarg;
+// if (_debugLevel >= SEV_DEBUG)
+ update("DBG:", format, blarg);
+ va_end(blarg);
+};
+
+
+
+
+char * samd21m0psn(char * buffer) {
+
+ // https://gist.github.com/mgk/c9ec87436d2d679e5d08
+ volatile uint32_t val1, val2, val3, val4;
+ volatile uint32_t *ptr1 = (volatile uint32_t *)0x0080A00C;
+ val1 = *ptr1;
+ volatile uint32_t *ptr = (volatile uint32_t *)0x0080A040;
+ val2 = *ptr;
+ ptr++;
+ val3 = *ptr;
+ ptr++;
+ val4 = *ptr;
+ snprintf(buffer, MONITOR_SERIAL_NUMBER_CHARS ,"%8x%8x%8x%8x", val1, val2, val3, val4);
+
+}
+
+Monitor::Monitor() {
+
+ _debugLevel=EEPROM_NOT_SET;
+ samd21m0psn(this->_psn);
+ /*
+ * insure that all jump table pointers go somewhere
+ */
+ int k;
+
+ for (k=0;k<NKEYWORDS;k++) {
+ if (actions[k]==NULL) {
+ actions[k]=&NOP;
+ }
+ }
+}
+void Monitor::init(){
+
+
+ MONITOR_UART.begin(MONITOR_BAUD);
+ while (!MONITOR_UART)
+ delay(1); // wait for USB serial to initialize (BAD IDEA)
+// console=&MONITOR_UART;
+ MONITOR_UART.flush();
+
+
+
+ if (debugLevel()==EEPROM_NOT_SET) {
+ setDebugLevel(SEV_WARN); // default level?
+ }
+
+ monitor.setCommandMode(0);
+
+ clock.init(); // needed to timestamp debug statement.
+
+ registerAction(_SYN_, &ACK);
+ registerAction(_DVL_, &DVL);
+ registerAction(_GIT_, &GIT);
+ registerAction(_HLP_, &HLP);
+ registerAction(_CMD_, &CMD); //
+ registerAction(_SSN_, &SSN);
+ registerAction(_SWV_, &SWV);
+ registerAction(_HWV_, &HWV);
+ registerAction(_RST_, &RST);
+ registerAction(_BLD_, &BLD);
+
+ //machine.todolist.addTask(__commands);
+ //__commands.enable();
+// monitor.update("monitor init");
+
+ monitor.debug("Monitor Init");
+
+}
+
+int commandBufferIndex=0;
+bool gotLine=false;
+char commandBuffer[84]={}; // rename and use constants.
+
+void Monitor::registerAction(uint8_t ndx, actionptr action){
+ if (ndx >=0 && ndx<NKEYWORDS) {
+ actions[ndx]=action;
+ }
+}
+
+void Monitor::run() {
+ int index;
+ char key[3];
+ char action;
+ char *arguments;
+ char ch;
+ int linlen;
+// if( (monitor.console!=NULL) && monitor.console->available() ){
+// while( monitor.console->available() && commandBufferIndex < MAX_MONITOR_LINE_LENGTH && ((ch=monitor.console->read()) != '\n') && ch !='\r' ) {
+// commandBuffer[commandBufferIndex++] = isprint(ch)?ch:'*';
+// monitor.console->flush();
+// } monitor.debug("monitor run");
+
+ if( (&MONITOR_UART!=NULL) && MONITOR_UART.available() ){
+ while(MONITOR_UART.available() && commandBufferIndex < MAX_MONITOR_LINE_LENGTH && ((ch=MONITOR_UART.read()) != '\n') && ch !='\r' ) {
+ commandBuffer[commandBufferIndex++] = isprint(ch)?ch:'*';
+ MONITOR_UART.flush();
+ }
+
+ if (commandBufferIndex && ((ch=='\n')||(ch=='\r'))) {
+ while (commandBufferIndex<4) { commandBuffer[commandBufferIndex++]='*';};
+ // things get questionable if there are less than 4 characters.
+ commandBuffer[commandBufferIndex]='\0';
+ commandBufferIndex=0;
+ gotLine=true;
+ }
+ }
+
+ if (gotLine) {
+ key[0]=toupper(commandBuffer[0]);
+ key[1]=toupper(commandBuffer[1]);
+ key[2]=toupper(commandBuffer[2]);
+ action=commandBuffer[3];
+ arguments=commandBuffer+4;
+ index=monitor.lookupIndex(key);
+ if (index>=0&&index<NKEYWORDS) {
+ actions[index](index,action,arguments);
+ } else {
+ monitor.update("NAK","%c%c%c[%c] is not understood HLP? for a list of keywords",
+ key[0],key[1],key[2],action); // better than no response...
+ }
+ gotLine=false;
+ }
+}
+
+int Monitor::lookupIndex(char *key) {
+ int ndx=0;
+ int ptr=0;
+ while (ndx<NKEYWORDS) {
+ if ( ( keywords[ptr]==toupper(key[0]) )
+ && ( keywords[ptr+1] == toupper(key[1]) )
+ && ( keywords[ptr+2] == toupper(key[2]) )
+ ) { return ndx;
+ } else {
+ ndx++;
+ ptr+=3;
+ }
+ }
+ return -1;
+}
+
+
+char keyBuff[4]; //fix or move this ???.
+
+char * Monitor::lookupKey(int ndx) {
+ int ptr=0;
+ keyBuff[0]=keyBuff[1]=keyBuff[2]='?';
+ if (ndx >=0 && ndx<NKEYWORDS) {
+ ptr=ndx*3;
+ keyBuff[0]=(keywords[ptr]);
+ keyBuff[1]=(keywords[ptr+1]);
+ keyBuff[2]=(keywords[ptr+2]);
+ keyBuff[3]='\0';
+ }
+
+ return keyBuff;
+}
+
+
+
+extern "C" char *sbrk(int i);
+
+int getFreeMemory()
+{
+
+ // avr specific
+ // extern int __heap_start, *__brkval;
+ // int v;
+ // return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
+ // return 0;
+ //https://learn.adafruit.com/adafruit-feather-m0-basic-proto/adapting-sketches-to-m0
+ char stack_dummy = 0;
+ return &stack_dummy - sbrk(0);
+
+}
+
+#ifdef ARDUINO_SAMD_ZERO
+#include "Adafruit_SleepyDog.h"
+#include "Reset.h"
+
+void jump2bootloader(){
+ initiateReset(10);
+}
+void reboot(){
+ Watchdog.enable(150);
+ for(;;);
+}
+#elif defined(ARDUINO_AVR_MICRO) || defined(ARDUINO_AVR_LEONARDO)
+#include <avr/wdt.h>
+#ifndef MAGIC_KEY
+#define MAGIC_KEY 0x7777
+#endif
+#ifndef MAGIC_KEY_POS
+#define MAGIC_KEY_POS 0x0800
+#endif
+void jump2bootloader(){
+ int16_t magic_key_pos = MAGIC_KEY_POS;
+ *(uint16_t *)magic_key_pos = MAGIC_KEY;
+ wdt_enable(WDTO_120MS);
+ for(;;);
+}
+void reboot(){
+ int16_t magic_key_pos = MAGIC_KEY_POS;
+ *(uint16_t *)magic_key_pos = 0;
+ wdt_enable(WDTO_120MS);
+ for(;;);
+
+}
+#endif
+
+
+
+
+
+