From a97fc7f0874a3a35419f5af53cc11f7840a91530 Mon Sep 17 00:00:00 2001
From: Karol Hennessy <revkarol@gmail.com>
Date: Sat, 11 Apr 2020 15:07:59 +0200
Subject: [PATCH] update to lib for breathing with comms

---
 .../breathing_with_comms/src/MemoryFree.cpp   | 52 +++++++++++++
 arduino/breathing_with_comms/src/MemoryFree.h | 18 +++++
 arduino/breathing_with_comms/src/main.cpp     | 24 ++++--
 .../breathing_with_comms/src/test_hw_loop.cpp |  4 +-
 .../common/lib/commsControl/commsConstants.h  | 74 ++++++++++---------
 .../common/lib/commsControl/commsControl.cpp  | 37 +++++-----
 .../common/lib/commsControl/commsControl.h    |  6 +-
 .../common/lib/commsControl/commsFormat.cpp   |  1 -
 arduino/common/lib/commsControl/commsFormat.h | 14 ++++
 raspberry-dataserver/commsDebug.py            | 15 +++-
 10 files changed, 176 insertions(+), 69 deletions(-)
 create mode 100644 arduino/breathing_with_comms/src/MemoryFree.cpp
 create mode 100644 arduino/breathing_with_comms/src/MemoryFree.h

diff --git a/arduino/breathing_with_comms/src/MemoryFree.cpp b/arduino/breathing_with_comms/src/MemoryFree.cpp
new file mode 100644
index 00000000..bf571845
--- /dev/null
+++ b/arduino/breathing_with_comms/src/MemoryFree.cpp
@@ -0,0 +1,52 @@
+#if (ARDUINO >= 100)
+#include <Arduino.h>
+#else
+#include <WProgram.h>
+#endif
+
+extern unsigned int __heap_start;
+extern void *__brkval;
+
+/*
+ * The free list structure as maintained by the
+ * avr-libc memory allocation routines.
+ */
+struct __freelist
+{
+  size_t sz;
+  struct __freelist *nx;
+};
+
+/* The head of the free list structure */
+extern struct __freelist *__flp;
+
+#include "MemoryFree.h"
+
+/* Calculates the size of the free list */
+int freeListSize()
+{
+  struct __freelist* current;
+  int total = 0;
+  for (current = __flp; current; current = current->nx)
+  {
+    total += 2; /* Add two bytes for the memory block's header  */
+    total += (int) current->sz;
+  }
+
+  return total;
+}
+
+int freeMemory()
+{
+  int free_memory;
+  if ((int)__brkval == 0)
+  {
+    free_memory = ((int)&free_memory) - ((int)&__heap_start);
+  }
+  else
+  {
+    free_memory = ((int)&free_memory) - ((int)__brkval);
+    free_memory += freeListSize();
+  }
+  return free_memory;
+}
diff --git a/arduino/breathing_with_comms/src/MemoryFree.h b/arduino/breathing_with_comms/src/MemoryFree.h
new file mode 100644
index 00000000..f9d7cad7
--- /dev/null
+++ b/arduino/breathing_with_comms/src/MemoryFree.h
@@ -0,0 +1,18 @@
+// MemoryFree library based on code posted here:
+// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1213583720/15
+// Extended by Matthew Murdoch to include walking of the free list.
+
+#ifndef	MEMORY_FREE_H
+#define MEMORY_FREE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int freeMemory();
+
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
diff --git a/arduino/breathing_with_comms/src/main.cpp b/arduino/breathing_with_comms/src/main.cpp
index 621a77b4..2d2de750 100644
--- a/arduino/breathing_with_comms/src/main.cpp
+++ b/arduino/breathing_with_comms/src/main.cpp
@@ -1,9 +1,16 @@
 #include <Arduino.h>
+#include <MemoryFree.h>
 #include "commsControl.h"
 #include "test_hw_loop.h"
 #include "common.h"
 
 int ventilation_mode = HEV_MODE_PS;
+
+const uint16_t report_freq = 1 ; // in Hz
+const uint16_t update_freq = 100 ; // in Hz
+
+uint16_t report_cnt = 0;
+
 float working_pressure = 1;             //?
 float inspiratory_minute_volume = 6000; // ml/min
 float respiratory_rate = 15;            //  10-40 +-1 ;aka breaths_per_min
@@ -106,23 +113,28 @@ void loop()
     data.readback_valve_inhale = vinhale;
     data.readback_valve_exhale = vexhale;
     data.readback_valve_purge = vpurge;
