Temp Publish

Files at this revision

API Documentation at this revision

Comitter:
Jonathan738
Date:
Tue Jan 08 16:21:39 2019 +0000
Commit message:
FIXING EVERYTHING

Changed in this revision

Display.cpp Show annotated file Show diff for this revision Revisions of this file
Display.hpp Show annotated file Show diff for this revision Revisions of this file
General.hpp Show annotated file Show diff for this revision Revisions of this file
LCD.cpp Show annotated file Show diff for this revision Revisions of this file
LCD.hpp Show annotated file Show diff for this revision Revisions of this file
NetWorking.cpp Show annotated file Show diff for this revision Revisions of this file
NetWorking.hpp Show annotated file Show diff for this revision Revisions of this file
SDReader.cpp Show annotated file Show diff for this revision Revisions of this file
SDReader.hpp Show annotated file Show diff for this revision Revisions of this file
Sample.cpp Show annotated file Show diff for this revision Revisions of this file
Sample.hpp Show annotated file Show diff for this revision Revisions of this file
Terminal.cpp Show annotated file Show diff for this revision Revisions of this file
Terminal.hpp Show annotated file Show diff for this revision Revisions of this file
WatchDog.cpp Show annotated file Show diff for this revision Revisions of this file
WatchDog.hpp Show annotated file Show diff for this revision Revisions of this file
cyclicalBUFFER.cpp Show annotated file Show diff for this revision Revisions of this file
cyclicalBUFFER.hpp Show annotated file Show diff for this revision Revisions of this file
dateTime.cpp Show annotated file Show diff for this revision Revisions of this file
dateTime.hpp 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
diff -r 000000000000 -r 4ccd12e1d789 Display.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Display.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,351 @@
+/*------------------------------------------------------------------------------
+Creator : Ben Gordon
+Date : 30/12/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : The purpose of this thread is to manage control of button inputs and
+page selection (or changing the dateTime). It also updates the main lcd screen
+with data at regular 5 second intervals.
+------------------------------------------------------------------------------*/
+#include "Display.hpp"
+//---Button Management---//
+//Interrupts
+InterruptIn button1(b1);
+InterruptIn button2(b2);
+
+//Dual button press management
+Timeout doublePress;
+
+//Button input store (Used to detect dual button press)
+U_BYTE buttonPressed;
+///////////////////////////
+
+//extern Terminal PC;
+
+//---Used for "setting DateTime" page---//
+//Controll inputs for: {day,month,year,hour,minute,second}.
+//Each having +1 and +10 (year also has +100 and +1000)
+signed INT_32 increment[] = {10,1,10,1,1000,100,10,1,10,1,10,1,10,1};
+//Manage cursor position
+signed INT_32 cursorPosition[] = {3,4,6,7,9,10,11,12,4,5,7,8,10,11};
+
+//---Initialise Display---//
+Display display(RS,E,d4,d5,d6,d7); //rs,e,d4,d5,d6,d7
+
+//---Set cursor position---//
+U_BYTE cursorPos=0;
+
+//---Creeate event and mail queues---//
+EventQueue DisplayQueue;
+extern Mail<mail_t, 32>Display_mail;
+
+////------------------------------Main Thread-------------------------------////
+void DisplayThread()
+{
+    //Initialise displays
+    display.INIT();
+    //Initialise twice to combat unknown initialisation error
+    display.pageOne();
+    display.pageOne();
+    
+    //Initialise variables
+    buttonPressed = 0;
+    
+    //Initialise interrupts
+    button1.rise(buttonISR1);
+    button2.rise(buttonISR2);
+    
+    //Preset date time to default of 27/02/2020 01:12:45 
+    
+    //setDate(27,02,2020);    //27th February 2020
+    //setTime(01,12,45);      //1:12:45 am
+    
+    while(1)
+    {
+        DisplayQueue.dispatch_forever();
+    }
+}
+////////////////////////////////////////////////////////////////////////////////
+
+////---------------------------Button Management----------------------------////
+void buttonISR1()
+{
+    buttonPressed |= 1;
+    
+    if(buttonPressed != 3)
+    {
+        doublePress.attach(&buttonTO, 0.2);
+    }
+}
+
+void buttonISR2()
+{
+    buttonPressed |= 2;
+    
+    if(buttonPressed != 3)
+    {
+        doublePress.attach(&buttonTO, 0.2);
+    }
+}
+
+void buttonTO()
+{
+    if(buttonPressed != 0)
+    {
+        DisplayQueue.call(&pageSelect,buttonPressed);
+        buttonPressed = 0;
+    }
+}
+////////////////////////////////////////////////////////////////////////////////
+
+void pageSelect(U_BYTE buttonValue)
+{
+    switch (display.currentPage())
+    {
+        case 1:
+            buttonActionOne(buttonValue);
+            break;
+        case 2:
+            buttonActionTwo(buttonValue);
+            break;
+        case 3:
+            buttonActionFour(buttonValue);
+            break;
+    }
+}
+
+void buttonActionOne(U_BYTE buttonValue)
+{
+    switch(buttonValue)
+    {
+        case 0x01:
+            display.pageTwoA();
+            display.setDate(startEditDate());
+            cursorPos=0;
+            display.cursorPos(LINE1+cursorPosition[cursorPos]);
+            break;
+        
+        case 0x02:
+            display.pageTwoB();
+            display.setTime(startEditTime());
+            cursorPos=8;
+            display.cursorPos(LINE1+cursorPosition[cursorPos]);
+            break;
+            
+        case 0x03:
+            display.pageFour();
+            break;
+    }
+}
+void buttonActionTwo(U_BYTE buttonValue)
+{
+    switch (buttonValue)
+    {
+        case 0x01:
+            setValue(cursorPos,increment[cursorPos]);
+            break;
+        case 0x02:
+            setValue(cursorPos,0-increment[cursorPos]);
+            break;
+        case 0x03:
+            cursorPos++;
+            if((cursorPos == 8) || (cursorPos == 12)) //8 finished date set, 12 finishes time set
+            {
+                endEdit();
+                display.pageOne();
+            }
+            break;
+    }
+    display.cursorPos(LINE1+cursorPosition[cursorPos]);
+}
+
+void buttonActionFour(U_BYTE buttonValue)
+{
+    switch(buttonValue)
+    {
+        case 0x01:
+            display.pageOne();
+            break;
+        
+        case 0x02:
+            //No Function
+            break;
+            
+        case 0x03:
+            //No Function
+            break;
+    }
+}
+void setValue(BYTE cycle,signed INT_32 value)
+{
+    switch(cycle)
+    {
+        case 0:
+        case 1:
+            addDay(value);
+            display.setDate(getSetDate());
+            break;
+        
+        case 2:
+        case 3:
+            addMonth(value);
+            display.setDate(getSetDate());
+            break;
+            
+        case 4:
+        case 5:
+        case 6:
+        case 7:
+            addYear(value);
+            display.setDate(getSetDate());
+            break;
+            
+        case 8:
+        case 9:
+            addHour(value);
+            display.setTime(getSetTime());
+            break;
+        
+        case 10:
+        case 11:
+            addMin(value);
+            display.setTime(getSetTime());
+            break;
+        
+        case 12:
+        case 13:   
+            addSec(value);
+            display.setTime(getSetTime());
+            break;
+    }
+}
+
+/*============================================================================*/
+
+////-----------------------------Display Class------------------------------////
+extern Mail<mail_t, 32>Display_mail;
+
+void Display::INIT()
+{
+    _lcd.INIT();
+}
+
+void Display::pageOne()
+{
+    _lcd.clear();
+   // _lcd.disableCursor();
+    
+    //Temperature Page
+    _lcd.display("T:",LINE1);
+    _lcd.display(Data->MTEMP);
+    _lcd.putt(223);
+    _lcd.display("C");
+    
+    //LightLevel Page
+    _lcd.display("L:",LINE1+9);
+    _lcd.display(Data->MLIGHT);
+
+    //Pressure Page
+    _lcd.display("P:",LINE2+2);
+    _lcd.display(Data->MPRESS);
+    _lcd.display(" mbar");
+    
+    pageNumber = 1;
+}
+
+void Display::updatePageOne()
+{
+    _lcd.display(Data->MTEMP,LINE1+2);
+    _lcd.putt(223);
+    _lcd.display("C");
+    
+    //LightLevel Page
+    _lcd.display(Data->MLIGHT,LINE1+11);
+
+    //Pressure Page
+    _lcd.display(Data->MPRESS,LINE2+4);
+    _lcd.display(" mbar");
+}
+
+void Display::pageTwoA()
+{
+    _lcd.clear();
+  //  _lcd.enableCursor();
+    
+    _lcd.display("00/00/0000",LINE1+3);
+    _lcd.display("dd/mm/yyyy",LINE2+3);
+    
+    _lcd.pos(LINE1+3);
+    
+    pageNumber = 2;
+    _lcd.enableCursor();
+}
+
+void Display::pageTwoB()
+{
+        _lcd.clear();
+  //  _lcd.enableCursor();
+    
+    _lcd.display("00:00:00",LINE1+4);
+    _lcd.display("hh:mm:ss",LINE2+4);
+    
+    _lcd.pos(LINE1+4);
+    
+    pageNumber = 2;
+    _lcd.enableCursor();
+}
+
+void Display::pageFour()
+{
+    _lcd.clear();
+  //  _lcd.enableCursor();
+    
+    _lcd.display("Life? don't talk",LINE1);
+    _lcd.display("to me about life",LINE2);
+    
+    _lcd.pos(LINE1);
+    
+    pageNumber = 3;
+}
+
+void Display::addData()
+{
+    //Receive mail on mail queue
+    osEvent evt = Display_mail.get();
+    
+    //Check that there is mail in queue
+    if (evt.status == osEventMail) {
+        Data = (mail_t*)evt.value.p;
+        
+        if(pageNumber == 1)
+        {
+            updatePageOne();
+        }
+        Display_mail.free(Data);
+    }
+}
+
+U_BYTE Display::currentPage()
+{
+    return pageNumber;
+}
+
+void Display::setDate(char* date)
+{
+    _lcd.pos(LINE1+3);
+    _lcd.display(date,LINE1+3);
+}
+
+void Display::setTime(char* time)
+{
+    _lcd.pos(LINE1+4);
+    _lcd.display(time,LINE1+4);   
+}
+
+void Display::cursorPos(UINT_16 location)
+{
+    _lcd.pos(location);
+}
+////////////////////////////////////////////////////////////////////////////////
+
diff -r 000000000000 -r 4ccd12e1d789 Display.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Display.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,71 @@
+/*------------------------------------------------------------------------------
+Creator : 
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : 
+------------------------------------------------------------------------------*/
+#ifndef _DISPLAY_HPP
+#define _DISPLAY_HPP
+    #include "mbed.h"
+    #include "General.hpp"
+    
+    #include "dateTime.hpp"
+    #include "LCD.hpp"
+    
+    //#include "Terminal.hpp"
+    
+    #define b1 PE_12
+    #define b2 PE_14
+    
+    #define RS  PD_15   //D9
+    #define E   PF_12   //D8
+    #define d4  PF_13   //D7
+    #define d5  PE_9    //D6
+    #define d6  PF_14   //D4
+    #define d7  PF_15   //D2
+    
+    
+    #define PRESSED 1
+    
+void setValue(BYTE cycle,signed INT_32 value);
+void waitForInput();
+void DisplayThread();
+void pageSelect(U_BYTE buttonValue);
+void buttonActionOne(U_BYTE buttonValue);
+void buttonActionTwo(U_BYTE buttonValue);
+void buttonActionFour(U_BYTE buttonValue);
+
+void buttonISR1();
+void buttonISR2();
+
+void buttonTO();
+    
+    class Display{
+        public:
+            Display(PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7) : _lcd(rs,e,d4,d5,d6,d7) {} 
+            void INIT();
+            
+            void pageOne();
+            void updatePageOne();
+            
+            void pageTwoA();
+            void pageTwoB();
+            
+            void pageFour();
+            
+            void cursorPos(UINT_16 location);
+            void addData();
+            
+            U_BYTE currentPage();
+            
+            void setDate(char* date);
+            void setTime(char* time);
+        private:
+            mail_t *Data;
+            LCD _lcd;
+            U_BYTE pageNumber;
+    };
+#endif
+
diff -r 000000000000 -r 4ccd12e1d789 General.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/General.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,54 @@
+/*------------------------------------------------------------------------------
+Creator : Jonathan Wheadon ; Ben Gordon ; Joel Pallent
+Date : 06/12/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "mbed.h"
+Purpose : This file is for declarations and structures that are needed for 
+multiple files (makes everything neater)
+------------------------------------------------------------------------------*/
+#include "mbed.h"
+
+// set to 15.0f for coursework
+//#define SampleRate 5.0f
+
+// Define Needed values for SD reader
+#define Signal_UnMount 1
+
+// define all datatypes to make data sizes more understandable
+#define     S_BYTE      signed char
+#define     BYTE        char
+#define     U_BYTE      unsigned char
+#define     INT_16      short int
+#define     UINT_16     unsigned short int
+#define     INT_32      int
+#define     UINT_32     unsigned int
+#define     INT_64      long int
+#define     UINT_64     unsigned long int
+#define     FLOAT_32    float
+#define     FLOAT_64    double
+#define     FLOAT_96    long double
+
+// define ERROR levels
+#define criticalFAILURE 0 // critical FAILURE shows full system broken
+#define criticalERROR   1 // critical ERROR means atleast one system failed
+#define fault           2 // FAULT means atleast one system is not working properly
+#define warning         3 // warning means atleast one system may be functioning incorecctly
+
+#ifndef Define_ONCE
+#define Define_ONCE
+
+// structure used for holding sample data in the form of strings
+    typedef struct{
+        BYTE MTEMP [8];
+        BYTE MPRESS [8];
+        BYTE MLIGHT [8];
+        BYTE MDate [20];
+    }mail_t;
+    
+#endif
+
+// Threads
+extern Thread SDcard_THREAD, Terminal_THREAD, NetWorking_THREAD;
+
+
diff -r 000000000000 -r 4ccd12e1d789 LCD.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LCD.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,107 @@
+/*------------------------------------------------------------------------------
+Creator : Ben Gordon
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : 
+------------------------------------------------------------------------------*/
+#include "LCD.hpp"
+#include "General.hpp"
+
+//LCD data sheet: https://www.rapidonline.com/pdf/57-2224.pdf
+
+void LCD::INIT()
+{
+    //All lines default low
+    _LCD_RS = 0;
+    _LCD_E  = 0;
+    
+    //LCD Initialise
+    wait_ms(45); //Wait for LCD startup
+    /*Step 1*/
+        wait_us(40);      //Wait whilst LCD busy
+        _LCD_RS = control;   
+        LCD_DDRAM = 0;  //Clear data line
+        LCD_DDRAM = (FUNC|bit8)>>4;  //Put data on line
+        LCD_strobe();
+    
+    /*Step 2*/ cmdLCD(FUNC|lines2);  //Function Set 0x20|0x08 = 0x28
+    /*Step 3*/ cmdLCD(FUNC|lines2);  //Function Set 0x20|0x08 = 0x28
+    /*Step 4*/ cmdLCD(DISPLAY|on);    //Display Control 0x08|0x0x04 = 0x0c
+    /*Step 5*/ cmdLCD(CLEAR);         //Clear Display 0x01
+    /*Step 6*/ cmdLCD(ENTRYMODE|I);   //Set entry mode 0x04|0x02 = 0x06
+
+    cmdLCD(RETURN); //return home location
+}
+
+void LCD::clear()
+{
+    cmdLCD(CLEAR);
+    disableCursor();  
+}
+
+void LCD::display(BYTE* str, UINT_16 location)
+{
+    if(location != NULL)
+    {
+        pos(location);
+    }
+    U_BYTE p = 0;
+    while((str[p]!= NULL)&&(p<16))
+    {
+        putt(str[p]);
+        p++; 
+    }
+}
+
+void LCD::pos(UINT_16 location)
+{
+    cmdLCD(0x80|location);   
+}
+
+void LCD::putt(U_BYTE c)
+{
+    wait_us(3000);
+    _LCD_RS = text;
+    set_LCD_data(c);
+}
+
+void LCD::cmdLCD(U_BYTE cmd)
+{
+    wait_us(3000);      //Wait whilst LCD busy
+    _LCD_RS = control;   
+    set_LCD_data(cmd);  //set data on bus
+}
+
+void LCD::LCD_strobe(void)
+{
+    wait_us(10);
+    _LCD_E = 1;
+    wait_us(10);
+    _LCD_E = 0;
+}
+
+void LCD::set_LCD_data(U_BYTE d)
+{
+    // Send upper 4 bits then lower for bits
+    // e.g. 11110000 => 1111 -> 0000
+    
+    LCD_DDRAM = 0;  //Clear data line
+    LCD_DDRAM = d>>4;  //Put data on line
+    LCD_strobe();
+    wait_us(1000);
+    LCD_DDRAM = 0;  //Clear
+    LCD_DDRAM = d; //Put remaining data on line
+    LCD_strobe();   
+}
+
+void LCD::enableCursor()
+{
+    cmdLCD(DISPLAY|on|cursor);
+}
+
+void LCD::disableCursor()
+{
+    cmdLCD(DISPLAY|on);
+}
diff -r 000000000000 -r 4ccd12e1d789 LCD.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LCD.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,63 @@
+/*------------------------------------------------------------------------------
+Creator : 
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : 
+------------------------------------------------------------------------------*/
+#ifndef _LCD_HPP
+#define _LCD_HPP
+    
+    #include "mbed.h"
+    #include "General.hpp"
+    
+    #define CLEAR   0x01
+    #define RETURN  0x02
+    
+    #define ENTRYMODE 0x04
+    #define I 0x02
+    #define shift 0x01    
+    
+    #define DISPLAY 0x08
+    #define on 0x04
+    #define cursor  0x02
+    #define blink   0x01    
+    
+    #define FUNC 0x20
+    #define bit8  0x10
+    #define lines2 0x08
+    #define dots11 0x04
+    
+    #define control 0
+    #define text 1
+    
+    #define write 0
+    #define read 1
+    
+    #define LINE1 0x00
+    #define LINE2 0x40
+    
+    class LCD{
+        public:
+            LCD(PinName rs, PinName e, PinName d4, PinName d5, PinName d6, PinName d7) : _LCD_RS(rs), _LCD_E(e), LCD_DDRAM(d4,d5,d6,d7) {} 
+            void INIT();
+            void clear();
+            void display(BYTE* str, UINT_16 location=NULL);
+            void putt(U_BYTE c);
+            void pos(UINT_16 location);
+            
+            void enableCursor();
+            void disableCursor();
+        private:
+            DigitalOut _LCD_RS;
+            DigitalOut _LCD_E;
+            BusOut LCD_DDRAM;   
+        private:
+            void cmdLCD(U_BYTE cmd);
+            void LCD_strobe(void);
+            void set_LCD_data(U_BYTE d);
+            UINT_32 findSpace(U_BYTE* str);
+    };
+#endif
+
diff -r 000000000000 -r 4ccd12e1d789 NetWorking.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetWorking.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,97 @@
+/*------------------------------------------------------------------------------
+Creator : Jonathan Wheadon
+Date : 29/11/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "General.hpp" ; "NetWorking.hpp"
+Purpose : To allow the low power enviromental sensor to publish data to a html
+webpage via the onboard ethernet conection of the stm429ZI
+------------------------------------------------------------------------------*/
+
+#include "NetWorking.hpp"
+#include "Terminal.hpp"
+
+Mutex NetWork_DATA_mutex;
+mail_t NetWork_DATA;
+
+Timeout NetworkCheck;
+void NetworkTimeOUT(void);
+    
+// Needed to print messages to terminal
+extern EventQueue TerminalQueue;
+extern Terminal PC;
+
+// Thread handels networking and updates a conected PC whenever the webpage is refreshed
+void NetWorkingThread(void)
+{    
+    // Configure an ethernet connection
+    EthernetInterface eth;
+    eth.set_network(IP, NETMASK, GATEWAY);
+    eth.connect();
+    
+    // Now setup a web server
+    TCPServer srv;           // TCP/IP Server
+    TCPSocket clt_sock;      // Socket for communication
+    SocketAddress clt_addr;  // Address of incoming connection
+    
+    while (true) {
+        // Open the server on ethernet stack
+        srv.open(&eth);
+        
+        // Bind the HTTP port (TCP 80) to the server
+        srv.bind(eth.get_ip_address(), 80);
+        
+        // Set maximum simultanious conections
+        srv.listen(5);
+        
+        // Block and wait on an incoming connection (if page is accessed)
+        srv.accept(&clt_sock, &clt_addr);
+        TerminalQueue.call(&PC, &Terminal::updateNetWorkstate, true);
+        NetworkCheck.detach();
+        NetworkCheck.attach(&NetworkTimeOUT, 7.0f);
+        
+        // Get most up to date enviromental values
+        float LIGHT = 0.0f;
+        float TEMP = 0.0f;
+        float PRES = 0.0f;
+        
+        // Convert to a C String
+        char Light_str[8];
+        char Temp_str[8];
+        char Pres_str[8];
+        sprintf(Light_str, "%5.3f", LIGHT );
+        sprintf(Temp_str, "%5.3f", TEMP );
+        sprintf(Pres_str, "%5.3f", PRES );
+        
+        string response;
+
+        NetWork_DATA_mutex.lock();
+
+        //Build the C++ string response
+        response = HTTP_OPEN;
+        response += NetWork_DATA.MDate;
+        response += NextColumb;        
+        response += NetWork_DATA.MLIGHT;
+        response += NextColumb;
+        response += NetWork_DATA.MPRESS;
+        response += NextColumb;
+        response += NetWork_DATA.MTEMP;
+        response += HTTP_CLOSE;
+        
+        NetWork_DATA_mutex.unlock();
+        
+        // Send static HTML response (as a C string)
+        int debug = clt_sock.send(response.c_str(), strlen(response.c_str()));
+        
+        wait(1);
+        
+        clt_sock.close();     
+    }
+}
+
+void NetworkTimeOUT(void)
+{
+    NetworkCheck.detach();
+    TerminalQueue.call(&PC, &Terminal::updateNetWorkstate, false);
+}
+
diff -r 000000000000 -r 4ccd12e1d789 NetWorking.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/NetWorking.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,70 @@
+/*------------------------------------------------------------------------------
+Creator : Jonathan Wheadon
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : 
+------------------------------------------------------------------------------*/
+//#if !FEATURE_LWIP
+//    #error [NOT_SUPPORTED] LWIP not supported for this target
+//#endif
+
+#include "mbed.h"
+#include "EthernetInterface.h"
+#include "TCPServer.h"
+#include "TCPSocket.h"
+#include <iostream>
+#include <string> 
+#include "General.hpp"
+
+#define HTTP_STATUS_LINE "HTTP/1.0 200 OK"
+#define HTTP_HEADER_FIELDS "Content-Type: text/html; charset=utf-8"
+#define HTTP_OPEN ""                                                                       \
+"<html>" "\n\r"                                                                            \
+"<head>" "\n\r"                                                                            \
+"  <meta charset=\"utf-8\">" "\n\r"                                                        \
+"  <title> ELEC 351 </title>" "\n\r"                                                       \
+"  <meta http-equiv=\"refresh\" content=\"5\">" "\n\r"                                     \
+"</head>" "\n\r"                                                                           \
+"<body style=\"display:flex;text-align:center\" bgcolor=\"black\" text=\"white\">" "\n\r"  \
+"  <div style=\"margin:auto\">" "\n\r"                                                     \
+"    <img src=\"https://scontent-lhr3-1.xx.fbcdn.net/v/t1.0-9/46878948_2350013835069200_1354076263555268608_o.jpg?_nc_cat=104&_nc_ht=scontent-lhr3-1.xx&oh=347a7ea2c45a8f6d874c912b120dc396&oe=5C658958\" alt=\"Plymouth UNI logo\" width=\"768\" height=\"191\">" "\n\r"\
+"    <h1> Low Power Enviromental Sensor : Network Conection </h1>" "\n\r"                  \
+"    <table align=\"center\" BORDER=\"1\" BORDERCOLOR=\"white\"> " "\n\r"                  \
+"      <tr>" "\n\r"                                                                        \
+"        <th> Date and Time </th>" "\n\r"                                                  \
+"        <th> Light (V) </th>" "\n\r"                                                      \
+"        <th> Pressure (mbar) </th>" "\n\r"                                                \
+"        <th> Temperature (C) </th>" "\n\r"                                                \
+"      </tr>" "\n\r"                                                                       \
+"      <tr>" "\n\r"                                                                        \
+"        <th> "
+
+#define NextColumb ""                                                                      \
+"        </th>" "\n\r"                                                                     \
+"        <th> "
+
+#define NextRow ""                                                                         \
+"      </tr>" "\n\r"                                                                       \ 
+"      <tr> " "\n\r"                                                                       \
+"        <th>"
+
+#define HTTP_CLOSE ""                                                                      \
+"        </th>" "\n\r"                                                                     \
+"      </tr>" "\n\r"                                                                       \
+"    </table>" "\n\r"                                                                      \
+"  </div>" "\n\r"                                                                          \
+"</body>" "\n\r"                                                                           \
+"</html>"                                                        
+
+#define HTTP_RESPONSE HTTP_STATUS_LINE "\r\n"   \
+                      HTTP_HEADER_FIELDS "\r\n" \
+                      "\r\n"                    \
+                      HTTP_MESSAGE_BODY "\r\n"
+
+#define IP        "10.0.0.10"
+#define NETMASK   "255.0.0.0"
+#define GATEWAY   "10.0.0.1"
+
+void NetWorkingThread(void);
diff -r 000000000000 -r 4ccd12e1d789 SDReader.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDReader.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,162 @@
+/*------------------------------------------------------------------------------
+Creator : Jonathan Wheadon
+Date : 28/11/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "SDReader.hpp" ; "Button.hpp" ; "General.hpp"
+Purpose : To allow for uploading and downloading blocks of DATA to a SD card
+connected via SPI
+------------------------------------------------------------------------------*/
+
+#include "SDReader.hpp"
+#include "Terminal.hpp"
+
+// Create switch to dismount the SD card
+InterruptIn onBoardSwitch(USER_BUTTON);
+Timeout onBoardSwitchTimeOut;             //Used to prevent switch bounce
+int onBoardSwitchState = EDGE_FALLEN;     //Initial state for switch 1
+
+// Create object SD of the SDReader class with set SPI pins
+SDReader SD(PB_5, D12, D13, D10); // mosi, miso, sclk, cs   
+
+// queue for SD reader events
+EventQueue SDQueue(32 * EVENTS_EVENT_SIZE);
+
+// Needed to print messgaes to terminal
+extern EventQueue TerminalQueue;
+extern Terminal PC;
+
+extern Mail<mail_t, 32>SDreader_mail;
+
+// Thread for saving DATA to the SD card
+void SDThread(void)
+{ 
+    //Initial attempt of init SD to check if SD is pluged in
+    if(SD.INIT() == false){
+        TerminalQueue.call(&PC, &Terminal::updateSDstate, false);
+    } else {
+        TerminalQueue.call(&PC, &Terminal::updateSDstate, true); 
+    } 
+    
+    while(1)
+    {
+        SDQueue.dispatch_forever();
+    }
+}
+
+bool SDReader::INIT(void)
+{    
+    // call the SDBlockDevice instance initialisation method.
+    if(sd.init() != 0){
+        SDmounted = false;
+    } else {
+        SDmounted = true;
+    }
+    
+    onBoardSwitch.rise(&SD, &SDReader::onBoardSwitchRisingEdge);
+    
+    if(SDmounted == false){
+        return false;
+    } else {           
+        //Remove existing file
+        remove( "/sd/ELEC351.csv" );
+        
+        FILE* fp = fopen("/sd/ELEC351.csv","a+");
+        //Check file handle (stream)
+        if (fp == NULL) {
+            return true;
+        }
+            
+        //Put some text in the file...
+        fprintf(fp, " TIME STAMP, light, temperature, pressure\n");
+        
+        //Close the file
+        fclose(fp);
+        
+        return true;
+    }
+}
+
+void SDReader::upload(BYTE DATETIME[20], BYTE LIGHT[8], BYTE TEMP[8], BYTE PRESS[8])
+{   
+    FILE* fp = fopen("/sd/ELEC351.csv","a+");
+    //Check file handle (stream)
+    if (fp == NULL) {
+        return;
+    }
+    
+    //Put some text in the file...
+    fprintf(fp, " %s, %s, %s, %s\n", DATETIME, LIGHT, TEMP, PRESS);
+    
+    //Close the file
+    fclose(fp);
+}
+
+void SDReader::addDATA(void)
+{
+    //open mailbox and print to line in terminal
+    osEvent evt = SDreader_mail.get();
+    if (evt.status == osEventMail) {
+        mail_t *mail = (mail_t*)evt.value.p;
+
+        upload(mail->MDate, mail->MLIGHT, mail->MTEMP, mail->MPRESS);
+
+        SDreader_mail.free(mail);
+    }
+}
+
+void SDReader::unmount(void)
+{
+    sd.deinit();
+    return;
+}
+
+void SDReader::update_SD_state(void){
+    switch(SDmounted)
+    {
+        case false :
+            if(SD.INIT() == false){
+                SDmounted = false;
+                TerminalQueue.call(&PC, &Terminal::updateSDstate, false);
+            } else {
+                SDmounted = true; 
+                TerminalQueue.call(&PC, &Terminal::updateSDstate, true); 
+            }  
+        break;
+        case true :
+            SDmounted = false;
+            SDQueue.call(&SD, &SDReader::unmount);
+            TerminalQueue.call(&PC, &Terminal::updateSDstate, false);
+        break;
+    }
+}
+
+//Interrupt service routine for handling the timeout
+void SDReader::onBoardSwitchTimeOutHandler() {
+    onBoardSwitchTimeOut.detach();            //Stop the timeout counter firing
+
+    //Which event does this follow?
+    switch (onBoardSwitchState) {
+        case EDGE_RISEN:    
+            onBoardSwitch.fall(&SD, &SDReader::onBoardSwitchFallingEdge);  //Now wait for a falling edge
+            SDQueue.call(&SD, &SDReader::update_SD_state); 
+        break;
+        case EDGE_FALLEN:
+            onBoardSwitch.rise(&SD, &SDReader::onBoardSwitchRisingEdge);   //Now wait for a rising edge
+        break;
+    } //end switch 
+}
+
+//Interrupt service routine for a rising edge (press)
+void SDReader::onBoardSwitchRisingEdge() {
+    onBoardSwitch.rise(NULL);             //Disable detecting more rising edges
+    onBoardSwitchState = EDGE_RISEN;      //Flag state
+    onBoardSwitchTimeOut.attach(&SD, &SDReader::onBoardSwitchTimeOutHandler, 0.2);    //Start timeout timer
+}
+
+//Interrupt service routive for SW1 falling edge (release)
+void SDReader::onBoardSwitchFallingEdge() {
+    onBoardSwitch.fall(NULL);                         //Disable this interrupt
+    onBoardSwitchState = EDGE_FALLEN;                 //Flag state
+    onBoardSwitchTimeOut.attach(&SD, &SDReader::onBoardSwitchTimeOutHandler, 0.2);    //Start timeout counter    
+}
diff -r 000000000000 -r 4ccd12e1d789 SDReader.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SDReader.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,52 @@
+/*------------------------------------------------------------------------------
+Creator : 
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : 
+------------------------------------------------------------------------------*/
+
+#ifndef Define_ONCE_SDReader
+#define Define_ONCE_SDReader
+
+#include "mbed.h"
+#include "SDBlockDevice.h"
+#include "FATFileSystem.h"
+#include "General.hpp"
+#include "rtos.h"
+
+#define EDGE_FALLEN 0
+#define EDGE_RISEN  1
+
+// Class SDReader expects mosi miso sclk and cs pins and is used for controlling a spi connected sd reader
+class SDReader {
+    public:
+        SDReader(PinName mosi, PinName miso, PinName sclk, PinName cs) : sd(mosi, miso, sclk, cs), fs("sd", &sd){}
+        bool INIT(void);
+        
+        void addDATA(void);
+        
+        bool getSDstate(void) {return SDmounted;}
+        
+    private:
+        SDBlockDevice sd;
+        FATFileSystem fs;
+        
+        void unmount(void);
+        
+        void upload(BYTE DATETIME[20], BYTE LIGHT[8], BYTE TEMP[8], BYTE PRESS[8]);
+
+        bool SDmounted;
+
+        // Functions for buttons
+        void update_SD_state(void);
+        void onBoardSwitchRisingEdge();
+        void onBoardSwitchFallingEdge();
+        void onBoardSwitchTimeOutHandler();
+};
+
+void SDThread(void); // Thread for terminal to run in 
+
+#endif
+
diff -r 000000000000 -r 4ccd12e1d789 Sample.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sample.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,162 @@
+/*------------------------------------------------------------------------------
+Creator : Joel Pallent
+Date : 06/12/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "Samples.hpp" 
+Purpose : The purpose of this file is to collect data from the peripherals,
+convert it into an appropriate form then put it into a mailbox so other parts
+access the data
+Return data: This file returns sample data in NetWork_Data and Terminal_mail
+
+------------------------------------------------------------------------------*/
+#include "SDReader.hpp"
+#include "Sample.hpp"
+
+Ticker t;                               // set ticker to control sample rate
+BME280 sensor(I2C_SDA, I2C_SCL);        // temp and pressure sensor setup
+AnalogIn LDR_ADC_In(A0);                // input for LDR
+FLOAT_32 fLDR = 0.0f;                   // initializeing the data to zero
+FLOAT_32 voltage = 0.0f;                // initializeing the data to zero
+
+// Set starting sample rate
+FLOAT_32 SampleRate = 15.0f;
+
+// Needed to print messgaes to terminal
+extern EventQueue TerminalQueue;
+extern Terminal PC;
+
+extern EventQueue SDQueue;
+extern SDReader SD; 
+
+extern EventQueue DisplayQueue;
+extern Display display;
+
+extern Mutex NetWork_DATA_mutex;
+extern mail_t NetWork_DATA;
+
+// Timeout to debug on the sample frequency and detect if sample jitter has occured
+Timeout SampleFrequencyDebugger;
+void SampleFrequencyDebuggerHandler(void);
+
+Mail<mail_t, 32>Terminal_mail;          // setting up mailbox for Terminal
+Mail<mail_t, 32>Display_mail;   
+Mail<mail_t, 32>SDreader_mail;  
+
+EventQueue SampleQueue(2 * EVENTS_EVENT_SIZE);
+
+// Create a cyclical buffer with 120 spaces as per coursework requirement 2
+cyclical_Buffer internalBuffer(120);
+
+// takes sample then peroidically takes sample every 15s using ticker
+void SampleThread(void)
+{
+    start_sampling(true);
+    
+     while(true)
+     {
+        SampleQueue.dispatch_forever();  
+     }  
+}
+
+// this function converts converts the data into strings then pushes them into respective mailbox or data path 
+void take_sample(void)
+{
+    //convert to strings
+    BYTE temperature [8];
+    BYTE pressure [8];
+    BYTE light [8]; 
+    BYTE SampleTimeTag [20];   
+    
+    fLDR = LDR_ADC_In;          // read adc data from LDR
+    voltage = fLDR* 3.3f;       // convert adc data to voltage
+            
+    FLOAT_32 Temp = sensor.getTemperature();
+    FLOAT_32 Press = sensor.getPressure();
+    strcpy(SampleTimeTag, getSystemDateTime());
+    
+    sprintf(temperature, "%2.2f", Temp);    // convert temperature float to string
+    sprintf(pressure, "%4.2f", Press);      // convert pressure float to string
+    sprintf(light, "%1.2f", voltage);       // convert LDR voltage to string   
+    
+    if(PC.getLoggingState() == true){
+        mail_t *TerminalMail = Terminal_mail.alloc();   // telling what mailbox to send data to
+        strcpy(TerminalMail->MTEMP, temperature);       // set temperature 
+        strcpy(TerminalMail->MPRESS, pressure);         // set pressure 
+        strcpy(TerminalMail->MLIGHT, light);            // set light as voltage
+        strcpy(TerminalMail->MDate, SampleTimeTag);     // Get and set system time from display thread
+        Terminal_mail.put(TerminalMail);                // send samples to terminal mailbox
+        TerminalQueue.call(&PC, &Terminal::addDATA);
+    }
+    
+    if(SD.getSDstate() == true){
+        mail_t *SDreaderMail = SDreader_mail.alloc();   // telling what mailbox to send data to
+        strcpy(SDreaderMail->MTEMP, temperature);       // set temperature 
+        strcpy(SDreaderMail->MPRESS, pressure);         // set pressure 
+        strcpy(SDreaderMail->MLIGHT, light);            // set light as voltage
+        strcpy(SDreaderMail->MDate, SampleTimeTag);     // Get and set system time from display thread
+        SDreader_mail.put(SDreaderMail);                // send samples to SD reader mailbox
+        SDQueue.call(&SD, &SDReader::addDATA);
+    }
+    
+    mail_t *DisplayMail = Display_mail.alloc();     // telling what mailbox to send data to
+    strcpy(DisplayMail->MTEMP, temperature);        // set temperature 
+    strcpy(DisplayMail->MPRESS, pressure);          // set pressure 
+    strcpy(DisplayMail->MLIGHT, light);             // set light as voltage
+    strcpy(DisplayMail->MDate, SampleTimeTag);      // Get and set system time from display thread
+    Display_mail.put(DisplayMail);                  // send samples to terminal mailbox
+    DisplayQueue.call(&display, &Display::addData);
+
+   
+   // set network data
+    NetWork_DATA_mutex.lock();
+    strcpy(NetWork_DATA.MTEMP, temperature);    // set temperature 
+    strcpy(NetWork_DATA.MPRESS, pressure);      // set pressure 
+    strcpy(NetWork_DATA.MLIGHT, light);         // set light
+    strcpy(NetWork_DATA.MDate, SampleTimeTag);  // Get and set system time from display thread
+    NetWork_DATA_mutex.unlock();
+    
+    // Create mail_t Data to store in internal memory
+    mail_t BufferData;     
+    strcpy(BufferData.MTEMP, temperature);     // set temperature 
+    strcpy(BufferData.MPRESS, pressure);       // set pressure 
+    strcpy(BufferData.MLIGHT, light);          // set light as voltage
+    strcpy(BufferData.MDate, SampleTimeTag);   // Get and set system time from display thread
+    
+    internalBuffer.addDataToBufferOverride(BufferData); // add data to cyclical buffer which overides oldest sample
+    
+    SampleFrequencyDebugger.detach();
+}
+
+// This function is called by the ticker and adds the take_sample function to the event queue
+void sample_handler(void)
+{
+    SampleQueue.call(take_sample);                        // once sample is ready to be collected call function to get data
+    SampleFrequencyDebugger.attach(&SampleFrequencyDebuggerHandler, (SampleRate-0.1*SampleRate));
+}
+
+void SampleFrequencyDebuggerHandler(void)
+{
+    Error msgs;
+    msgs.ErrorCode = fault;
+    msgs.ErrorMSGS = "Sample frequency has been compromised";
+    TerminalQueue.call(&PC, &Terminal::ERROR_MSGS, msgs);
+}
+
+void start_sampling(bool start)
+{
+    if(start == true){
+        t.attach(&sample_handler,SampleRate); // attach sample handler to ticker with rate SampleRate
+    } else {
+        t.detach();
+    }   
+}
+
+void update_sampleRATE(FLOAT_32 New_sampleRATE)
+{
+    SampleRate = New_sampleRATE;
+    
+    // update sample rate
+    t.detach();
+    t.attach(&sample_handler,SampleRate);
+}
diff -r 000000000000 -r 4ccd12e1d789 Sample.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Sample.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,22 @@
+/*------------------------------------------------------------------------------
+Creator : Joel Pallent
+Date : 07/12/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "General.hpp" , "BME280.h" , "Terminal.cpp" , "Display.hpp"
+                and "mbed.h"
+Purpose : the purpose for this file is to initilaise the functions in Samples.cpp
+and set the sample rate for the samples to be sent to the mailbox
+------------------------------------------------------------------------------*/
+#include "General.hpp"
+#include "BME280.h"
+#include "Terminal.hpp"
+#include "Display.hpp"
+#include "cyclicalBUFFER.hpp"
+#include "mbed.h"
+
+void sample_handler(void);  // adds take_sample to event queue everytime ticker is triggered
+void take_sample(void);     // sends data to mailbox and other data paths
+void update_sampleRATE(FLOAT_32 New_sampleRATE);
+void start_sampling(bool start);
+void SampleThread(void);    // periodically calls take_sample at a constant rate of SampleRate
diff -r 000000000000 -r 4ccd12e1d789 Terminal.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Terminal.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,689 @@
+/*------------------------------------------------------------------------------
+Creator : Jonathan Wheadon
+Date : 28/11/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "Terminal.hpp" and "General.hpp"
+Purpose : This cpp defines the functions for the terminal class which are used
+to control the terminal, it also defines the TerminalThread function which
+is ran in its own thread and controls the printing of DATA to the Terminal
+------------------------------------------------------------------------------*/
+
+#include "Terminal.hpp"
+#include "Sample.hpp"
+
+// queue for Terminal events
+EventQueue TerminalQueue(32 * EVENTS_EVENT_SIZE);
+
+// external eventqueues for sample and display threads
+extern EventQueue SampleQueue;
+extern EventQueue DisplayQueue;
+
+// Create Object PC of class Terminal with Set SERIAL_TX and SERIAL_RX pins
+Terminal PC(SERIAL_TX, SERIAL_RX);
+
+extern cyclical_Buffer internalBuffer;
+
+extern Mail<mail_t, 32>Terminal_mail; 
+
+
+/*------------------------------------------------------------------------------
+ Thread for handiling the terminal
+------------------------------------------------------------------------------*/
+void TerminalThread(void)
+{
+    PC.init();
+    
+    // Enter Forever loop
+    while(1)
+    {
+        TerminalQueue.dispatch_forever();
+    }   
+}
+
+/*------------------------------------------------------------------------------
+ Gets data from mailbox and displays on Terminal, if terminal is full it
+ overwrites the oldest displayed sample. 
+------------------------------------------------------------------------------*/
+void Terminal::addDATA(void)
+{
+    //open mailbox and print to line in terminal
+    osEvent evt = Terminal_mail.get();
+    if (evt.status == osEventMail) {
+        mail_t *mail = (mail_t*)evt.value.p;
+        if(col == 0)
+        {
+            Colour(ColourBLUE);
+        } else {
+            Colour(ColourPURPLE);
+        } 
+        // Print time
+        PrintDATA(mail->MDate, currentIDX);
+        currentIDX++;
+        // Print Temp
+        PrintDATA(mail->MTEMP, currentIDX);
+        currentIDX++;
+        // Print Pressure
+        PrintDATA(mail->MPRESS, currentIDX);
+        currentIDX++;
+        // Print Light
+        PrintDATA(mail->MLIGHT, currentIDX);
+        currentIDX++;
+        if(currentIDX >= MaxDATA)
+        {
+            currentIDX = 0;
+            if(col == 0)
+            {
+               col = 1;
+            } else {
+               col = 0;
+            }  
+        }
+        Terminal_mail.free(mail);
+    }
+}
+
+/*------------------------------------------------------------------------------
+ initialize terminal, print table, initialize variables and attach interupts
+------------------------------------------------------------------------------*/
+void Terminal::init(void)
+{
+    // Set baud rate for serial object pc
+    pc.baud (115200);  
+     
+    // Hide cursor, move to x 0 y 0 and change print colour to green
+    pc.printf("\x1b[?25l"); // Hides cursor
+    //pc.printf("\x1b[3j"); // Clear screen
+    Cursor(0,0);
+    Colour(ColourGREEN);
+ 
+    // Print DATA table to present data
+    pc.printf("|      ELEC351     :     Low Power Enviromental Sensor     |                                |\n\r"
+              "|*******************************************************************************************|\n\r"
+              "|         TIME         |        TEMP (C)      |    PRESSURE (mbar)   |       LIGHT (V)      |\n\r"
+              "|----------------------|----------------------|----------------------|----------------------|\n\r");
+    for(BYTE idx = 0; idx < Rows; idx++)
+    {
+        pc.printf("|                      |                      |                      |                      |\n\r");
+    }
+    pc.printf("|*******************************************************************************************|\n\r"
+              "| Input Command Line :                                                                      |\n\r"
+              "|-------------------------------------------------------------------------------------------|\n\r"
+              "|                                                                                           |\n\r"
+              "|*******************************************************************************************|\n\r"
+              "| SD state :                                  | NetWork Conected :                          |\n\r"
+              "|*******************************************************************************************|\n\r"
+              "                                                                                             \n\r"
+              "                                                                                             ");
+
+    
+    // InitNetwork indicator
+    Colour(ColourRED);
+    Cursor((68),(Rows+10));
+    pc.printf("NO");
+
+    // initialise variables    
+    buffer_pointer = 0;
+    col = 0;
+    currentIDX = 0;
+    
+    // Attach interupts
+    Terminal_ticker.attach(this, &Terminal::Ticker_Handler, 1.0f);
+    pc.attach(this, &Terminal::Input_Handler,pc.RxIrq);
+}
+
+/*------------------------------------------------------------------------------
+ Move cursor of pc terminal to co-ordinates 'X' and 'Y' (between 0 and 255)
+------------------------------------------------------------------------------*/
+void Terminal::Cursor(BYTE X, BYTE Y)
+{
+    pc.printf("\x1b[%d;%dH",Y,X);
+}
+
+/*------------------------------------------------------------------------------
+ Change pc terminal print colour (8 bit colour) to colour defined by "COLOUR"
+------------------------------------------------------------------------------*/
+void Terminal::Colour(BYTE COLOUR)
+{
+    pc.printf("\x1b[38;5;%dm",COLOUR);
+}
+
+/*------------------------------------------------------------------------------
+ Prints data(STRING) to cell in table defined by IDX
+------------------------------------------------------------------------------*/
+void Terminal::PrintDATA(BYTE* STRING, BYTE IDX)
+{
+    BYTE Y = (IDX/4)+5;
+    BYTE X = ((IDX%4)*23)+3;
+    Cursor(X,Y);
+    pc.printf("%s",STRING);  
+}
+
+/*------------------------------------------------------------------------------
+ function updates displayed SD state to boolean input
+------------------------------------------------------------------------------*/
+void Terminal::updateSDstate(bool SDstate)
+{    
+    Cursor((14),(Rows+10));
+    switch(SDstate) {
+        case true :
+            Colour(ColourGREEN);
+            pc.printf(" MOUNTED SD ");
+        break;
+        
+        case false :
+            Colour(ColourRED);
+            pc.printf("UNMOUNTED SD");
+        break;
+    }
+}
+
+/*------------------------------------------------------------------------------
+ function updates displayed NetWork state to boolean input
+------------------------------------------------------------------------------*/
+void Terminal::updateNetWorkstate(bool NetWorkstate)
+{    
+    Cursor((68),(Rows+10));
+    switch(NetWorkstate) {
+        case true :
+            Colour(ColourGREEN);
+            pc.printf(" YES ");
+        break;
+        
+        case false :
+            Colour(ColourRED);
+            pc.printf(" NO  ");
+        break;
+    }
+}
+
+/*------------------------------------------------------------------------------
+ Function checks terminal buffer to see which key has been entered and saves to 
+ internal buffer, if carridge return (0x0D) has been pressed it calls function
+ to decode the command to the event QUEUE 
+------------------------------------------------------------------------------*/
+void Terminal::checkKEY(void)
+{
+    BYTE gotkey; 
+    gotkey=pc.getc();
+    if(gotkey == NULL)
+    {
+        // do nothing
+    } else if (gotkey == 0x0D) {
+        Terminal_buffer[buffer_pointer] = 0x00;
+        TerminalQueue.call(&PC, &Terminal::HandleCOMMAND);
+        buffer_pointer = 0;
+        Cursor((24),(Rows+6));
+        pc.printf("                                ");
+    }  else if (gotkey == 0x7f) {
+        if (buffer_pointer > 0) {
+            buffer_pointer -= 1;
+            Cursor((24 + buffer_pointer),(Rows+6));
+            pc.printf(" ");
+        } else {
+            //do nothing
+        }
+    } else {
+        Colour(ColourWHITE);
+        if(buffer_pointer == 30)
+        {
+            // do error thing
+        } else {
+            pc.printf("\x1b[4m");
+            Cursor((24 + buffer_pointer),(Rows+6));
+            Colour(ColourWHITE);
+            pc.printf("%c",gotkey);
+            pc.printf("\x1b[24m");
+            Terminal_buffer[buffer_pointer] = gotkey;
+            buffer_pointer++;
+        }
+    }
+    pc.attach(this, &Terminal::Input_Handler,pc.RxIrq);
+}
+
+/*------------------------------------------------------------------------------
+ Function decodes command that has been input on input command line and performs
+ any necasary action   
+------------------------------------------------------------------------------*/
+void Terminal::HandleCOMMAND(void)
+{
+    INT_32 commandSize = 0;
+    INT_32 dataSIZE = 0;
+    bool searchingCOMMAND = true;
+    bool searchingDATA = true;
+    while(searchingCOMMAND)
+    {
+        if((Terminal_buffer[commandSize] == ' ') || (Terminal_buffer[commandSize] == 0x00))
+        {
+            searchingCOMMAND = false;
+        } else {
+            commandSize++;
+        }
+        
+        // debug break loop if too big
+        if(commandSize > 8){
+            break;
+        }
+    }
+    while(searchingDATA)
+    {
+        if((Terminal_buffer[commandSize+dataSIZE+1] == ' ') || (Terminal_buffer[commandSize+dataSIZE+1] == 0x00))
+        {
+            searchingDATA = false;
+        } else {
+            dataSIZE++;
+        }
+        
+        // debug break loop if too big
+        if(dataSIZE > 8){
+            break;
+        }
+    }
+        
+    if(commandSize == 4)
+    {
+        
+        // Action for input of READ command
+        if((Terminal_buffer[0] == 'R') && (Terminal_buffer[1] == 'E') && (Terminal_buffer[2] == 'A') && (Terminal_buffer[3] == 'D')) {
+            if(dataSIZE > 3){
+                Error msgs;
+                msgs.ErrorCode = warning;
+                msgs.ErrorMSGS = "input Value is not valid for command \"READ\"";
+                ERROR_MSGS(msgs);
+            } else {
+                INT_32 inputVAL;
+                if(dataSIZE == 1) {
+                    BYTE tempARRAY[3] = {'0','0',Terminal_buffer[5]};
+                    inputVAL = strTOint(tempARRAY);
+                } else if(dataSIZE == 2) {
+                    BYTE tempARRAY[3] = {'0',Terminal_buffer[5],Terminal_buffer[6]};
+                    inputVAL = strTOint(tempARRAY);
+                } else if(dataSIZE == 3) {
+                    BYTE tempARRAY[3] = {Terminal_buffer[5],Terminal_buffer[6],Terminal_buffer[7]};
+                    inputVAL = strTOint(tempARRAY);
+                }
+                if(inputVAL != NULL){
+                    mail_t bufferedDATA = internalBuffer.ReadNfromBuffer(inputVAL);
+                    if(bufferedDATA.MDate != NULL){
+                        printBufferedData(bufferedDATA);
+                    } else {
+                        Error msgs;
+                        msgs.ErrorCode = warning;
+                        msgs.ErrorMSGS = "Value is outside the number of stored samples";
+                        ERROR_MSGS(msgs);
+                    }
+                } else {
+                    Error msgs;
+                    msgs.ErrorCode = warning;
+                    msgs.ErrorMSGS = "Value input is incorrect format for command \"READ\"";
+                    ERROR_MSGS(msgs);
+                }
+            }
+                        
+        // Action for input of SETT command
+        } else if((Terminal_buffer[0] == 'S') && (Terminal_buffer[1] == 'E') && (Terminal_buffer[2] == 'T') && (Terminal_buffer[3] == 'T')) {          
+            FLOAT_32 inputVAL;
+            if(dataSIZE == 3) {
+                BYTE tempARRAY[4] = {'0',Terminal_buffer[5],Terminal_buffer[6],Terminal_buffer[7]};
+                inputVAL = strTOflt(tempARRAY);
+            } else if(dataSIZE == 4) {
+                BYTE tempARRAY[4] = {Terminal_buffer[5],Terminal_buffer[6],Terminal_buffer[7],Terminal_buffer[8]};
+                inputVAL = strTOflt(tempARRAY);
+            } else {
+                inputVAL = NULL;
+            }
+            if(inputVAL != NULL){
+                // TELL SAMPLE THREAD TO UPDATE SAMPLE RATE
+                SampleQueue.call(update_sampleRATE, inputVAL);
+                printDEBUG("New sample rate has been applied!!!");
+            } else {
+                Error msgs;
+                msgs.ErrorCode = warning;
+                msgs.ErrorMSGS = "Value input is incorrect format for command \"SETT\"";
+                ERROR_MSGS(msgs);
+            }            
+            
+        // Command not recognised
+        } else {
+            Error msgs;
+            msgs.ErrorCode = warning;
+            msgs.ErrorMSGS = "Command not recognised";
+            ERROR_MSGS(msgs);
+        }
+                
+    } else if(commandSize == 5) {  
+    
+        // Action for STATE command
+        if((Terminal_buffer[0] == 'S') && (Terminal_buffer[1] == 'T') && (Terminal_buffer[2] == 'A') && (Terminal_buffer[3] == 'T') && (Terminal_buffer[4] == 'E')) {
+            if(dataSIZE == 2) {
+                if((Terminal_buffer[6] == 'O') && (Terminal_buffer[7] == 'N')){
+                    SampleQueue.call(start_sampling,true);      // Tell sample thread to begin sampling
+                    printDEBUG("Sampling has been turned ON");  // Print debug message to show command has been executed
+                } else {
+                    Error msgs;
+                    msgs.ErrorCode = warning;
+                    msgs.ErrorMSGS = "State cannot be set to parameter given  for command \"STATE\"";
+                    ERROR_MSGS(msgs);
+                }
+            } else if(dataSIZE == 3) {
+                if((Terminal_buffer[6] == 'O') && (Terminal_buffer[7] == 'F') && (Terminal_buffer[8] == 'F')){
+                    SampleQueue.call(start_sampling,false);
+                    printDEBUG("Sampling has been turned OFF");
+                } else {
+                    Error msgs;
+                    msgs.ErrorCode = warning;
+                    msgs.ErrorMSGS = "State cannot be set to parameter given  for command \"STATE\"";
+                    ERROR_MSGS(msgs);
+                }
+            } else {
+                Error msgs;
+                msgs.ErrorCode = warning;
+                msgs.ErrorMSGS = "State cannot be set to parameter given  for command \"STATE\"";
+                ERROR_MSGS(msgs);
+            }
+            
+        // Command not recognised
+        } else {
+            Error msgs;
+            msgs.ErrorCode = warning;
+            msgs.ErrorMSGS = "Command not recognised";
+            ERROR_MSGS(msgs);
+        }
+        
+    } else if(commandSize == 6) {
+        
+        // Action for DELETE command
+        if((Terminal_buffer[0] == 'D') && (Terminal_buffer[1] == 'E') && (Terminal_buffer[2] == 'L') && (Terminal_buffer[3] == 'E') && (Terminal_buffer[4] == 'T') && (Terminal_buffer[5] == 'E')) {
+            printDEBUG("DELETE command used");
+            
+        // Command not recognised
+        } else {
+            Error msgs;
+            msgs.ErrorCode = warning;
+            msgs.ErrorMSGS = "Command not recognised";
+            ERROR_MSGS(msgs);
+        }
+        
+    } else if(commandSize == 7) {
+        
+        // Action for SETTIME command
+        if((Terminal_buffer[0] == 'S') && (Terminal_buffer[1] == 'E') && (Terminal_buffer[2] == 'T') && (Terminal_buffer[3] == 'T') && (Terminal_buffer[4] == 'I') && (Terminal_buffer[5] == 'M') && (Terminal_buffer[6] == 'E')) {
+            BYTE tempARRAY[8] = {Terminal_buffer[8],Terminal_buffer[9],Terminal_buffer[10],Terminal_buffer[11],Terminal_buffer[12],Terminal_buffer[13],Terminal_buffer[14],Terminal_buffer[15]};
+            if(handleTIME(tempARRAY) == NULL){
+                Error msgs;
+                msgs.ErrorCode = warning;
+                msgs.ErrorMSGS = "TIME could not be set";
+                ERROR_MSGS(msgs);
+            } else {
+                printDEBUG("Time set");
+            }
+            
+        // Action for SETDATE command
+        } else if((Terminal_buffer[0] == 'S') && (Terminal_buffer[1] == 'E') && (Terminal_buffer[2] == 'T') && (Terminal_buffer[3] == 'D') && (Terminal_buffer[4] == 'A') && (Terminal_buffer[5] == 'T') && (Terminal_buffer[6] == 'E')) {
+            BYTE tempARRAY[10] = {Terminal_buffer[8],Terminal_buffer[9],Terminal_buffer[10],Terminal_buffer[11],Terminal_buffer[12],Terminal_buffer[13],Terminal_buffer[14],Terminal_buffer[15],Terminal_buffer[16],Terminal_buffer[17]};
+            if(handleDATE(tempARRAY) == NULL){
+                Error msgs;
+                msgs.ErrorCode = warning;
+                msgs.ErrorMSGS = "DATE could not be set";
+                ERROR_MSGS(msgs);
+            } else {
+                printDEBUG("Date set");
+            }
+            
+        // Action for LOGGING command
+        } else if((Terminal_buffer[0] == 'L') && (Terminal_buffer[1] == 'O') && (Terminal_buffer[2] == 'G') && (Terminal_buffer[3] == 'G') && (Terminal_buffer[4] == 'I') && (Terminal_buffer[5] == 'N') && (Terminal_buffer[6] == 'G')) {
+            if(dataSIZE == 2) {
+                if((Terminal_buffer[8] == 'O') && (Terminal_buffer[9] == 'N')){
+                    Logging_STATE = true;
+                    printDEBUG("LOGGING has been enabled");
+                } else {
+                    Error msgs;
+                    msgs.ErrorCode = warning;
+                    msgs.ErrorMSGS = "State cannot be set to parameter given";
+                    ERROR_MSGS(msgs);
+                }
+            } else if(dataSIZE == 3) {
+                if((Terminal_buffer[8] == 'O') && (Terminal_buffer[9] == 'F') && (Terminal_buffer[10] == 'F')){
+                    printDEBUG("LOGGING has been disabled");
+                    Logging_STATE = false;
+                } else {
+                    Error msgs;
+                    msgs.ErrorCode = warning;
+                    msgs.ErrorMSGS = "State cannot be set to parameter given";
+                    ERROR_MSGS(msgs);
+                }
+            } else {
+                Error msgs;
+                msgs.ErrorCode = warning;
+                msgs.ErrorMSGS = "State cannot be set to parameter given";
+                ERROR_MSGS(msgs);
+            }
+            
+        // Command not recognised
+        } else {
+            Error msgs;
+            msgs.ErrorCode = warning;
+            msgs.ErrorMSGS = "Command not recognised";
+            ERROR_MSGS(msgs);
+        }
+    // Command not recognised
+    } else {
+        Error msgs;
+        msgs.ErrorCode = warning;
+        msgs.ErrorMSGS = "Command not recognised";
+        ERROR_MSGS(msgs);
+    }
+}
+
+/*------------------------------------------------------------------------------
+ ISR for whenever data is in terminal buffer, add function to terminal queue
+ to check which charecteter has been entered and add it to a buffer.
+------------------------------------------------------------------------------*/
+void Terminal::Input_Handler(void)
+{
+    pc.attach(NULL,pc.RxIrq);
+    if(pc.readable()!= 0)
+    {
+        TerminalQueue.call(&PC, &Terminal::checkKEY);
+    }
+}
+
+/*------------------------------------------------------------------------------
+ Function prints debug messages to screen
+------------------------------------------------------------------------------*/
+void Terminal::printDEBUG(BYTE* msgs)
+{
+    if(Logging_STATE == true){
+        Cursor(3,(Rows+8));
+        Colour(ColourWHITE);
+        pc.printf("                                                                                          ");
+        Cursor(3,(Rows+8));
+        pc.printf(msgs);
+    }
+}
+
+/*------------------------------------------------------------------------------
+ Function prints debug messages to screen
+------------------------------------------------------------------------------*/
+void Terminal::printBufferedData(mail_t bufferedDATA)
+{
+    Cursor(1,(Rows+12));
+    Colour(ColourWHITE);
+    pc.printf("                                                                                          ");
+    Cursor(1,(Rows+12));
+    pc.printf("%s , %s , %s , %s ; ",bufferedDATA.MDate,bufferedDATA.MTEMP,bufferedDATA.MPRESS,bufferedDATA.MLIGHT);
+}
+
+/*------------------------------------------------------------------------------
+ Function prints ERROR messages to screen
+------------------------------------------------------------------------------*/
+void Terminal::ERROR_MSGS(Error msgs)
+{   
+    Cursor(3,(Rows+8));
+    pc.printf("                                                                                          ");
+    Cursor(3,(Rows+8));
+     
+    switch(msgs.ErrorCode)
+    {
+        case warning :
+            Colour(ColourAMBER);
+            pc.printf("Warning - %s ", msgs.ErrorMSGS);
+        break;
+        
+        case fault :
+            Colour(ColourAMBER);
+            pc.printf("Fault - %s ", msgs.ErrorMSGS);        
+        break;
+        
+        case criticalERROR :
+            Colour(ColourRED);
+            pc.printf("Critical ERROR - %s ", msgs.ErrorMSGS);       
+        break;
+        
+        case criticalFAILURE :
+            Colour(ColourRED);
+            pc.printf("Critical FAILURE - %s ", msgs.ErrorMSGS);       
+        break;
+    }
+}
+
+/*------------------------------------------------------------------------------
+ Ticker fires once per second and add function to terminal queue to update time
+------------------------------------------------------------------------------*/
+void Terminal::Ticker_Handler(void)
+{
+    TerminalQueue.call(&PC, &Terminal::updateTIME);
+}
+
+/*------------------------------------------------------------------------------
+ Function prints current time to top right of terminal  
+------------------------------------------------------------------------------*/
+void Terminal::updateTIME(void)
+{
+    Cursor(67,1);
+    Colour(ColourWHITE);   
+    pc.printf("%s", getSystemDateTime());
+}
+
+/*------------------------------------------------------------------------------
+ Function converts string to FLOAT_32, one decimal place expected must be 4 bytes
+ long, PAd with '0', example 1.2f would be "01.2" and 12.3f would be "12.3"
+------------------------------------------------------------------------------*/
+FLOAT_32 strTOflt(BYTE ary[4])
+{
+    //check that values entered are in format "00.0"
+    for(INT_32 tester = 0; tester < 4; tester++)
+    {
+        if(tester != 2){
+            INT_32 testing = (INT_32)(ary[tester]-'0');
+            if((testing > 9) || (testing < 0)) {
+                return NULL;
+            }
+        } else if(ary[tester] != '.') {
+            return NULL;
+        }
+    }
+    
+    FLOAT_32 retFlt;
+    
+    retFlt = ((FLOAT_32)(ary[0]-'0'))*10.0f;
+    retFlt += ((FLOAT_32)(ary[1]-'0'));
+    retFlt += ((FLOAT_32)(ary[3]-'0'))/10.0f;
+    
+    if(retFlt > 60.0f){
+        return NULL;
+    } else {
+        return retFlt;
+    }
+}
+
+INT_32 strTOint(BYTE ary[3])
+{   
+    //check that values entered are in format "000"
+    for(INT_32 tester = 0; tester < 3; tester++)
+    {
+        INT_32 testing = (INT_32)(ary[tester]-'0');
+        if((testing > 9) || (testing < 0)) {
+            return NULL;
+        }
+    }
+    
+    INT_32 temp_int = (INT_32)(ary[0]-'0')*100;
+    temp_int += (INT_32)(ary[1]-'0')*10;
+    temp_int += (INT_32)(ary[2]-'0');
+
+    return temp_int;
+}
+
+/*------------------------------------------------------------------------------
+ Function converts string to S_BYTE, format should be 00;00;00 (HH;MM;SS)
+------------------------------------------------------------------------------*/
+BYTE handleTIME(BYTE ary[8])
+{
+    //check that values entered are in format "00.0"
+    for(INT_32 tester = 0; tester < 8; tester++)
+    {
+        if((tester == 2 || tester == 5) == false){
+            INT_32 testing = (INT_32)(ary[tester]-'0');
+            if((testing > 9) || (testing < 0)) {
+                return NULL;
+            }
+        } else if((ary[tester] != ';') && (ary[tester] != '/') && (ary[tester] != ':')) {
+            return NULL;
+        }
+    }
+    
+    S_BYTE HH;
+    S_BYTE MM;
+    S_BYTE SS;
+    
+    HH = ((S_BYTE)(ary[0]-'0'))*10;
+    HH += ((S_BYTE)(ary[1]-'0'));
+    
+    MM = ((S_BYTE)(ary[3]-'0'))*10;
+    MM += ((S_BYTE)(ary[4]-'0'));
+    
+    SS = ((S_BYTE)(ary[6]-'0'))*10;
+    SS += ((S_BYTE)(ary[7]-'0'));
+
+    DisplayQueue.call(setTime,HH,MM,SS);
+
+    return 1;
+}
+/*------------------------------------------------------------------------------
+ Function converts string to S_BYTE, format should be 00;00;0000 (dd;mm;yyyy)
+------------------------------------------------------------------------------*/
+BYTE handleDATE(BYTE ary[10])
+{
+    //check that values entered are in format "00.0"
+    for(INT_32 tester = 0; tester < 10; tester++)
+    {
+        if((tester == 2 || tester == 5) == false){
+            INT_32 testing = (INT_32)(ary[tester]-'0');
+            if((testing > 9) || (testing < 0)) {
+                return NULL;
+            }
+        } else if((ary[tester] != ';') && (ary[tester] != '/') && (ary[tester] != ':')) {
+            return NULL;
+        }
+    }
+    
+    S_BYTE dd;
+    S_BYTE mm;
+    INT_32 yyyy;
+    
+    dd = ((S_BYTE)(ary[0]-'0'))*10;
+    dd += ((S_BYTE)(ary[1]-'0'));
+    
+    mm = ((S_BYTE)(ary[3]-'0'))*10;
+    mm += ((S_BYTE)(ary[4]-'0'));
+    
+    yyyy = ((INT_32)(ary[6]-'0'))*1000;
+    yyyy += ((INT_32)(ary[7]-'0'))*100;
+    yyyy += ((INT_32)(ary[8]-'0'))*10;
+    yyyy += ((INT_32)(ary[9]-'0'));
+
+    DisplayQueue.call(setDate,dd,mm,yyyy);
+    
+    return 1;
+}
diff -r 000000000000 -r 4ccd12e1d789 Terminal.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Terminal.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,83 @@
+/*******************************************************************************
+This header defines Terminal class which has all the functions for controlling a 
+terminal, the serial object is kept private and therefore can only be accessed
+through function of the terminal class.
+*******************************************************************************/
+
+#include "mbed.h"
+#include "rtos.h"
+#include "General.hpp"
+#include "Display.hpp"
+#include "dateTime.hpp"
+#include "cyclicalBUFFER.hpp"
+
+// Use generic to set number of rows in table
+#define Rows 15
+#define MaxDATA (Rows*4)
+
+// Define 8 bit colours for printing to terminal 
+#define ColourRED    9
+#define ColourAMBER  166
+#define ColourGREEN  118
+#define ColourBLUE   12
+#define ColourWHITE  255
+#define ColourPURPLE 5
+
+#ifndef Define_ONCE_Terminal
+#define Define_ONCE_Terminal
+
+    typedef struct 
+    {
+        BYTE ErrorCode;
+        BYTE* ErrorMSGS;
+    } Error;
+
+    // Class Terminal expects tx and rx pins and is used for controlling a serialy conected terminal
+    class Terminal {
+        public:
+            Terminal(PinName tx, PinName rx) : pc(tx, rx){Logging_STATE = true;}
+            void init(void);                                // Initialise terminal and start all timers/interupts
+            void updateSDstate(bool SDstate);               // Updates displayed SD state
+            void updateNetWorkstate(bool NetWorkstate);     // Updates displayed NetWork state
+            void addDATA(void);                             // Function called by sample thread to add new data to terminal
+            
+            void ERROR_MSGS(Error msgs);   // function to print error msgs to debug section of terminal
+            
+            bool getLoggingState(void) {return Logging_STATE;} // return the priavte variable Logging_STATE
+            
+        private:
+            // define serial objects and function needed to change its parameters
+            Serial pc;                              // Serial object to be used for terminal
+            BYTE currentIDX;                        // Stores current cell in terminal
+            void Cursor(BYTE X, BYTE Y);            // Function moves cursor to position defined by co-ordinates x,y
+            void Colour(BYTE COLOUR);               // Function changes terminal print colour to 8 bit colour defined by COLOUR
+            void PrintDATA(BYTE* STRING, BYTE IDX); // Prints DATA to specific cell in table specified by IDX
+            bool col;                               // define current colour for samples to be printed in
+            void printDEBUG(BYTE* msgs);
+            void printBufferedData(mail_t bufferedDATA);
+            
+            // Functions needed to display time in top right of terminal
+            Ticker Terminal_ticker;         // Ticker calls "Ticker_Handler" every second
+            void Ticker_Handler(void);      // ISR hanler fires every second to add "updateTIME" to terminal event queue
+            void updateTIME(void);          // Prints current time to top right of terminal
+
+            //  Function needed to handle command inputs from terminal
+            void Input_Handler(void);       // ISR handler for whenever a charecter is input to terminal
+            void checkKEY(void);            // Functrion gets charecter from terminal input
+            void HandleCOMMAND(void);       // Functions handles any commands input into terminal
+            BYTE buffer_pointer;            // stores current point in terminal input line
+            BYTE Terminal_buffer[30];       // Buffer to store command
+            bool Logging_STATE;              // Stores whether Logging has been enabled/disabled
+    };
+    
+#endif
+
+// Thread used for controlling terminal
+void TerminalThread(void);
+
+FLOAT_32 strTOflt(BYTE ary[4]);
+INT_32 strTOint(BYTE ary[3]);
+BYTE handleTIME(BYTE ary[8]);
+BYTE handleDATE(BYTE ary[10]);
+
+
diff -r 000000000000 -r 4ccd12e1d789 WatchDog.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WatchDog.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,28 @@
+#include "WatchDog.hpp"
+#include "mbed.h"
+
+/* Enables Watchdog Timer -> T(period, s)= (1/32kHz)(4)(2^(IWDG_PR[2:0]))(IWDG_RLR[11:0]+1))*/
+void WatchDog (int prescaler, int reload) 
+{ 				
+	IWDG->KR 	|= 0x0000CCCC; 	// enable IWDG (watchdog)
+	IWDG->KR 	|= 0x00005555; 	// enable register access to PR & RLR
+	IWDG->PR 	|= prescaler; 	// Set prescaler 
+	IWDG->RLR 	|= reload;		// set Reload 				
+}
+
+/* Reset WatchDog timer */
+void Kick (void) 
+{ 
+	//Reset Watchdog counter
+	IWDG->KR |= 0x0000AAAA;
+}
+
+void WatchDogThread(void)
+{	
+	while(1)
+	{
+		Kick();
+		Thread::wait(200);	
+	}	
+}
+
diff -r 000000000000 -r 4ccd12e1d789 WatchDog.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WatchDog.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,9 @@
+
+#ifndef Define_ONCE_WatchDog
+#define Define_ONCE_WatchDog
+
+void WatchDog (int prescaler, int reload);
+void Kick (void);
+void WatchDogThread(void);
+
+#endif
diff -r 000000000000 -r 4ccd12e1d789 cyclicalBUFFER.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cyclicalBUFFER.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,129 @@
+/*------------------------------------------------------------------------------
+Creator : Joel Pallent ; Jonathan Wheadon
+Date : 06/12/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "semaphore.hpp"
+Purpose : to control the flow of data to synchronise everything so that there is
+no problems with the transmit and retrival of data between threads
+
+------------------------------------------------------------------------------*/
+
+#include "cyclicalBUFFER.hpp" 
+
+//Producer
+void cyclical_Buffer::addDataToBuffer(mail_t Data)     
+{
+    //Is there space?
+    int32_t Nspaces = spaceAvailable.wait();
+             
+    //Ok, there is space - take the lock
+    bufferLock.lock();
+        
+    //Update buffer
+    newestIndex = (newestIndex+1) % BUFFERSIZE;  
+    buffer[newestIndex] = Data;               
+    //printf("Data added to buffer"); 
+    
+    //Release lock
+    bufferLock.unlock();
+    
+    //Signal that a sample has been added
+    samplesInBuffer.release();
+    NoOfStoredSamples += 1;
+    
+    if(NoOfStoredSamples == BUFFERSIZE){
+        BufferFull = true;
+    } else {
+        BufferFull = false;
+    }
+}
+
+// the function addDataToBufferOverride adds data to the buffer, if the buffer is full it overides the oldest stored data
+void cyclical_Buffer::addDataToBufferOverride(mail_t Data)     
+{
+    bufferLock.lock();
+    
+    if( BufferFull == true ){
+        oldestIndex = (oldestIndex+1) % BUFFERSIZE;
+        Data = buffer[oldestIndex];
+        NoOfStoredSamples -= 1;
+        BufferFull = false;
+    }
+        
+    //Update buffer
+    newestIndex = (newestIndex+1) % BUFFERSIZE;  
+    buffer[newestIndex] = Data;               
+    //printf("Data added to buffer"); 
+    
+    //Release lock
+    bufferLock.unlock();
+    
+    //Signal that a sample has been added
+    NoOfStoredSamples += 1;
+    
+    if(NoOfStoredSamples == BUFFERSIZE){
+        BufferFull = true;
+    } else {
+        BufferFull = false;
+    }
+}
+
+//Consumer
+mail_t cyclical_Buffer::takeDataFromBuffer(void)
+{    
+    //Are thre any samples in the buffer
+    int32_t Nsamples = samplesInBuffer.wait();
+        
+    //Ok, there are samples - take the lock
+    bufferLock.lock();   
+    
+    mail_t Data;
+    
+    //Update buffer - remove oldest
+    oldestIndex = (oldestIndex+1) % BUFFERSIZE;
+    Data = buffer[oldestIndex];    
+    
+    //Release lock
+    bufferLock.unlock();
+    
+    //Signal there is space in the buffer
+    spaceAvailable.release();                            // change the space available soother things rying to acces the buffer can see there is space
+    NoOfStoredSamples -= 1;
+    
+    BufferFull = false;
+       
+    //return a copy of the result
+    return Data;                                     // returing the input data out in new structure.
+}
+
+// Returns data stored in the Nth place of the buffer
+mail_t cyclical_Buffer::ReadNfromBuffer(UINT_32 N)
+{
+    bufferLock.lock();
+    
+    // If N exceeds the stored samples
+    if((NoOfStoredSamples == 0) || (N > (NoOfStoredSamples - 1))){
+        
+        mail_t voided = {NULL,NULL,NULL,NULL};
+        
+        bufferLock.unlock();
+
+        return voided;
+        
+    } else {
+        
+        UINT_32 idx = (newestIndex - N + 1) % BUFFERSIZE;   
+        
+        mail_t Data;
+        
+        Data = buffer[idx];    
+        
+        //Release lock
+        bufferLock.unlock();
+            
+        //return a copy of the result
+        return Data;
+    }
+}
+
diff -r 000000000000 -r 4ccd12e1d789 cyclicalBUFFER.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cyclicalBUFFER.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,43 @@
+/*------------------------------------------------------------------------------
+Creator : Joel Pallent ; Jonathan Wheadon
+Date : 18/12/2018
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "General.hpp" and "mbed.h"
+Purpose : This is the header file defining the class for our cyclical_Buffer
+------------------------------------------------------------------------------*/
+
+#include "mbed.h"
+#include "General.hpp"
+
+#ifndef __cyclicalBUFFER__
+#define __cyclicalBUFFER__
+
+class cyclical_Buffer {
+    public:
+        cyclical_Buffer(UINT_32 size) : BUFFERSIZE(size), buffer(new mail_t[size]), spaceAvailable(size), samplesInBuffer(0) {newestIndex = size-1; oldestIndex = size-1; NoOfStoredSamples = 0; BufferFull = false;}
+
+        // Functions for cyclical buffer using semaphores (producer consumer patern)
+        void addDataToBuffer(mail_t Data);
+        mail_t takeDataFromBuffer(void);
+        
+        // Functions for keep most resant samples overiding oldest
+        void addDataToBufferOverride(mail_t Data);  // Function will add data to buffer, if buffer is full it overides the oldest data
+        mail_t ReadNfromBuffer(UINT_32 N);          // Function will read the data stored which is Nth from oldest sample. N = 0 is oldest, N = Buffersize = newest
+            
+    private:            
+        //Output buffer
+        const UINT_32 BUFFERSIZE;
+        mail_t* buffer;
+        UINT_32 newestIndex; //First time it is incremented, it will be 0
+        UINT_32 oldestIndex;
+        UINT_32 NoOfStoredSamples;
+        bool BufferFull;
+
+        //Thread sychronisation primatives
+        Semaphore spaceAvailable;
+        Semaphore samplesInBuffer;
+        Mutex bufferLock;
+};
+
+#endif
diff -r 000000000000 -r 4ccd12e1d789 dateTime.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dateTime.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,312 @@
+/*------------------------------------------------------------------------------
+Creator : Ben Gordon
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : 
+------------------------------------------------------------------------------*/
+#include "dateTime.hpp"
+//Constructor
+/*dateTime(PinName GREEN, PinName YELLOW, PinName RED) : _green(GREEN), _yellow(YELLOW), _red(RED) {
+    setDate(); //Sets default date 01/01/1970 00:00:00
+    setTime();
+}*/
+struct tm _addTime_struct;
+struct tm _setTime_struct;
+
+struct tm _updateTime_struct;
+
+DigitalOut _green(PB_11);
+DigitalOut _yellow(PB_10);
+DigitalOut _red(PE_15);
+
+char dateTimeStr[20];
+char dateStr[11];
+char timeStr[9];
+
+////---------------------------SET DATE AND TIME----------------------------////
+BYTE setTime(S_BYTE hours, S_BYTE minutes, S_BYTE seconds)
+{
+    //Get currently set time
+    _setTime_struct = getRawTime();
+    
+    //Setting Time
+    _setTime_struct.tm_hour = hours;
+    _setTime_struct.tm_min  = minutes;
+    _setTime_struct.tm_sec  = seconds;
+    
+    return updateSystemTime();
+}
+
+//Setting the date and time
+BYTE setDate(S_BYTE days, S_BYTE months, INT_32 years)
+{
+    //Get currently set time
+    _setTime_struct = getRawTime();
+    
+    //Setting Date
+    _setTime_struct.tm_mday = days;
+    _setTime_struct.tm_mon  = months -1;
+    _setTime_struct.tm_year = years  -1900;
+    
+    return updateSystemTime();
+}
+////------------------------------------------------------------------------////
+////////////////////////////////////////////////////////////////////////////////
+////---------------------------ADD DATE AND TIME----------------------------////
+void overFlow(INT_32 *base, INT_32 lower, INT_32 upper)
+{
+    if(*base < lower)
+    {
+        *base = upper;
+    }
+    else if (*base > upper)
+    {
+        *base = lower;
+    }
+}
+
+void addDay(S_BYTE days)
+{
+    struct tm _newTime_struct = _addTime_struct;
+    
+    _newTime_struct.tm_mday = _newTime_struct.tm_mday + days;
+    
+    overFlow(&_newTime_struct.tm_mday,1,31);
+    
+    BYTE error = checkStruct(_newTime_struct);
+    
+    if(!(error > 1))
+    {
+        _addTime_struct = _newTime_struct;
+    }
+}
+
+void addMonth(S_BYTE months)
+{
+    struct tm _newTime_struct = _addTime_struct;
+    
+    _newTime_struct.tm_mon = _newTime_struct.tm_mon + months;
+    
+    overFlow(&_newTime_struct.tm_mon,1,12);
+    
+    BYTE error = checkStruct(_newTime_struct);
+    if(!(error > 1))
+    {
+        _addTime_struct = _newTime_struct;
+    }
+}
+
+void addYear(INT_32 years)
+{
+    struct tm _newTime_struct = _addTime_struct;                //Define a structure for the new calculated
+    
+    _newTime_struct.tm_year = _newTime_struct.tm_year + years;  //Update new time
+    
+    overFlow(&_newTime_struct.tm_year,1970,2106);
+    
+    BYTE error = checkStruct(_newTime_struct);                 //Check for errors
+    
+    if(!(error > 1))                                            //If no errors are found, update the time structure
+    {
+        _addTime_struct = _newTime_struct;
+    }
+}
+
+void addHour(S_BYTE hours)
+{
+    struct tm _newTime_struct = _addTime_struct;
+    
+    _newTime_struct.tm_hour = _newTime_struct.tm_hour + hours;
+    
+    overFlow(&_newTime_struct.tm_hour,0,23);
+    
+    BYTE error = checkStruct(_newTime_struct);
+    if(!((error > 1)||(_newTime_struct.tm_hour < 0)||(_newTime_struct.tm_hour > 23)))
+    {
+        _addTime_struct = _newTime_struct;
+    }
+}
+
+void addMin(S_BYTE minutes)
+{
+    struct tm _newTime_struct = _addTime_struct;
+    
+    _newTime_struct.tm_min = _newTime_struct.tm_min + minutes;
+    
+    overFlow(&_newTime_struct.tm_min,0,59);
+    
+    BYTE error = checkStruct(_newTime_struct);
+    if(!((error > 1)||(_newTime_struct.tm_min < 0)||(_newTime_struct.tm_min > 59)))
+    {
+        _addTime_struct = _newTime_struct;
+    }
+}
+
+void addSec(S_BYTE seconds)
+{
+    struct tm _newTime_struct = _addTime_struct;
+    
+    _newTime_struct.tm_sec = _newTime_struct.tm_sec + seconds;
+    
+    overFlow(&_newTime_struct.tm_sec,0,59);
+    
+    BYTE error = checkStruct(_newTime_struct);
+    if(!((error > 1)||(_newTime_struct.tm_sec < 0)||(_newTime_struct.tm_sec > 59)))
+    {
+        _addTime_struct = _newTime_struct;
+    }
+}
+
+BYTE checkStruct(struct tm check)
+{
+   //Initialise LEDs [for debugging] 
+    _green  = 0;
+    _yellow = 0;
+    _red    = 0;
+    
+    //Check new set time is within range of valid dates (1970 - 2106)
+    if((check.tm_year < 1970-1900)||(check.tm_year > 2106-1900))
+    {
+        _red = 1;
+        return 2; //ERROR_2 Year outside of valid range [1970 - 2106]
+    }
+    
+    //Update structure with correct dates (e.g. 32/10 would become 1/11)
+    struct tm _newTime_struct = check;
+    time_t _newTime_time = mktime(&_newTime_struct);
+    _newTime_struct = *localtime(&_newTime_time);
+    
+    //Check structure has remained same (if not, invalid input has been entered (eg 32nd day or 61s minute)
+    if((check.tm_year != _newTime_struct.tm_year)||
+       (check.tm_mon  != _newTime_struct.tm_mon )||
+       (check.tm_mday != _newTime_struct.tm_mday)||
+       (check.tm_hour != _newTime_struct.tm_hour)||
+       (check.tm_min  != _newTime_struct.tm_min )||
+       (check.tm_sec  != _newTime_struct.tm_sec ))
+    {   
+        _yellow = 1;
+        printf("YEAR IS %d", _newTime_struct.tm_year);
+        if(_newTime_struct.tm_year < (1970-1900))
+        {
+            _red = 1;
+            return 3; //ERROR_03 Date exceeds maximum range [06/02/2106 06:28:14]
+        }
+        
+        return 1; //ERROR_01 Index exceeds max value [e.g Date = 32/31 or Hour = 26/24]
+    }
+    _green = 1;
+    return 0; //ERROR_00 No errors
+}
+////------------------------------------------------------------------------////
+////////////////////////////////////////////////////////////////////////////////
+
+BYTE updateSystemTime()
+{
+    //Checking DateTime remains in valid format
+    BYTE error = checkStruct(_setTime_struct);
+    
+    //If no errors are returned, then set the DateTime to set values.
+    if(!error){
+        set_time(mktime(&_setTime_struct));
+    }
+    
+    //Return error to be used for terminal display
+    return error;
+}
+
+BYTE confirmDate()
+{
+    BYTE error;
+    error = checkStruct(_addTime_struct);
+    
+    if(!error)
+    {
+        mktime(&_addTime_struct);
+        updateSystemTime();
+    }
+    else
+    {
+        while(error)
+        {
+            _addTime_struct.tm_mday = _addTime_struct.tm_mday - 1;
+            error = checkStruct(_addTime_struct);
+        }
+        mktime(&_addTime_struct);
+        return 1;
+    }
+    return 0;
+}
+
+char* getSetDate()
+{
+    return printDate(_addTime_struct);
+}
+
+char* getSetTime()
+{
+    return printTime(_addTime_struct);
+}
+
+char* startEditDate()
+{
+    _addTime_struct = getRawTime();
+    return getSetDate();
+}
+
+char* startEditTime()
+{
+    _addTime_struct = getRawTime();
+    return getSetTime();
+}
+
+void   endEdit()
+{
+    set_time(mktime(&_addTime_struct));
+}
+
+char* getSystemDateTime()
+{
+    struct tm _current_time = getRawTime();
+    sprintf(dateTimeStr,"%s %s",printDate(_current_time),printTime(_current_time));
+    return dateTimeStr;
+}
+
+////------------------------------------------------------------------------////
+
+
+struct tm getRawTime()
+{
+    time_t rawTime;
+    time(&rawTime);
+    return *localtime(&rawTime);
+}
+
+//time_t range 0 - 0xFFFFFFFFFFFE [01/01/1970 00:00:00 - 06/02/2106 06:28:14]
+
+char* printDate(struct tm _time_struct) 
+{
+    sprintf(dateStr,"%02d/%02d/%4d",
+                    getDay(_time_struct),
+                    getMonth(_time_struct),
+                    getYear(_time_struct));
+    return dateStr;
+}
+
+char* printTime(struct tm _time_struct)
+{
+    sprintf(timeStr,"%02d:%02d:%02d",
+                    getHour(_time_struct),
+                    getMin(_time_struct),
+                    getSec(_time_struct));
+    return timeStr;
+}
+
+signed INT_32 getYear(struct tm _time_struct)  {return _time_struct.tm_year + 1900;}
+BYTE          getMonth(struct tm _time_struct) {return _time_struct.tm_mon + 1;    }
+BYTE          getDay(struct tm _time_struct)   {return _time_struct.tm_mday;       }
+BYTE          getHour(struct tm _time_struct)  {return _time_struct.tm_hour;       }
+BYTE          getMin(struct tm _time_struct)   {return _time_struct.tm_min;        }
+BYTE          getSec(struct tm _time_struct)   {return _time_struct.tm_sec;        }
+
diff -r 000000000000 -r 4ccd12e1d789 dateTime.hpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dateTime.hpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,58 @@
+/*------------------------------------------------------------------------------
+Creator : Ben Gordon
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : 
+Purpose : 
+------------------------------------------------------------------------------*/
+#ifndef _dateTime_HPP
+#define _dateTime_HPP
+    #include "mbed.h"
+    #include "General.hpp"
+    //dateTime(PinName GREEN, PinName YELLOW, PinName RED);
+    
+    BYTE updateSystemTime();
+    
+    BYTE setTime(S_BYTE hours   = 0,
+                 S_BYTE minutes = 0,
+                 S_BYTE seconds = 0);
+     
+    //Setting the date and time
+    BYTE setDate(S_BYTE days    = 1,
+                 S_BYTE months  = 1,
+                 INT_32 years   = 1970);
+    
+    void addYear (INT_32 years  = 1);
+    
+    void addMonth(S_BYTE months =1);
+    void addDay  (S_BYTE days   =1);
+    void addHour (S_BYTE hours  =1);
+    void addMin  (S_BYTE minutes=1);
+    void addSec  (S_BYTE seconds=1);
+    
+    BYTE confirmDate();
+    char* getSetDate();
+    char* getSetTime();
+    
+    char* startEditDate();
+    char* startEditTime();
+    void   endEdit();
+    
+    char* getSystemDateTime();
+    //-----------------------------------
+    BYTE checkStruct(struct tm check);
+    
+    char* printDate(struct tm _time_struct);
+    
+    char* printTime(struct tm _time_struct);
+    struct tm getRawTime();
+    
+    signed INT_32 getYear(struct tm _time_struct);
+    BYTE          getMonth(struct tm _time_struct);
+    BYTE          getDay(struct tm _time_struct);
+    BYTE          getHour(struct tm _time_struct);
+    BYTE          getMin(struct tm _time_struct);
+    BYTE          getSec(struct tm _time_struct);
+#endif
+
diff -r 000000000000 -r 4ccd12e1d789 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jan 08 16:21:39 2019 +0000
@@ -0,0 +1,56 @@
+/*------------------------------------------------------------------------------
+Creator : Jonathan Wheadon ; Ben Gordon ; Joel Pallent
+Date : 
+Module : ELEC351
+Project : ELEC351_GroupA
+Dependencies : "mbed.h" ; "SDReader.hpp" ; "rtos.h" ; "General.hpp" ;
+"NetWorking.hpp" ; "Display.hpp" ; "Terminal.hpp" ; "Sample.hpp"
+Purpose : Low power enviromental sensor using multi threading, has four outputs,
+SD card, Terminal, LCD, and a website hosted on the ip "10.0.0.10". Two inputs
+LDR (for light values), BMP280 (for pressure and temperature)
+------------------------------------------------------------------------------*/
+
+#include "mbed.h"
+#include "SDReader.hpp"
+#include "rtos.h"
+#include "General.hpp"
+#include "NetWorking.hpp"
+#include "Display.hpp"
+#include "Terminal.hpp"
+#include "Sample.hpp"
+#include "cyclicalBUFFER.hpp" 
+#include "WatchDog.hpp"
+
+// Threads
+Thread Display_THREAD(osPriorityNormal);
+Thread NetWorking_THREAD(osPriorityNormal);
+Thread sample_THREAD(osPriorityRealtime);
+Thread SDcard_THREAD(osPriorityNormal);
+Thread Terminal_THREAD(osPriorityNormal);
+Thread WatchDog_THREAD(osPriorityNormal);
+
+// Thread ID for the Main function (CMSIS API)
+osThreadId tidMain;
+
+//int main starts all threads then becomes TerminalThread
+int main(void)
+{
+    // Main thread ID
+    tidMain = Thread::gettid();
+
+    // Start each thread
+    Display_THREAD.start(DisplayThread);
+    sample_THREAD.start(SampleThread);
+    SDcard_THREAD.start(SDThread);
+    Terminal_THREAD.start(TerminalThread);
+    
+    // Create Watchdog, and start thread to kick watchdog every 200 mili seconds
+    WatchDog(5, 1000);
+    WatchDog_THREAD.start(WatchDogThread);
+    
+    // have Main become
+    NetWorkingThread();
+
+    while(1);
+}
+