Temp Publish
Revision 0:4ccd12e1d789, committed 2019-01-08
- Comitter:
- Jonathan738
- Date:
- Tue Jan 08 16:21:39 2019 +0000
- Commit message:
- FIXING EVERYTHING
Changed in this revision
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(ð); + + // 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); +} +