+    data.pressure_o2_supply = freeMemory() & 0xFFFF;
+    data.pressure_o2_regulated = freeMemory() >> 16;
     // TODO ; add to dataFormat
     // data.readback_valve_atmosphere = vpurge;
 
-    //breath_cycle();
     FSM_assignment();
     FSM_breath_cycle();
 
-    plSend.setType(payloadType::payloadData);
-    plSend.setData(&data);
-    comms.writePayload(&plSend);
+    report_cnt++;
+    if(report_cnt % (update_freq/report_freq) == 0)
+    {
+        plSend.setType(payloadType::payloadData);
+        plSend.setData(&data);
+        comms.writePayload(plSend);
+    }
     // per cycle sender
     comms.sender();
     // per cycle receiver
     comms.receiver();
 
     uint8_t cmdCode = 0;
-    if(comms.readPayload(&plReceive)){
+    if(comms.readPayload(plReceive)){
       if (plReceive.getType() == payloadType::payloadCmd) {
           cmdCode = (plReceive.getCmd()->cmdCode);
           plReceive.setType(payloadType::payloadUnset);
@@ -138,5 +150,5 @@ void loop()
         default:
         break;
     }
-    delay(10);
+    delay(1000/update_freq);
 }
diff --git a/arduino/breathing_with_comms/src/test_hw_loop.cpp b/arduino/breathing_with_comms/src/test_hw_loop.cpp
index 2e84c744..14597919 100644
--- a/arduino/breathing_with_comms/src/test_hw_loop.cpp
+++ b/arduino/breathing_with_comms/src/test_hw_loop.cpp
@@ -26,7 +26,7 @@ void FSM_assignment( ) {
         switch (bs_state)
         {
         case BS_IDLE:
-            if (running == false) {
+            if (running == true) {
                 next_state = BS_BUFF_PREFILL;
                 FSM_time = millis();
                 // Serial.println("Exit IDLE") ;
@@ -99,7 +99,7 @@ void FSM_breath_cycle()
     switch (bs_state) {
         case BS_IDLE:
             
-            if (running == false) {
+            if (running == true) {
                 FSM_time = millis();
             } else {
                 timeout = 1000; 
diff --git a/arduino/common/lib/commsControl/commsConstants.h b/arduino/common/lib/commsControl/commsConstants.h
index 4a633c95..072b4183 100644
--- a/arduino/common/lib/commsControl/commsConstants.h
+++ b/arduino/common/lib/commsControl/commsConstants.h
@@ -5,7 +5,7 @@
 
 #define CONST_TIMEOUT_ALARM 5
 #define CONST_TIMEOUT_DATA  10
-#define CONST_TIMEOUT_CMD   50
+#define CONST_TIMEOUT_CMD   5
 
 
 #define CONST_MAX_SIZE_RB_RECEIVING 10
@@ -31,20 +31,14 @@
 #define PACKET_DATA  0x40
 #define PACKET_SET   0x20 //set vs get ?
 
-// TODO: make sensible
-#define PRESSURE_PEEP_LOW  0x01
-#define PRESSURE_PEEP_HIGH 0x02
-
 #define HEV_FORMAT_VERSION 0xA0
 
-enum command_codes {CMD_START = 1, 
+enum command_codes {CMD_START = 1,
                     CMD_STOP  = 2};
 
 // struct for all data sent
-
 struct dataFormat {
-    uint8_t  version = HEV_FORMAT_VERSION; // 
-    uint8_t  size = 27; // in bytes (includes version and size itself)
+    uint8_t  version = HEV_FORMAT_VERSION; //
     uint8_t  fsm_state = 0;
     uint16_t pressure_air_supply = 0;
     uint16_t pressure_air_regulated = 0;
@@ -60,19 +54,17 @@ struct dataFormat {
     uint8_t  readback_valve_inhale = 0;
     uint8_t  readback_valve_exhale = 0;
     uint8_t  readback_valve_purge = 0;
-    uint8_t  readback_mode = 0; 
+    uint8_t  readback_mode = 0;
 };
 
 struct cmdFormat {
-    uint8_t  version = HEV_FORMAT_VERSION; // 
-    uint8_t  size    = 7; // in bytes (includes version and size itself)
+    uint8_t  version = HEV_FORMAT_VERSION; //
     uint8_t  cmdCode = 0;
     uint32_t  param   = 0;
 };
 
 struct alarmFormat{
-    uint8_t  version = HEV_FORMAT_VERSION; // 
-    uint8_t  size    = 7; // in bytes (includes version and size itself)
+    uint8_t  version = HEV_FORMAT_VERSION; //
     uint8_t  alarmCode = 0;
     uint32_t param   = 0;
                     // do we do the same as dataFormat and put all alarms in one message?
@@ -91,28 +83,44 @@ enum payloadType {
 // information is set as information in the protocol
 class payload {
 public:
-    payload(payloadType type = payloadType::payloadUnset)  {type_ = type; data_ = nullptr; cmd_ = nullptr; alarm_ = nullptr; }
-    ~payload() {unsetData(); unsetAlarm(); unsetCmd();}
+    payload(payloadType type = payloadType::payloadUnset)  {type_ = type; } //data_ = nullptr; cmd_ = nullptr; alarm_ = nullptr; }
+    payload(const payload &other) {
+//        unsetAll();
+        type_ = other.type_;
+        /*if ( other. data_ != nullptr) {  data_ = new  dataFormat;*/ memcpy(& data_, & other.data_, sizeof( dataFormat));// } else { data_ = nullptr; }
+        /*if ( other.  cmd_ != nullptr) {   cmd_ = new   cmdFormat;*/ memcpy(&  cmd_, &  other.cmd_, sizeof(  cmdFormat));// } else {  cmd_ = nullptr; }
+        /*if ( other.alarm_ != nullptr) { alarm_ = new alarmFormat;*/ memcpy(&alarm_, &other.alarm_, sizeof(alarmFormat));// } else {alarm_ = nullptr; }
+    }
+    payload& operator=(const payload& other) {
+//        unsetAll();
+        type_ = other.type_;
+        /*if ( other. data_ != nullptr) {  data_ = new  dataFormat;*/ memcpy(& data_, & other.data_, sizeof( dataFormat));// } else { data_ = nullptr; }
+        /*if ( other.  cmd_ != nullptr) {   cmd_ = new   cmdFormat;*/ memcpy(&  cmd_, &  other.cmd_, sizeof(  cmdFormat));// } else {  cmd_ = nullptr; }
+        /*if ( other.alarm_ != nullptr) { alarm_ = new alarmFormat;*/ memcpy(&alarm_, &other.alarm_, sizeof(alarmFormat));// } else {alarm_ = nullptr; }
+
+        return *this;
+    }
+
+    ~payload() {;}//unsetData(); unsetAlarm(); unsetCmd();}
 
     void setType(payloadType type) { type_ = type; }
     payloadType getType() {return type_; }
 
     // requires argument as new struct
-    void setData (dataFormat   *data) { unsetAll();  data_ = new  dataFormat; memcpy( data_,  data,  data->size); }
-    void setCmd  (cmdFormat     *cmd) { unsetAll();   cmd_ = new   cmdFormat; memcpy(  cmd_,   cmd,   cmd->size); }
-    void setAlarm(alarmFormat *alarm) { unsetAll(); alarm_ = new alarmFormat; memcpy(alarm_, alarm, alarm->size); }
+    void setData (dataFormat   *data) { /*unsetAll(); type_ = payloadType::payloadData;   data_ = new  dataFormat(  *data); }*/ memcpy(& data_,  data, sizeof( dataFormat)); }
+    void setCmd  (cmdFormat     *cmd) { /*unsetAll(); type_ = payloadType::payloadCmd;     cmd_ = new   cmdFormat(   *cmd); }*/ memcpy(&  cmd_,   cmd, sizeof(  cmdFormat)); }
+    void setAlarm(alarmFormat *alarm) { /*unsetAll(); type_ = payloadType::payloadAlarm; alarm_ = new alarmFormat( *alarm); }*/ memcpy(&alarm_, alarm, sizeof(alarmFormat)); }
 
-    dataFormat  *getData () {return  data_; }
-    cmdFormat   *getCmd  () {return   cmd_; }
-    alarmFormat *getAlarm() {return alarm_; }
+    dataFormat  *getData () {return  &data_; }
+    cmdFormat   *getCmd  () {return   &cmd_; }
+    alarmFormat *getAlarm() {return &alarm_; }
 
-    void unsetAll()   { unsetData(); unsetAlarm(); unsetCmd(); }
-    void unsetData()  { if ( data_ != nullptr) { delete  data_;  data_ = nullptr; } }
-    void unsetCmd()   { if (  cmd_ != nullptr) { delete   cmd_;   cmd_ = nullptr; } }
-    void unsetAlarm() { if (alarm_ != nullptr) { delete alarm_; alarm_ = nullptr; } }
+//    void unsetAll()   { unsetData(); unsetAlarm(); unsetCmd(); type_ = payloadType::payloadUnset; }
+//    void unsetData()  { if ( data_ != nullptr) { delete  data_;  data_ = nullptr; } }
+//    void unsetCmd()   { if (  cmd_ != nullptr) { delete   cmd_;   cmd_ = nullptr; } }
+//    void unsetAlarm() { if (alarm_ != nullptr) { delete alarm_; alarm_ = nullptr; } }
 
     void setPayload(payloadType type, void* dt) {
-        setType(type);
         switch (type) {
             case payloadType::payloadData:
                 setData(reinterpret_cast<dataFormat*>(dt));
@@ -145,11 +153,11 @@ public:
     uint8_t getInformationSize()  {
         switch (type_) {
             case payloadType::payloadData:
-                return getData()->size;
+                return static_cast<uint8_t>(sizeof( dataFormat));
             case payloadType::payloadCmd:
-                return getCmd()->size;
+                return static_cast<uint8_t>(sizeof(  cmdFormat));
             case payloadType::payloadAlarm:
-                return getAlarm()->size;
+                return static_cast<uint8_t>(sizeof(alarmFormat));
             default:
                 return 0;
         }
@@ -158,9 +166,9 @@ public:
 private:
     payloadType type_;
 
-    dataFormat   *data_;
-    cmdFormat     *cmd_;
-    alarmFormat *alarm_;
+    dataFormat   data_;
+    cmdFormat     cmd_;
+    alarmFormat alarm_;
 };
 
 #endif
diff --git a/arduino/common/lib/commsControl/commsControl.cpp b/arduino/common/lib/commsControl/commsControl.cpp
index 86c7570d..62a89385 100644
--- a/arduino/common/lib/commsControl/commsControl.cpp
+++ b/arduino/common/lib/commsControl/commsControl.cpp
@@ -19,7 +19,7 @@ commsControl::commsControl(uint32_t baudrate) {
     queueData_  = new RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING>();
     queueCmd_   = new RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING>();
 
-    queueReceived_ = new RingBuf<payload *, CONST_MAX_SIZE_RB_RECEIVING>();
+    queueReceived_ = new RingBuf<payload, CONST_MAX_SIZE_RB_RECEIVING>();
 
     commsTmp_   = commsFormat(CONST_MAX_SIZE_PACKET - CONST_MIN_SIZE_PACKET );
 
@@ -135,45 +135,44 @@ void commsControl::receiver() {
     }
 }
 
-bool commsControl::writePayload(payload *pl) {
+bool commsControl::writePayload(payload &pl) {
     commsFormat* tmpComms;
+    payloadType type = pl.getType();
 
     // switch on different received payload types
     // TODO simplify the static functions
-    switch(pl->getType()) {
+    switch(type) {
         case payloadAlarm:
-            tmpComms = commsFormat::generateALARM(pl);
+            tmpComms = commsFormat::generateALARM(&pl);
             break;
         case payloadData:
-            tmpComms = commsFormat::generateDATA(pl);
+            tmpComms = commsFormat::generateDATA(&pl);
             break;
         case payloadCmd:
-            tmpComms = commsFormat::generateCMD(pl);
+            tmpComms = commsFormat::generateCMD(&pl);
             break;
         default:
             return false;
     }
 
+    RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *tmpQueue = getQueue(&type);
     // add new entry to the queue
-    if (queueData_->isFull()) {
+    if (tmpQueue->isFull()) {
         commsFormat *tmpCommsRm;
-        if (queueData_->pop(tmpCommsRm)) {
+        if (tmpQueue->pop(tmpCommsRm)) {
             delete tmpCommsRm;
         }
     }
 
-    if (queueData_->push(tmpComms) ) {
+    if (tmpQueue->push(tmpComms) ) {
         return true;
     }
     return false;
 }
 
-bool commsControl::readPayload( payload* pl) {
+bool commsControl::readPayload( payload &pl) {
     if ( !queueReceived_->isEmpty()) {
-        payload *tmpPl;
-        if (queueReceived_->pop(tmpPl)) {
-            memcpy(pl, tmpPl, sizeof(payload));
-            delete tmpPl;
+        if (queueReceived_->pop(pl)) {
             return true;
         }
     }
@@ -259,9 +258,8 @@ void commsControl::resendPacket(RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING
 
 
 // receiving anything of commsFormat
-// TODO remove address and use commsTmp only
 bool commsControl::receivePacket(payloadType *type) {
-    payload *tmpPl = new payload(*type);
+    payload tmpPl = payload(*type);
 
     void *tmpInformation = nullptr;
     switch (*type) {
@@ -282,13 +280,12 @@ bool commsControl::receivePacket(payloadType *type) {
         return false;
     }
     memcpy(tmpInformation, commsTmp_.getInformation(), commsTmp_.getInfoSize());
-    tmpPl->setPayload(*type, tmpInformation);
+    tmpPl.setPayload(*type, tmpInformation);
 
     // remove first entry if RB is full
     if (queueReceived_->isFull()) {
-        payload *tmpDataRm = nullptr;
-        if (queueReceived_->pop(tmpDataRm)) {
-            delete tmpDataRm;
+        payload tmpPlRm;
+        if (queueReceived_->pop(tmpPlRm)) {
         }
     }
 
diff --git a/arduino/common/lib/commsControl/commsControl.h b/arduino/common/lib/commsControl/commsControl.h
index e0417884..789f3605 100644
--- a/arduino/common/lib/commsControl/commsControl.h
+++ b/arduino/common/lib/commsControl/commsControl.h
@@ -19,8 +19,8 @@ public:
 
     void beginSerial();
 
-    bool writePayload(payload *pl);
-    bool readPayload (payload *pl);
+    bool writePayload(payload &pl);
+    bool readPayload (payload &pl);
 
     void sender();
     void receiver();
@@ -50,7 +50,7 @@ private:
     RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queueData_;
     RingBuf<commsFormat *, CONST_MAX_SIZE_RB_SENDING> *queueCmd_;
 
-    RingBuf<payload *, CONST_MAX_SIZE_RB_RECEIVING> *queueReceived_;
+    RingBuf<payload, CONST_MAX_SIZE_RB_RECEIVING> *queueReceived_;
 
     commsFormat commsTmp_;
 
diff --git a/arduino/common/lib/commsControl/commsFormat.cpp b/arduino/common/lib/commsControl/commsFormat.cpp
index affb4200..b4951e59 100644
--- a/arduino/common/lib/commsControl/commsFormat.cpp
+++ b/arduino/common/lib/commsControl/commsFormat.cpp
@@ -73,7 +73,6 @@ void commsFormat::generateCrc(bool assign) {
 
     // assign crc to fcs
     if (assign) {
-        ;
         assignBytes(getFcs(), reinterpret_cast<uint8_t*>(&crc_), 2, false);
     }
 }
diff --git a/arduino/common/lib/commsControl/commsFormat.h b/arduino/common/lib/commsControl/commsFormat.h
index ddfc6e3a..81b2ca47 100644
--- a/arduino/common/lib/commsControl/commsFormat.h
+++ b/arduino/common/lib/commsControl/commsFormat.h
@@ -14,6 +14,20 @@
 class commsFormat {
 public:
     commsFormat(uint8_t infoSize = 0, uint8_t address = 0x00, uint16_t control = 0x0000);
+    commsFormat(const commsFormat& other) {
+        crc_        = other.crc_;
+        packetSize_ = other.packetSize_;
+        infoSize_   = other.infoSize_;
+        memcpy(data_, other.data_, CONST_MAX_SIZE_PACKET);
+    }
+    commsFormat& operator=(const commsFormat& other) {
+        crc_        = other.crc_;
+        packetSize_ = other.packetSize_;
+        infoSize_   = other.infoSize_;
+        memcpy(data_, other.data_, CONST_MAX_SIZE_PACKET);
+
+        return *this;
+    }
 
     uint8_t* getData()    { return data_; }
     uint8_t  getSize()    { return packetSize_; }
diff --git a/raspberry-dataserver/commsDebug.py b/raspberry-dataserver/commsDebug.py
index 47effb6b..09cfaa5c 100755
--- a/raspberry-dataserver/commsDebug.py
+++ b/raspberry-dataserver/commsDebug.py
@@ -1,5 +1,6 @@
 #!/usr/bin/env python3
 from commsControl import commsControl
+from commsConstants import *
 import logging
 logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
 import sys
@@ -18,17 +19,23 @@ class Dependant(object):
         logging.info(f"payload received: {payload}")
         self._llipacket = payload.getDict() # returns a dict
         # pop from queue - protects against Dependant going down and not receiving packets
-        self._lli.pop_payloadrecv()
+        self._lli.poppayloadrecv_()
 
 dep = Dependant(comms)
-
 start = 0x1
 stop =  0x2
 
-#comms.registerData(start)
-# comms.sender()
+cmd = commandFormat()
+cmd.cmdCode = start
+cmd.toByteArray()
+
+comms.writePayload(cmd)
+#comms.sender()
 while True:
     time.sleep(30)
+    cmd.cmdCode = stop
+    cmd.toByteArray()
+    comms.writePayload(cmd)
     #comms.registerData(stop)
     pass
 
-- 
GitLab