afLib 1.3 which is supporting both SPI and UART

Dependencies:   vt100 mbed afLib_1_3

Files at this revision

API Documentation at this revision

Comitter:
Rhyme
Date:
Mon Apr 23 06:15:26 2018 +0000
Child:
1:90652e9012b9
Commit message:
First UART working version

Changed in this revision

afLib.lib Show annotated file Show diff for this revision Revisions of this file
af_utils/af_attriburtes.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/af_attributes.h Show annotated file Show diff for this revision Revisions of this file
af_utils/af_mgr.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/af_mgr.h Show annotated file Show diff for this revision Revisions of this file
af_utils/edgeSerial.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/edgeSerial.h Show annotated file Show diff for this revision Revisions of this file
af_utils/mbedSPI.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/mbedSPI.h Show annotated file Show diff for this revision Revisions of this file
af_utils/mbedUART.cpp Show annotated file Show diff for this revision Revisions of this file
af_utils/mbedUART.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_mgr.cpp Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_mgr.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_pin.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_reset_mgr.cpp Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_reset_mgr.h Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_time.cpp Show annotated file Show diff for this revision Revisions of this file
edge_utils/edge_time.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
vt100.lib Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/afLib.lib	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,1 @@
+afLib#112741fe45d1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_attriburtes.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,338 @@
+#include "mbed.h"
+#include <ctype.h>
+#include "af_attributes.h"
+#include "af_mgr.h"
+#include "edge_time.h"
+#include "edge_mgr.h"
+#include "edge_reset_mgr.h"
+
+
+static const af_attribute_type af_attr[] = {
+#if 1
+/*     ID,                     Description,                Type,                Size */     
+/* Software Reset Request */    
+    {  ATTR_SOFTWARE_RESET,   "Software Reset",            ATTRIBUTE_TYPE_BOOLEAN, 1 },
+    {  ATTR_MCU_RESET_REASON, "MCU Reset Reason",          ATTRIBUTE_TYPE_UTF8S,  64 },
+    
+    { ATTR_LED,               "LED",                       ATTRIBUTE_TYPE_SINT16,  2 },
+    { ATTR_IO0,               "I/O 0",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_IO1,               "I/O 1",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_IO2,               "I/O 2",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_BUTTON,            "BUTTON",                    ATTRIBUTE_TYPE_BOOLEAN, 2 },
+    { ATTR_IO3,               "I/O 3",                     ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_BOOT_LOADER_VER,   "Bootloader Version",        ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_BLE_STACK_VER,     "BLE Stack Version",         ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_FW_APP_VER,        "FW Application Version",    ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_DEVICE_DESC,       "Device Description",        ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_WIFI_VER,          "Wi-Fi chip",                ATTRIBUTE_TYPE_SINT64,  8 },
+    { ATTR_OFFLINE_SCHED,     "Offline Schedules enable",  ATTRIBUTE_TYPE_SINT16,  2 }, 
+    { ATTR_SECURITY_ENABLED,  "Security Enabled",          ATTRIBUTE_TYPE_SINT8,   1 }, /* ? */
+    { ATTR_UTC_OFFSET,        "UTC offset data",           ATTRIBUTE_TYPE_BYTES,   8 },
+    { ATTR_CONFIGURES_SSID,   "Configured SSID",           ATTRIBUTE_TYPE_UTF8S,  10 }, /* ? */
+    { ATTR_WIFI_BARS,         "Wi-Fi Bars",                ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_WIFI_STDY_STATE,   "Wi-Fi Steady State",        ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_COMMAND,           "Command",                   ATTRIBUTE_TYPE_BYTES,   8 }, /* ? */   
+    { ATTR_ASR_STATE,         "ASR State",                 ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_LOW_BATTERY,       "Low Battery Warning",       ATTRIBUTE_TYPE_SINT8,   1 },
+    { ATTR_LINKED_TIMESTAMP,  "Linked Timestamp",          ATTRIBUTE_TYPE_SINT32,  4 },
+    { ATTR_ATTR_ACK,          "Attribute ACK",             ATTRIBUTE_TYPE_SINT16,  8 },
+    { ATTR_REBOOT_REASON,     "Reboot Reason",             ATTRIBUTE_TYPE_UTF8S, 100 },
+    { ATTR_BLE_COMMS,         "BLE Comms",                 ATTRIBUTE_TYPE_BYTES,  12 },
+    { ATTR_MCU_INTERFACE,     "MCU Interface",             ATTRIBUTE_TYPE_SINT8,   1 },
+    { 0,                      0,                           0,                      0 }
+} ;
+#endif
+
+int get_af_attr(uint16_t id) 
+{
+    int i ;
+    for (i = 0 ; af_attr[i].id != 0 ; i++ ) {
+        if (id == af_attr[i].id) {
+            break ;
+        }
+    }
+    return (i) ;
+}
+
+void print_af_error(int resultCode) 
+{
+    switch(resultCode) {
+    case afSUCCESS:
+        tty->printf("Operation completed successfully\n") ;
+        break ;
+    case afERROR_NO_SUCH_ATTRIBUTE:
+        tty->printf("Request was made for unknown attribute id\n") ;
+        break ;
+    case afERROR_BUSY:
+        tty->printf("Request already in progress, try again\n") ;
+        break ;
+    case afERROR_INVALID_COMMAND:
+        tty->printf("Command could not be parsed\n") ;
+        break ;
+    case afERROR_QUEUE_OVERFLOW:
+        tty->printf("Queue is full\n") ;
+        break ;
+    case afERROR_QUEUE_UNDERFLOW:
+        tty->printf("Queue is empty\n") ;
+        break ;
+    case afERROR_INVALID_PARAM:
+        tty->printf("Bad input parameter\n") ;
+        break ;
+    default:
+        tty->printf("Unknown error code %d\n", resultCode) ;
+        break ;
+    }
+}
+
+void af_print_values(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) 
+{
+    int i, id ;
+
+    id = get_af_attr(attributeId) ;
+
+    if (af_attr[id].id  != 0) {
+        tty->printf(af_attr[id].description) ;
+        tty->printf(" : ") ;
+        switch(af_attr[id].attribute_type) {
+        case ATTRIBUTE_TYPE_BOOLEAN:
+        case ATTRIBUTE_TYPE_SINT8: 
+            if (valueLen >= 1) {
+                tty->printf("%02X\n", value[0]) ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_SINT16:
+            if (valueLen >= 2) {
+                tty->printf("%02X%02X\n", value[1], value[0]) ;
+            }
+            break ; 
+        case ATTRIBUTE_TYPE_SINT32:
+            if (valueLen >= 4) {
+                tty->printf("%02X%02X%02X%02X\n",
+                    value[3],value[2],value[1],value[0]) ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_SINT64:
+            if (valueLen >= 8) {
+                tty->printf("%02X%02X %02X%02X %02X%02X %02X%02X\n",
+                    value[7], value[6], value[5], value[4],
+                    value[3], value[2], value[1], value[0]) ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_UTF8S: 
+            if (valueLen > 0) {
+                for (i = 0 ; i < valueLen ; i++) {
+                    if (isprint(value[i])) {
+                        tty->printf("%c", value[i]) ;
+                    } else if (value[i] == 0) { /* string terminator NULL */
+                        break ;
+                    } else {
+                        tty->printf("\'%02X\'",value[i]) ;
+                    }
+                }
+                tty->printf("\n") ;
+            }
+            break ;
+        case ATTRIBUTE_TYPE_BYTES:
+        default:
+            if (valueLen > 0) {
+                for (i = 0 ; i < valueLen ; i++ ) {
+                    tty->printf("%02X ", value[i]) ;
+                }
+                tty->printf("\n") ;
+            }
+            break ;
+        }
+    } else {
+        if (valueLen > 0) {
+            for (i = 0 ; i < valueLen ; i++ ) {
+                tty->printf("%02X ", value[i]) ;
+            }
+            tty->printf("\n") ;
+        }
+    }
+//    tty->printf("\n") ;
+}
+
+bool assignAttribute(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value,
+    bool fromRequest
+) 
+{
+    bool result = true ;
+    switch(attributeId) {
+    case ATTR_LINKED_TIMESTAMP: /* timestamp */  
+        set_time(valueLen, value) ; /* 68 us */
+//        if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+        tty->printf("timestamp = ") ;
+        print_date_wd(&current_time) ;
+//        print_time(&current_time) ;
+        tty->printf("\n") ;
+        break ;  
+    case ATTR_SOFTWARE_RESET: /* software reset requested! */
+        if (value[0]) {
+            printf("Software Reset Requested!\n") ;
+            reset_watch_dog() ;
+//            if (fromRequest) afero->setAttributeComplete(requestId, attributeId, valueLen, value) ;
+            wait(0.5) ;
+            reboot_edge() ;
+        }
+        break ;          
+    default:
+        break ;    
+    }
+    return result ;
+}
+
+/*
+ * Callback that allows ASR to request an MCU attribute be changed. 
+ * You should define this function in your MCU firmware to perform application-specific actions 
+ * your code must take (e.g., updating the state of the hardware), 
+ * in light of the attribute value change.
+*/
+bool attributeChangeRequest(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) 
+{ 
+    int result ;
+    uint32_t timestamp = edge_time ;
+
+    ts2time(timestamp, &current_time) ; /* 12 us */
+//    if (verbos) {
+        print_time(&current_time) ;
+        tty->printf(" %5d ASR requested [%d] : ", attributeId, requestId) ;
+        af_print_values(requestId, attributeId, valueLen, value) ;
+//    }
+
+    result = assignAttribute(requestId, attributeId, valueLen, value, true) ;
+
+//    af_print_values(requestId, attributeId, valueLen, value) ;
+    return(result == afSUCCESS) ;
+}
+
+/*
+ * Application callback that allows afLib to notify that an attribute has changed. 
+ * This method will be called in response to a getAttribute call from the application 
+ * and whenever a ASR module attribute changes.
+ */
+void attributeUpdatedReport(
+    const uint8_t   requestId,
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) 
+{
+    uint32_t timestamp = edge_time ;
+    int result ;
+
+    ts2time(timestamp, &current_time) ; /* 12us */
+//    if (verbos) {
+        print_time(&current_time) ;
+        tty->printf(" %5d ASR reported [%d]: ", attributeId, requestId) ;
+        af_print_values(requestId, attributeId, valueLen, value) ;
+//    }
+
+    switch(attributeId) {
+    case ATTR_LED:
+        tty->printf("LED : ") ;
+        if (value[0]) {
+            tty->printf("ON\n") ;
+        } else {
+            tty->printf("OFF\n") ;
+        }
+        break ;
+    case ATTR_LINKED_TIMESTAMP:
+        set_time(valueLen, value) ; /* 68 us */
+        tty->printf("timestamp = ") ;
+        print_date_wd(&current_time) ;
+//        print_time(&current_time) ;
+        tty->printf("\n") ;
+        break ;         
+    case ATTR_WIFI_STDY_STATE:
+        gConnected = false ;
+        tty->printf("WiFi Steady State: ") ;
+        switch(value[0]) {
+        case 0: tty->printf("Not Connected\n")      ; break ;
+        case 1: tty->printf("Pending\n") ;            break ;
+        case 2: 
+            tty->printf("Connected\n") ;       
+            gConnected = true ; // the only case Connected state is OK   
+            break ;
+        case 3: tty->printf("Unknown Failure\n") ;    break ;
+        case 4: tty->printf("Association Failed\n") ; break ;
+        case 5: tty->printf("Handshake Failed\n") ;   break ;
+        case 6: tty->printf("Echo Failed\n") ;        break ;
+        case 7: tty->printf("SSID Not Found\n") ;     break ;
+        case 8: tty->printf("NTP Failed\n") ;         break ;
+        default: tty->printf("Unknown [%d]\n", value[0]) ; break ;
+        }
+        break ;
+    case ATTR_REBOOT_REASON:
+        tty->printf("Reboot Reason: ") ;
+        switch(value[0]) {
+        case 1: tty->printf("Reset pin asserted\n") ; break ;
+        case 2: tty->printf("Watchdog reset\n") ;     break ;
+        case 4: tty->printf("Software reset\n") ;     break ;
+        case 8: tty->printf("CPU Lock up\n") ;        break ;
+        default: tty->printf("Unknown [%d]\n", value[0]) ;     break ;
+        }
+        break ; 
+    case ATTR_MCU_INTERFACE:
+        tty->printf("MCU Interface: ") ;
+        switch(value[0]) {
+        case 0:  tty->printf("No MCU\n") ;    break ;
+        case 1:  tty->printf("SPI Slave\n") ; break ;
+        case 2:  tty->printf("UART\n") ;      break ;
+        default: tty->printf("Unknown\n") ;   break ; 
+        }
+        break ;
+    case AF_SYSTEM_ASR_STATE:
+        tty->printf("ASR state: ") ;
+        switch(value[0]) {
+        case MODULE_STATE_REBOOTED:
+            gLinked = false ;
+            tty->printf("Rebooted\n") ;
+            wait_ms(100) ;
+            if (edge_mgr_status == EDGE_MGR_RUNNING) {
+                reboot_edge() ;
+            }
+            break ;
+        case MODULE_STATE_LINKED:
+            if (gLinked == false) { /* new link established */
+                result = afero->getAttribute(ATTR_LINKED_TIMESTAMP) ;
+            }
+            gLinked = true ;
+            tty->printf("Linked\n") ;
+            break ;
+        case MODULE_STATE_UPDATING:
+            gLinked = true ; 
+            tty->printf("Updating\n") ;
+            break ;
+        case MOUDLE_STATE_UPDATE_READY:
+            gLinked = false ;
+            tty->printf("Update ready - rebooting\n") ;
+            while(afero->setAttribute32(AF_SYSTEM_COMMAND, MODULE_COMMAND_REBOOT) != afSUCCESS) {
+                afero->loop() ;
+                wait_us(100) ;
+            }
+            reboot_edge() ;
+            break ;
+        default:
+            break ;
+        }
+        break ;
+    default:
+        assignAttribute(requestId, attributeId, valueLen, value, false) ;
+        break ;
+    }        
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_attributes.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,124 @@
+#ifndef _AF_ATTRIBUTES_H_
+#define _AF_ATTRIBUTES_H_
+
+#include "mbed.h"
+#include "afLib.h"
+
+/**
+ * af_attributes.h
+ *
+ */
+
+#define ATTRIBUTE_TYPE_SINT8                                       2
+#define ATTRIBUTE_TYPE_SINT16                                      3
+#define ATTRIBUTE_TYPE_SINT32                                      4
+#define ATTRIBUTE_TYPE_SINT64                                      5
+#define ATTRIBUTE_TYPE_BOOLEAN                                     1
+#define ATTRIBUTE_TYPE_UTF8S                                      20
+#define ATTRIBUTE_TYPE_BYTES                                      21
+#define ATTRIBUTE_TYPE_FIXED_15_16                                 6
+
+#define afSUCCESS                    0    // Operation completed successfully
+#define afERROR_NO_SUCH_ATTRIBUTE   -1    // Request was made for unknown attribute id
+#define afERROR_BUSY                -2    // Request already in progress, try again
+#define afERROR_INVALID_COMMAND     -3    // Command could not be parsed
+#define afERROR_QUEUE_OVERFLOW      -4    // Queue is full
+#define afERROR_QUEUE_UNDERFLOW     -5    // Queue is empty
+#define afERROR_INVALID_PARAM       -6    // Bad input parameter
+
+#define AF_SYSTEM_COMMAND            65012
+#define AF_SYSTEM_ASR_STATE          65013
+#define AF_SYSTEM_LINKED_TIMESTAMP   65015
+
+#define MODULE_STATE_REBOOTED                 0
+#define MODULE_STATE_LINKED                   1
+#define MODULE_STATE_UPDATING                 2
+#define MOUDLE_STATE_UPDATE_READY             3
+
+#define MODULE_COMMAND_NONE                   0
+#define MODULE_COMMAND_REBOOT                 1
+
+#define ATTR_SOFTWARE_RESET          666
+#define ATTR_MCU_RESET_REASON        999
+
+#define ATTR_LED                 1024
+#define ATTR_IO0                 1025
+#define ATTR_IO1                 1026
+#define ATTR_IO2                 1028
+#define ATTR_BUTTON              1030
+#define ATTR_IO3                 1031
+
+#define ATTR_BOOT_LOADER_VER     2001
+#define ATTR_BLE_STACK_VER       2002
+#define ATTR_FW_APP_VER          2003
+#define ATTR_DEVICE_DESC         2004
+#define ATTR_WIFI_VER            2006
+
+#define ATTR_OFFLINE_SCHED      59001
+#define ATTR_SECURITY_ENABLED   60000
+#define ATTR_UTC_OFFSET         65001
+#define ATTR_CONFIGURES_SSID    65004
+#define ATTR_WIFI_BARS          65005
+#define ATTR_WIFI_STDY_STATE    65006
+
+#define ATTR_COMMAND            65012
+#define ATTR_ASR_STATE          65013
+#define ATTR_LOW_BATTERY        65014
+#define ATTR_LINKED_TIMESTAMP   65015
+#define ATTR_ATTR_ACK           65018
+#define ATTR_REBOOT_REASON      65019
+#define ATTR_BLE_COMMS          65020
+#define ATTR_MCU_INTERFACE      65021
+
+#define DISPLAY_MODE_OFF        0
+#define DISPLAY_MODE_GAS        1
+#define DISPLAY_MODE_SUMMARY    2
+#define DISPLAY_MODE_CHART      3
+
+typedef struct {
+    uint16_t id ;
+    char *description ;
+    int attribute_type ;
+    int size ;
+} af_attribute_type ;
+
+/**
+ * get_af_attr
+ * @param id attribute id value to look up
+ * @returns index of the attribute in the af_attribute_type af_attr[]
+ */
+int get_af_attr(uint16_t id) ;
+
+/**
+ * print_af_error
+ * @param resultCode return value from afLib function(s)
+ */
+void print_af_error(int resultCode) ;
+
+/**
+ * Callback that allows ASR to request an MCU attribute be changed. 
+ * You should define this function in your MCU firmware to perform application-specific actions 
+ * your code must take (e.g., updating the state of the hardware), 
+ * in light of the attribute value change.
+*/
+bool attributeChangeRequest(
+    const uint8_t   requestId, 
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) ;
+
+/*
+ * Application callback that allows afLib to notify that an attribute has changed. 
+ * This method will be called in response to a getAttribute call from the application 
+ * and whenever a ASR module attribute changes.
+ */
+void attributeUpdatedReport(
+    const uint8_t   requestId,
+    const uint16_t  attributeId,
+    const uint16_t  valueLen,
+    const uint8_t   *value
+) ;
+
+extern afLib *afero ; 
+#endif /* _AF_ATTRIBUTES_H */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_mgr.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,62 @@
+#include "mbed.h"
+#include "string.h"
+#include "edge_mgr.h"
+#include "edge_time.h"
+#include "edge_pin.h"
+#include "afLib.h"
+#include "af_attributes.h"
+#include "afTransport.h"
+#include "msg_types.h"
+#include "mbedSPI.h"
+#include "mbedUART.h"
+#include "af_mgr.h"
+
+#define ASR_USE_SPI 0
+#define ASR_USE_UART 1
+
+afLib           *afero = 0 ;
+InterruptIn     *afero_int = 0 ;
+afTransport     *afero_spi = 0 ;
+afTransport     *afero_uart = 0 ;
+DigitalOut      *afero_reset ;
+bool            gLinked = false ;
+bool            gConnected = false ;
+
+void afero_isr(void)
+{
+    afero->mcuISR() ;
+}
+
+void init_aflib(void)
+{
+    afero_reset = new DigitalOut(PIN_ASR_RESET, 1) ; /* create as deasserted */
+    Serial *theLog = new Serial(USBTX, USBRX, 115200) ;
+
+#if (ASR_USE_SPI)
+tty->printf("afero is using SPI\n") ;
+    afero_spi = (afTransport*) new mbedSPI(PIN_MOSI, PIN_MISO, PIN_SCK, PIN_CS) ;
+    afero = new afLib(
+        PIN_INTR,
+        afero_isr,
+        attributeChangeRequest,
+        attributeUpdatedReport,
+        theLog, /* Stream for log */
+        (afTransport *)afero_spi ) ;
+#elif (ASR_USE_UART)
+tty->printf("afero is using UART2\n") ;
+    afero_uart = (afTransport*) new mbedUART(PIN_UART2_RX, PIN_UART2_TX, theLog) ;
+    afero = new afLib(
+        PIN_INTR,
+        0,
+        attributeChangeRequest,
+        attributeUpdatedReport,
+        theLog, /* Stream for log */
+        (afTransport *)afero_uart ) ;
+#endif
+
+    wait(0.1) ;
+    *afero_reset = 0 ;
+    wait(0.5) ; /* required 250ms ~ time for reset */
+    *afero_reset = 1 ;       
+    wait(0.5) ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/af_mgr.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,12 @@
+#ifndef _AF_MGR_H_
+#define _AF_MGR_H_
+#include "afLib.h"
+
+extern afLib           *afero ;
+extern bool             gLinked ;
+extern bool             gConnected ;
+extern bool             verbos ;
+
+void init_aflib(void) ;
+
+#endif /* _AF_MGR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/edgeSerial.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,68 @@
+#include "mbed.h"
+#include "vt100.h"
+#include "edgeSerial.h"
+#include "edge_reset_mgr.h"
+extern vt100 *tty ;
+
+edgeSerial::edgeSerial(PinName txPin, PinName rxPin, int baud) 
+: Serial(txPin, rxPin, baud) 
+{
+    _is_peeked = false ;
+    _peeked_byte = 0 ;
+}
+    
+char edgeSerial::edge_peek(void)
+{
+    _peeked_byte = getc() ;
+    _is_peeked = true ;
+    return(  _peeked_byte ) ;
+}
+
+void edgeSerial::edge_read(uint8_t *buffer, int len)
+{
+    int i ;
+    if (_is_peeked) {
+        buffer[0] = _peeked_byte ;
+        _is_peeked = false ;
+#if 1
+        for (i = 1 ; i < len ; i++) {
+            buffer[i] = Serial::getc() ;
+        }
+#else
+        Serial::read(&buffer[1], len) ;
+#endif
+    } else {
+#if 1
+        for (i = 0 ; i < len ; i++) {
+            buffer[i] = Serial::getc() ;
+        }
+#else
+        Serial::read(buffer, len) ;
+#endif
+    }     
+}
+
+char edgeSerial::edge_read(void)
+{
+    char c ;
+// tty->printf("edge_read\n") ;
+    if (_is_peeked) {
+        c = _peeked_byte ;
+        _is_peeked = false ;
+    } else {
+//    Serial::read((uint8_t*)&c, 1) ;
+        c = Serial::getc() ;
+    }
+    return( c ) ;
+}
+
+void edgeSerial::edge_write(uint8_t *buffer, int len)
+{
+#if 1
+    for (int i = 0 ; i < len ; i++ ) {
+        Serial::write(&buffer[i], 1) ;
+    }    
+#else
+    Serial::write(buffer, len) ;
+#endif
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/edgeSerial.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,20 @@
+#ifndef _EDGESERIAL_H_
+#define _EDGESERIAL_H_
+
+#include "mbed.h"
+
+class edgeSerial : public Serial {
+public:
+    edgeSerial(PinName txPin, PinName rxPin, int baud) ;
+
+    bool edge_available(void) { return Serial::readable() ; }
+    char edge_peek(void) ;
+    char edge_read(void) ;
+    void edge_read(uint8_t *buffer, int len) ;
+    void edge_write(uint8_t *buffer, int len) ;
+private:
+    bool _is_peeked ;
+    uint8_t _peeked_byte ;
+} ;
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/mbedSPI.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,215 @@
+#include "mbed.h"
+#include "afSPI.h"
+#include "mbedSPI.h"
+#include "afErrors.h"
+#include "msg_types.h"
+#include "vt100.h"
+extern vt100 *tty ;
+
+#if defined (TARGET_KL25Z) || defined (TARGET_TEENSY3_1)
+ #ifndef SPI0_C1
+  #define SPI0_C1 (*(uint8_t *)0x40076000)
+ #endif
+#endif
+
+mbedSPI::mbedSPI(PinName mosi, PinName miso, PinName sckl, PinName cs) :
+    _spi(mosi, miso, sckl), _cs(cs, 1)
+{
+    _spi.format(8, 0) ;
+    _spi.frequency(1000000) ; /* 1MHz */
+
+#if defined (TARGET_KL25Z) || defined (TARGET_TEENSY3_1)
+    #ifndef SPI0_C1
+        #define SPI0_C1 (*(uint8_t *)0x40076000)
+    #endif
+//    SPI0_C1 |= 0x01 ; /* LSB First */
+//    SPI0_C1 &= 0xFE ; /* MSB First */
+#endif
+
+}
+
+void mbedSPI::begin(void)
+{
+}
+
+void mbedSPI::beginSPI(void)
+{
+    _cs = 0 ;
+    SPI0_C1 |= 0x01 ; /* LSB First */
+    wait_us(8) ;
+}
+
+void mbedSPI::endSPI(void)
+{
+    _cs = 1 ;
+    SPI0_C1 &= 0xFE ; /* MSB First */
+    wait_us(1) ;
+    // SPI.endTransaction() // in the original code
+}
+
+/**
+ * on 17-Jan-2018 disable/enable irq added
+ * before and after of each _spi.writes
+ */
+void mbedSPI::transfer(char *bytes, int len)
+{
+    int i ;
+    for (i = 0 ; i < len ; i++ ) {
+        __disable_irq() ; // Disable Interrupts
+        bytes[i] = _spi.write(bytes[i]) ;
+        __enable_irq() ; // Enable Interrupts
+    }
+}
+
+void mbedSPI::checkForInterrupt(volatile int *interrupts_pending, bool idle)
+{
+    // Nothing required here.
+}
+
+int  mbedSPI::exchangeStatus(StatusCommand *tx, StatusCommand *rx)
+{
+    int         result = afSUCCESS ;
+    uint16_t    len = tx->getSize() ;
+    int         *bytes ;
+    char        *rbytes ;
+    int         index = 0 ;
+    bytes = new int[len] ;
+    rbytes = new char[len + 1] ;
+    tx->getBytes(bytes) ;
+    
+    beginSPI() ;
+    for (int i = 0 ; i < len ; i++ ) {
+        rbytes[i] = bytes[i] ;
+    }
+    rbytes[len] = tx->getChecksum() ;
+    transfer(rbytes, len + 1) ;
+    
+    uint8_t cmd = bytes[index++] ;
+    if (cmd != SYNC_REQUEST && cmd != SYNC_ACK) {
+        tty->printf("exchangeStatus bad cmd: %02X\n", cmd) ;
+        result = afERROR_INVALID_COMMAND ;
+    }
+    
+    rx->setBytesToSend(rbytes[index + 0] | (rbytes[index + 1] << 8)) ;
+    rx->setBytesToRecv(rbytes[index + 2] | (rbytes[index + 3] << 8)) ;
+    rx->setChecksum(rbytes[index | 4]);
+    
+    endSPI() ;
+
+    delete [] bytes ;
+    delete [] rbytes ;    
+    return result ;
+}
+
+int  mbedSPI::writeStatus(StatusCommand *c)
+{
+    int         result = afSUCCESS ;
+    uint16_t    len = c->getSize() ;
+    int         *bytes ;
+    char         *rbytes ;
+    int         index = 0 ;
+    bytes = new int[len] ;
+    rbytes = new char[len+1] ;
+    c->getBytes(bytes) ;
+    
+    beginSPI() ;
+    
+    for (int i = 0 ; i < len ; i++ ) {
+        rbytes[i] = bytes[i] ;
+    }
+    rbytes[len] = c->getChecksum() ;
+    transfer(rbytes, len + 1) ;
+    
+    uint8_t cmd = rbytes[index++] ;
+    if (cmd != SYNC_REQUEST && cmd != SYNC_ACK) {
+        tty->printf("writeStatus bad cmd: %02X\n", cmd) ;
+        result = afERROR_INVALID_COMMAND ;
+    }
+    
+    endSPI() ;
+    
+    delete [] rbytes ;
+    delete [] bytes ;
+    
+    return result ;
+}
+
+void mbedSPI::sendBytes(char *bytes, int len)
+{
+    beginSPI() ;
+    
+    transfer(bytes, len) ;
+
+    endSPI() ;
+}
+
+void mbedSPI::recvBytes(char *bytes, int len)
+{
+    beginSPI() ;
+    
+    transfer(bytes, len) ;
+
+    endSPI() ;
+}
+
+void mbedSPI::sendBytesOffset(char *bytes, uint16_t *bytesToSend, uint16_t *offset)
+{
+    uint16_t len = 0;
+
+    len = *bytesToSend > SPI_FRAME_LEN ? SPI_FRAME_LEN : *bytesToSend;
+
+    char *buffer ;
+    buffer = new char[len] ;
+    memset(buffer, 0xff, sizeof(buffer));
+
+    memcpy(buffer, &bytes[*offset], len);
+
+    sendBytes(buffer, len);
+
+    *offset += len;
+    *bytesToSend -= len;
+    
+    delete [] buffer ;
+}
+
+#if 1
+void mbedSPI::recvBytesOffset(char **bytes, uint16_t *bytesLen, uint16_t *bytesToRecv, uint16_t *offset)
+{
+    uint16_t len = 0;
+
+    len = *bytesToRecv > SPI_FRAME_LEN ? SPI_FRAME_LEN : *bytesToRecv;
+
+    if (*offset == 0) {
+        *bytesLen = *bytesToRecv;
+        *bytes = new char[*bytesLen];
+    }
+
+    char *start = *bytes + *offset;
+
+    recvBytes(start, len);
+
+    *offset += len;
+    *bytesToRecv -= len;
+}
+#endif
+
+#if 0
+void mbedSPI::recvBytesOffset(char *bytes, uint16_t *bytesLen, uint16_t *bytesToRecv, uint16_t *offset)
+{
+    uint16_t len = 0;
+
+    len = *bytesToRecv > SPI_FRAME_LEN ? SPI_FRAME_LEN : *bytesToRecv;
+
+    if (*offset == 0) {
+        *bytesLen = *bytesToRecv;
+//        *bytes = new char[*bytesLen];
+    }
+
+    char *start = bytes + *offset;
+
+    recvBytes(start, len);
+
+    *offset += len;
+    *bytesToRecv -= len;
+}
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/mbedSPI.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,38 @@
+/**
+ * mbedSPI
+ *
+ * mbed spi class for afero afLib.
+ */
+#ifndef _MBEDSPI_H_
+#define _MBEDSPI_H_
+#include "mbed.h"
+#include "afSPI.h"
+#include "StatusCommand.h"
+#include "afTransport.h"
+
+#define SPI_FRAME_LEN   ((uint16_t)16)
+
+class mbedSPI : public afTransport {
+public:
+    mbedSPI(PinName mosi, PinName miso, PinName sckl, PinName cs) ;
+
+    virtual void checkForInterrupt(volatile int *interrupts_pending, bool idle);
+    virtual int exchangeStatus(StatusCommand *tx, StatusCommand *rx);
+    virtual int writeStatus(StatusCommand *c);
+    virtual void sendBytes(char *bytes, int len);
+    virtual void recvBytes(char *bytes, int len);
+    virtual void sendBytesOffset(char *bytes, uint16_t *bytesToSend, uint16_t *offset);
+    virtual void recvBytesOffset(char **bytes, uint16_t *bytesLen, uint16_t *bytesToRecv, uint16_t *offset);
+//    virtual void recvBytesOffset(char *bytes, uint16_t *bytesLen, uint16_t *bytesToRecv, uint16_t *offset);
+private:
+    virtual void begin(void) ;
+    virtual void beginSPI(void) ;
+    virtual void endSPI(void) ;
+    virtual void transfer(char *bytes,int len) ;
+
+    SPI         _spi ;
+    DigitalOut  _cs ;
+} ;
+    
+
+#endif /* _MBEDSPI_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/mbedUART.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,215 @@
+#include "mbed.h"
+#include "afErrors.h"
+#include "msg_types.h"
+#include "mbedUART.h"
+#include "edge_mgr.h"
+#include "edge_reset_mgr.h"
+
+#define mbedUART_BUFSIZE 300
+
+mbedUART::mbedUART(PinName rxPin, PinName txPin, Serial *theLog) 
+{
+    _uart = new edgeSerial(txPin, rxPin, 9600) ;
+    _buf = new uint8_t[300] ;
+}
+
+mbedUART::~mbedUART(void)
+{
+    if (_buf) {
+        delete [] _buf ;
+    }
+}
+
+int mbedUART::available(void)
+{
+    return (int)_uart->readable() ;
+}
+
+char mbedUART::peek(void)
+{
+    char c ;
+    c = _uart->edge_peek() ;
+//    c = _uart->getc() ;
+    return c ;
+    
+//    return _uart->peek() ;   
+}
+
+void mbedUART::read(uint8_t *buffer, int len)
+{
+    _uart->edge_read(buffer, len) ;
+}
+
+char mbedUART::read(void)
+{
+    char c ;
+    c = _uart->edge_read() ;
+    return( c ) ;
+}
+
+void mbedUART::write(uint8_t *buffer, int len)
+{
+    _uart->edge_write(buffer, len) ;
+}
+        
+void mbedUART::checkForInterrupt(volatile int *interrupts_pending, bool idle)
+{
+    char c ;
+    if (_uart->readable()) {
+        c = _uart->edge_peek() ;
+//tty->printf("Char %02X received\n", c) ;
+        if (c == INT_CHAR) {
+            if (*interrupts_pending == 0) {
+                c = _uart->edge_read() ;
+                *interrupts_pending += 1 ; /* (*interrupts_pending)++ ; */
+            } else if (idle) {
+                c = _uart->edge_read() ;
+            } else {
+               // _theLog->printf("INT(Pending)\n") ;
+            }
+        } else {
+            if (*interrupts_pending == 0) {
+                c = _uart->edge_read() ;
+            }
+        }
+    }
+}
+
+int mbedUART::exchangeStatus(StatusCommand *tx, StatusCommand *rx)
+{
+    int             result = afSUCCESS ;
+    int             i ;
+    uint16_t        len ;
+    int             *bytes ;
+    char            *rbytes ;
+    int             index = 0 ;
+    len = tx->getSize() ;
+    bytes = new int[len] ;
+    rbytes = new char[len + 1] ;
+    tx->getBytes(bytes) ;
+    
+    for(i = 0 ; i < len ; i++ ) {
+        rbytes[i] = bytes[i] ;
+    }
+    rbytes[len] = tx->getChecksum() ;
+    sendBytes(rbytes, len + 1) ;
+    
+    // Skip any interrupts, that may have come in.
+    do {
+        recvBytes(rbytes, 1) ;
+    } while(rbytes[0] == INT_CHAR) ;
+            
+    // Okay, we have good first char, now read the rest
+    recvBytes(&rbytes[1], len) ;
+        
+    uint8_t cmd = bytes[index++] ;
+    if (cmd != SYNC_REQUEST && cmd != SYNC_ACK) {
+        tty->printf("exchangeStatus bad cmd: %02X\n", cmd) ;
+        result = afERROR_INVALID_COMMAND ;
+    }
+    
+    rx->setBytesToSend(rbytes[index + 0] | (rbytes[index + 1] << 8)) ;
+    rx->setBytesToRecv(rbytes[index + 2] | (rbytes[index + 3] << 8)) ;
+    rx->setChecksum(rbytes[index + 4]) ;
+        
+    delete [] rbytes ;
+    delete [] bytes ;
+    return result ;
+}
+
+
+int mbedUART::writeStatus(StatusCommand *c)
+{
+    int result = afSUCCESS ;
+    uint16_t len ;
+    int *bytes ;
+    char *rbytes ;
+    int index = 0 ;
+    len = c->getSize() ;
+    bytes = new int[len] ;
+    rbytes = new char[len + 1] ;
+    
+    c->getBytes(bytes) ;
+    for (int i = 0 ; i < len ; i++ ) {
+        rbytes[i] = bytes[i] ;
+    }
+    rbytes[len] = c->getChecksum() ;
+    
+    sendBytes(rbytes, len + 1) ;
+    
+    uint8_t cmd = rbytes[index++] ;
+    if (cmd != SYNC_REQUEST && cmd != SYNC_ACK) {
+        tty->printf("writeStatus bad cmd: %02X\n", cmd) ;
+        result = afERROR_INVALID_COMMAND ;
+    }
+    // c->dump() ;
+    // c->dumpBytes() ;
+    
+    delete [] rbytes ;
+    delete [] bytes ;
+    
+    return result ;
+}
+
+void mbedUART::sendBytes(char *bytes, int len)
+{
+#if 0
+tty->printf("sendBytes %d: ", len) ;
+for (int i = 0 ; i < len ; i++ ) { tty->printf("%02X ", bytes[i]) ; }
+tty->printf("\n") ;
+#endif
+
+    _uart->edge_write((uint8_t *)bytes, len) ;
+}
+
+void mbedUART::recvBytes(char *bytes, int len)
+{
+    _uart->edge_read((uint8_t *)bytes, len) ;
+    
+#if 0
+tty->printf("recvBytes %d: ", len) ;
+for (int i = 0 ; i < len ; i++ ) { tty->printf("%02X ", bytes[i]) ; }
+tty->printf("\n") ;
+#endif
+}
+
+void mbedUART::sendBytesOffset(char *bytes, uint16_t *bytesToSend, uint16_t *offset)
+{
+    uint16_t len = 0 ;
+    
+    len = *bytesToSend ;
+    
+//    sendBytes(bytes, len) ;
+    sendBytes(&bytes[*offset], len) ;
+    
+    // dumpBytes("Sending: ", len, bytes) ;
+    
+    *offset += len ;
+    *bytesToSend -= len ;
+}
+
+void mbedUART::recvBytesOffset(char **bytes, uint16_t *bytesLen, uint16_t *bytesToRecv, uint16_t *offset)
+{
+    uint16_t len = 0 ;
+    
+    len = *bytesToRecv ;
+    
+    if (*offset == 0) {
+        *bytesLen = *bytesToRecv ;
+        *bytes = new char[*bytesLen] ;
+    }
+    
+    char * start = *bytes + *offset ;
+    
+    recvBytes(start, len) ;
+    
+//  dumpBytes("Receiving:", len, _readBuffer) ;
+#if 0
+    tty->printf("Receiving: ") ;
+    for (int i = 0; i < len ; i++ ) { tty->printf("%02X ", start[i]) ; } 
+    tty->printf("\n") ;
+#endif
+
+    *offset += len ;
+    *bytesToRecv -= len ;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/af_utils/mbedUART.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,35 @@
+#ifndef _MBEDUART_H_
+#define _MBEDUART_H_
+#include "mbed.h"
+#include "afTransport.h"
+#include "edgeSerial.h"
+
+#define INT_CHAR    0x32
+
+class mbedUART : public afTransport {
+public:
+    mbedUART(PinName rxPin, PinName txPin, Serial *theLog) ;
+    ~mbedUART(void) ;
+    
+    virtual void checkForInterrupt(volatile int *interrupts_pending, bool idle);
+    virtual int exchangeStatus(StatusCommand *tx, StatusCommand *rx);
+    virtual int writeStatus(StatusCommand *c);
+    virtual void sendBytes(char *bytes, int len);
+    virtual void recvBytes(char *bytes, int len);
+    virtual void sendBytesOffset(char *bytes, uint16_t *bytesToSend, uint16_t *offset);
+    virtual void recvBytesOffset(char **bytes, uint16_t *bytesLen, uint16_t *bytesToRecv, uint16_t *offset);
+//    virtual void recvBytesOffset(char *bytes, uint16_t *bytesLen, uint16_t *bytesToRecv, uint16_t *offset);
+private:
+    edgeSerial *_uart ;
+//    Serial *_uart ;
+//    Stream *_uart ;
+    Serial *_theLog ;
+    uint8_t *_buf ;
+
+    int available(void);
+    char peek(void);
+    void read(uint8_t *buffer, int len);
+    char read(void);
+    void write(uint8_t *buffer, int len);
+};    
+#endif /* _MBEDUART_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_mgr.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,41 @@
+#include "mbed.h"
+#include "edge_mgr.h"
+#include "edge_reset_mgr.h"
+#include "af_attributes.h"
+
+#include "edge_time.h"
+#include "edge_pin.h"
+
+bool            verbos = true ;
+
+static int error_tolerance   = 100 ;
+static int loop_interval     = 100 ; // 1000 ; 
+int        edge_mgr_status   = EDGE_MGR_INIT ;
+char       *reset_reason_str = 0 ;
+
+int init_edge_attribute(void)
+{
+    static int attr_index = 0 ;
+    static int error_count = 0 ;
+    int return_value = 0 ;
+    int result ;
+     
+   
+    if (error_count > error_tolerance) { // too many fails, trying reset
+        reboot_edge() ;
+    }
+ 
+    return(return_value) ;
+}
+
+void edge_loop(uint32_t count_robin)
+{       
+    if ((count_robin % loop_interval) == 0) {
+        loop_interval = 1 ;
+    }
+}
+
+void   reboot_edge(void) 
+{
+    software_reset() ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_mgr.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,18 @@
+#ifndef _EDGE_MGR_H_
+#define _EDGE_MGR_H_
+#include "mbed.h"
+#include "vt100.h"
+
+int    init_edge_attribute(void) ;
+void   edge_loop(uint32_t tick_count) ;
+void   reboot_edge(void) ;
+
+extern char             *reset_reason_str ;
+extern bool             verbos ;
+extern int              edge_mgr_status ;
+extern vt100            *tty ;
+
+#define EDGE_MGR_INIT    0
+#define EDGE_MGR_RUNNING 1
+
+#endif /* _EDGE_MGR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_pin.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,39 @@
+#ifndef _EDGE_PIN_H_
+#define _EDGE_PIN_H_
+
+#if defined (TARGET_KL25Z)
+#define PIN_INTR      PTD4
+#define PIN_ASR_RESET PTA13
+#define PIN_SCK       PTD1
+#define PIN_MOSI      PTD2
+#define PIN_MISO      PTD3
+#define PIN_CS        PTD0
+/* ILI9341 */
+#define PIN_CS_TFT    PTC7
+#define PIN_RESET_TFT PTC4
+#define PIN_DC_TFT    PTC0
+#define PIN_BL_TFT    PTC3
+
+#define PIN_FRDM_LEDR PTB18
+#define PIN_FRDM_LEDG PTB19
+#define PIN_FRDM_LEDB PTD1  /* conflict with SCK orz */
+/* on board I2C0 */
+// #define PIN_I2C0_SCL  PTE24
+// #define PIN_I2C0_SDA  PTE25
+/* external I2C0 */
+#define PIN_I2C0_SCL  PTC8 
+#define PIN_I2C0_SDA  PTC9 
+#define PIN_I2C1_SCL  PTE1
+#define PIN_I2C1_SDA  PTE0
+#define PIN_AN0       PTB0
+#define PIN_AN1       PTB1
+#define PIN_AN2       PTB2
+#define PIN_LED_R     PTB18
+#define PIN_LED_G     PTB19
+#define PIN_LED_B     PTD1
+
+#define PIN_UART2_TX    PTE22
+#define PIN_UART2_RX    PTE23
+#endif /* TARGET_KL25Z */
+
+#endif /* _EDGE_PIN_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_reset_mgr.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,146 @@
+#include "mbed.h"
+#include "edge_mgr.h"
+#include "edge_reset_mgr.h"
+
+/**
+  * System Reset Status Register 0 (RCM_SRS0) 0x4007_F000
+  *
+  * bit[7] : POR         Power-On Reset
+  * bit[6] : PIN         External Reset Pin
+  * bit[5] : WDOG        Watchdog
+  * bit[4] : (Reserved)
+  * bit[3] : LOL         Loss-of-Lock Reset
+  * bit[2] : LOC         Loss-of-Clock Reset
+  * bit[1] : LVD         Low-Voltage Detect Reset
+  * bit[0] : WAKEUP      Low Leakage Wakeup Reset
+  */
+#define REG_RCM_SRS0    (uint8_t *)0x4007F000
+#define POR_RESET_BIT   0x80
+#define PIN_RESET_BIT   0x40
+#define WDG_RESET_BIT   0x20
+#define LOL_RESET_BIT   0x08
+#define LOC_RESET_BIT   0x04
+#define LVD_RESET_BIT   0x02
+#define WUP_RESET_BIT   0x01
+
+  /**
+   * System Reset Status Register 1 (RCM_SRS1) 0x4007_F001
+   *
+   * bit[7:6] (Reserved)
+   * bit[5] : SACKERR     Stop Mode Acknowledge Error Reset
+   * bit[4] : (Reserved)
+   * bit[3] : MDM_AP      MDM-AP System Reset Request
+   * bit[2] : SW          Software Reset
+   * bit[1] : LOCKUP      Core Lockup
+   * bit[0] : (Reserved)
+   */
+#define REG_RCM_SRS1     (uint8_t *)0x4007F001
+#define SACK_RESET_BIT   0x20
+#define MDM_RESET_BIT    0x08
+#define SW_RESET_BIT     0x04
+#define LOCKUP_RESET_BIT 0x02
+
+#define IDX_POR_RESET    0
+#define IDX_PIN_RESET    1
+#define IDX_WDG_RESET    2
+#define IDX_LOL_RESET    3
+#define IDX_LOC_RESET    4
+#define IDX_LVD_RESET    5
+#define IDX_WUP_RESET    6
+#define IDX_SACK_RESET   7
+#define IDX_MDM_RESET    8
+#define IDX_SW_RESET     9
+#define IDX_LOCKUP_RESET 10 
+
+const char *reset_reason[] = {
+    "Power On Reset",
+    "Reset Pin Asserted",
+    "Watch Dog Reset",
+    "Loss of Lock Reset",
+    "Loss of Clock Reset",
+    "Low Voltage Detect Reset",
+    "Low Leakage Wakeup Reset",
+    "Stop Mode Acknowledge Error Reset",
+    "MDM-AP System Reset Request",
+    "Software Reset",
+    "Core Lockup Reset",
+    0
+} ;
+
+void print_reset_reason(void) 
+{
+    extern char *reset_reason_str ;
+    int idx = 0 ;
+    uint8_t *data = REG_RCM_SRS0 ;
+    if (*data & POR_RESET_BIT) {
+        idx = IDX_POR_RESET ;
+    }
+    if (*data & PIN_RESET_BIT) {
+        idx = IDX_PIN_RESET ; 
+    }
+    if (*data & WDG_RESET_BIT) {
+        idx = IDX_WDG_RESET ; 
+    }
+    if (*data & LOL_RESET_BIT) {
+        idx = IDX_LOL_RESET ;
+    }
+    if (*data & LVD_RESET_BIT) {
+        idx = IDX_LVD_RESET ;
+    }  
+    if (*data & LOC_RESET_BIT) {
+        idx = IDX_LOC_RESET ;
+    }
+    if (*data & WUP_RESET_BIT) {
+        idx = IDX_WUP_RESET ;
+    }
+    data = REG_RCM_SRS1 ;
+    if (*data & SACK_RESET_BIT) {
+        idx = IDX_SACK_RESET ;
+    }
+    if (*data & MDM_RESET_BIT) {
+        idx = IDX_MDM_RESET ;
+    }
+    if (*data & SW_RESET_BIT) {
+        idx = IDX_SW_RESET ;
+    }
+    if (*data & LOCKUP_RESET_BIT) {
+        idx = IDX_LOCKUP_RESET ;
+    }
+    tty->printf("%s\n", reset_reason[idx]) ;
+    reset_reason_str = (char *)reset_reason[idx] ;
+}
+
+/**
+ * Software Reset
+ * 
+ * From Cortex-M0 Devices Generic User Guide
+ * 4.3.4 Application Interrupt and Reset Control Register
+ *
+ * Bit[31:16] : VECTCKEY
+ * Bit[15]    : ENDIANESS
+ * Bit[14:3]  : (Reserved)
+ * Bit[2]     : SYSRESETREQ
+ * Bit[1]     : VECTCLRACTIVE (reserved for debug use)
+ * Bit[0]     : (Reserved)
+ *
+ * Note: To trigger software reset, both VECTKEY=0x05FA and SYSRESETREQ
+ * must be written at once, therefore the value will be
+ * 0x05FA0004
+ */
+ 
+void software_reset(void)
+{
+     SCB->AIRCR = 0x05FA0004 ; 
+}
+
+/**
+ * reset_watch_dog
+ * reset the watch dog counter
+ * this function must be called within the limit (1sec)
+ */
+ 
+void reset_watch_dog(void) 
+{
+    SIM->SRVCOP = (uint32_t)0x55u;
+    SIM->SRVCOP = (uint32_t)0xAAu;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_reset_mgr.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,8 @@
+#ifndef _EDGE_RESET_MGR_H_
+#define _EDGE_RESET_MGR_H_
+
+void print_reset_reason(void) ;
+void software_reset(void) ;
+void reset_watch_dog(void) ;
+
+#endif /* _EDGE_RESET_MGR_H_ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_time.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,231 @@
+#include "mbed.h"
+#include "edge_mgr.h"
+#include "edge_time.h"
+
+static const uint8_t daysInMonth[12] = {
+    31, 28, 31, 30,
+    31, 30, 31, 31,
+    30, 31, 30, 31
+} ;
+
+const char *nameOfDay[7] = {
+    "Sunday", "Monday", "Tuesday", "Wednesday", 
+    "Thursday", "Friday", "Saturday"
+} ;
+
+uint32_t edge_time = 0 ;
+uint32_t utc_offset = 9 * 60 * 60 ;
+tm current_time ;
+Ticker *tokei = 0 ;
+
+void inc_sec(void)
+{
+    __disable_irq() ; // Disable Interrupts
+    edge_time++ ;
+    __enable_irq() ; // Enable Interrupts
+}
+
+void init_timer(void)
+{
+    tokei = new Ticker() ;
+    tokei->attach(inc_sec, 1.0) ;
+}
+
+void set_time(const uint16_t  valueLen, const uint8_t *value) 
+{
+    uint32_t tmp_timestamp = 0 ;
+    for (int i = 0 ; i < valueLen ; i++ ) {
+        tmp_timestamp |= (value[i] & 0xFF) << (i * 8) ;
+    }
+    edge_time = tmp_timestamp ;
+    ts2tm(edge_time, &current_time) ;
+//    ts2time(edge_time, &current_time) ;
+}
+
+void ts2time(uint32_t timestamp, struct tm *tm)
+{
+    uint32_t seconds, minutes, hours, days, month, year ;
+    uint32_t dayOfWeek ;
+    
+//    timestamp += (3600 * 9) ; /* +9 hours for JST */
+    timestamp += utc_offset ;
+    
+    seconds = timestamp % 60 ;
+    minutes = timestamp / 60 ;
+    hours   = minutes / 60  ; /* +9 for JST */
+    minutes -= hours * 60 ;
+    days    = hours / 24 ;
+    hours   -= days * 24 ;
+    
+    tm->tm_sec = seconds ;
+    tm->tm_min = minutes ;
+    tm->tm_hour = hours ; 
+    tm->tm_mday = days + 1 ;
+//    tm->tm_mon  = month ;
+//    tm->tm_year = year ;
+//    tm->tm_wday = dayOfWeek ;
+}
+
+void ts2tm(uint32_t timestamp, struct tm *tm)
+{
+    uint32_t seconds, minutes, hours, days, month, year ;
+    uint32_t dayOfWeek ;
+    
+//    timestamp += (3600 * 9) ; /* +9 hours for JST */
+    timestamp += utc_offset ;
+    
+    seconds = timestamp % 60 ;
+    minutes = timestamp / 60 ;
+    hours   = minutes / 60  ; /* +9 for JST */
+    minutes -= hours * 60 ;
+    days    = hours / 24 ;
+    hours   -= days * 24 ;
+    
+    /* Unix timestamp start 1-Jan-1970 Thursday */
+    year = 1970 ;
+    dayOfWeek = 4 ; /* Thursday */
+    
+    while(1) {
+        bool isLeapYear = 
+            (((year % 4) == 0)
+            &&(((year % 100) != 0)
+            || ((year % 400) == 0))) ;
+        uint16_t daysInYear = isLeapYear ? 366 : 365 ;
+        if (days >= daysInYear) {
+            dayOfWeek += isLeapYear ? 2 : 1 ;
+            days      -= daysInYear ;
+            if (dayOfWeek >= 7) {
+                dayOfWeek -= 7 ;
+            }
+            year++ ;
+        } else {
+            tm->tm_yday = days ;
+            dayOfWeek += days ;
+            dayOfWeek %= 7 ;
+            
+            /* calc the month and the day */
+            for (month = 0 ; month < 12 ; month++) {
+                uint8_t dim = daysInMonth[month] ;
+                
+                /* add a day to feburary if this is a leap year */
+                if ((month == 1) && (isLeapYear)) {
+                    dim++ ;
+                }
+                
+                if (days >= dim) {
+                    days -= dim ;
+                } else {
+                    break ;
+                }
+            }
+            break ;
+        }
+    }
+    tm->tm_sec = seconds ;
+    tm->tm_min = minutes ;
+    tm->tm_hour = hours ; 
+    tm->tm_mday = days + 1 ;
+    tm->tm_mon  = month ;
+    tm->tm_year = year ;
+    tm->tm_wday = dayOfWeek ;
+}
+
+void print_time(struct tm *tm)
+{
+    tty->printf("%02d:%02d:%02d",
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec ) ;
+}
+
+void print_time(uint32_t thetime) 
+{
+    struct tm timestruct ;
+    ts2time(thetime, &timestruct) ;
+    print_time(&timestruct) ;
+}
+
+void print_time(void)
+{
+    struct tm timestruct ;
+    ts2time(edge_time, &timestruct) ;
+    print_time(&timestruct) ;
+}
+
+void print_date(struct tm *tm) 
+{
+    tty->printf("%d/%d/%d %02d:%02d:%02d",
+        tm->tm_year,
+        tm->tm_mon + 1,
+        tm->tm_mday,
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec
+        ) ;
+}
+
+void print_date_wd(struct tm *tm) 
+{
+    tty->printf("%d/%d/%d %02d:%02d:%02d (%s)",
+        tm->tm_year,
+        tm->tm_mon + 1,
+        tm->tm_mday,
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec,
+        nameOfDay[tm->tm_wday]
+        ) ;
+}
+
+void time2str(struct tm *tm, char *timestr) 
+{
+    sprintf(timestr, "%02d:%02d:%02d",
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec ) ;
+}
+
+void time2str(char *timestr)
+{
+    struct tm timestruct ;
+    ts2time(edge_time, &timestruct) ;
+    time2str(&timestruct, timestr) ;
+}
+
+int32_t time2seq(uint32_t timestamp)
+{
+    struct tm timestruct ;
+    int32_t result  ;
+    ts2time(timestamp, &timestruct) ;
+    result = timestruct.tm_hour * 10000 
+        + timestruct.tm_min * 100
+        + timestruct.tm_sec ;
+    return(result) ;
+}
+
+void time2seq(uint32_t timestamp, char *timestr) 
+{
+    struct tm timestruct ;
+    ts2tm(timestamp, &timestruct) ;
+    sprintf(timestr, "%d%02d%02d%02d%02d%02d",
+        timestruct.tm_year,
+        timestruct.tm_mon + 1,
+        timestruct.tm_mday,
+        timestruct.tm_hour,
+        timestruct.tm_min,
+        timestruct.tm_sec
+    ) ;
+}
+
+void time2date(struct tm *tm, char *datestr)
+{
+    sprintf(datestr, "%d/%d/%d %02d:%02d:%02d (%s)",
+        tm->tm_year,
+        tm->tm_mon + 1,
+        tm->tm_mday,
+        tm->tm_hour,
+        tm->tm_min,
+        tm->tm_sec,
+        nameOfDay[tm->tm_wday]
+    ) ;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/edge_utils/edge_time.h	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,25 @@
+#ifndef _EDGE_TIME_H_
+#define _EDGE_TIME_H_
+#include "mbed.h"
+
+void init_timer(void) ;
+void set_time(const uint16_t  valueLen, const uint8_t *value) ;
+void ts2time(uint32_t timestamp, struct tm *tm) ; /* light version */
+void ts2tm(uint32_t timestamp, struct tm *date) ; /* full version */
+void print_time(void) ; /* light version */
+void print_time(uint32_t thetime) ;
+void print_time(struct tm *tm) ; /* light version */
+void print_date(struct tm *date) ; /* full version */
+void print_date_wd(struct tm *date) ; /* vull version with day of week */
+void time2str(char *timestr) ; /* light version */
+int32_t time2seq(uint32_t timestamp) ; /* hhmmss */
+void time2seq(uint32_t timestamp, char *timestr) ;
+void time2str(struct tm *tm, char *timestr) ; /* hh:mm:ss */
+void time2date(struct tm *tm, char *datestr) ; /* YYYY/MM/DD hh:mm:ss */
+void time2date(struct tm *tm, char *datestr) ; /* full version with day of week */
+
+extern const char *nameOfDay[] ;
+extern tm current_time ;
+extern uint32_t edge_time ;
+extern uint32_t utc_offset ;
+#endif /* _EDGE_TIME_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,120 @@
+#include "mbed.h"
+#include "vt100.h"
+
+#include "af_mgr.h"
+#include "af_attributes.h"
+#include "edge_mgr.h"
+#include "edge_pin.h"
+#include "edge_time.h"
+#include "edge_reset_mgr.h"
+
+vt100 *tty = 0 ;
+uint32_t wait_tolerance = 500 ; /* 5sec */
+uint32_t connect_tolerance = 60 ; /* after 60 trials, reboot */
+uint32_t wait_count = 0 ;
+uint32_t connect_trial_count = 0 ;
+
+DigitalOut *led_r = 0 ;
+DigitalOut *led_g = 0 ;
+DigitalOut *led_b = 0 ;
+// DigitalOut myled(LED1);
+
+void doLEDs(int num)
+{
+    if (num & 0x01) { *led_b = 0 ; } else { *led_b = 1 ; }
+    if (num & 0x02) { *led_g = 0 ; } else { *led_g = 1 ; }
+    if (num & 0x04) { *led_r = 0 ; } else { *led_r = 1 ; }
+}
+
+/**
+ * wait_connection
+ * When gConnected == false, which is connection is lost.
+ * Each 5sec check attribute ATTR_WIFI_STDY_STATE to see
+ * if the connection has recovered.
+ * Meantime even if connection is established communicated
+ * data is invalid, so AF_SYSTEM_ASR_STATE is also
+ * checked for gLinked ;
+ * And in case connect_tolerance trials failed
+ * try to reboot the system if it can improve the situation.
+ */
+void wait_connection(void)
+{
+    int result ;
+    wait_count++ ;
+    if (wait_count > wait_tolerance) {
+        if (gConnected == false) {
+            result = afero->getAttribute(ATTR_WIFI_STDY_STATE) ;
+            if (result != afSUCCESS) {
+                print_af_error(result) ;
+            }
+        }
+        if (gLinked == false) {
+            result = afero->getAttribute(AF_SYSTEM_ASR_STATE) ;
+            if (result != afSUCCESS) {
+                print_af_error(result) ;
+            }
+        }
+        connect_trial_count++ ;
+        if (connect_trial_count > connect_tolerance) {
+            reboot_edge() ;
+        }
+        wait_count = 0 ;
+    }
+}
+
+void init_hardware(void)
+{
+    tty = new vt100(PTA2, PTA1, 115200) ;
+//    tty->cls() ;
+    led_r = new DigitalOut(PIN_LED_R, 1) ;
+    led_g = new DigitalOut(PIN_LED_G, 1) ;
+    led_b = new DigitalOut(PIN_LED_B, 1) ;
+}
+
+#if 1
+int main() 
+{
+    int led_state = 0 ;
+    init_hardware() ;
+    tty->printf("afLib1.3 UART test program (%s)\n", __DATE__) ;
+    tty->printf("Reset Reason: ") ;
+    print_reset_reason() ;
+    init_aflib() ;
+    tty->printf("afLib 1.3 initialized\n") ;
+    doLEDs(0x04) ;
+    init_timer() ;
+    tty->printf("timer init done\n") ;
+    while(1) {
+        afero->loop() ;
+        if (afero->isIdle()) {
+            led_state = 0x04 ; /* red */
+            if (gLinked && gConnected) {
+                led_state = 0x02 ; /* green */
+            } else if (gConnected) {
+                led_state = 0x01 ; /* blue */
+            } else {
+                wait_connection() ;
+            }
+            doLEDs(led_state) ;
+            wait_ms(100);
+        }
+    }
+}
+#else
+int main() 
+{
+    init_hardware() ;
+    tty->printf("afLib1.3 test program (%s)\n", __DATE__) ;
+    init_aflib() ;
+    tty->printf("afLib 1.3 initialized\n") ;
+    init_timer() ;
+    tty->printf("timer init done\n") ;
+    while(1) {
+        afero->loop() ;
+        if (afero->isIdle()) {
+            *led_r = ! (*led_r) ;
+            wait_ms(100);
+        }
+    }
+}
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/mbed_official/code/mbed/builds/7130f322cb7e
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vt100.lib	Mon Apr 23 06:15:26 2018 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Rhyme/code/vt100/#141a8a98c504