Andrew Boyson / oldheating

Dependencies:   net 1-wire lpc1768 crypto clock web fram log

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers program.c Source File

program.c

00001 #include <stdint.h>
00002 #include <stdlib.h>
00003 #include <stdbool.h>
00004 
00005 #include "rtc.h"
00006 #include "clktime.h"
00007 #include "clk.h"
00008 #include "log.h"
00009 #include "fram.h"
00010 #include "http.h"
00011 
00012 #define PROGRAMS_COUNT    3
00013 #define TRANSITIONS_COUNT 4
00014 static int16_t programs[PROGRAMS_COUNT][TRANSITIONS_COUNT]; static int iPrograms;
00015 static char    programDay[7];                               static int iDay;
00016 static char    programNewDayHour;                           static int iNewDayHour;
00017 
00018 int  ProgramGetDay       (int i)             { return (int) programDay[i];    } 
00019 int  ProgramGetNewDayHour()                  { return (int) programNewDayHour;}
00020 
00021 void ProgramSetDay       (int i, int  value) { programDay       [i] = (char)value; FramWrite(iDay        + i, 1, &programDay       [i]); }
00022 void ProgramSetNewDayHour(       int  value) { programNewDayHour    = (char)value; FramWrite(iNewDayHour,     1, &programNewDayHour   ); }
00023 
00024 int ProgramInit()
00025 {
00026     char def1;
00027     int address;
00028     int programSize = PROGRAMS_COUNT * TRANSITIONS_COUNT * sizeof(int16_t);
00029               address = FramLoad(7,            programDay,         NULL); if (address < 0) return -1; iDay        = address;
00030               address = FramLoad(programSize,  programs,           NULL); if (address < 0) return -1; iPrograms   = address; //3 x 4 x 2
00031     def1 = 2; address = FramLoad(1,           &programNewDayHour, &def1); if (address < 0) return -1; iNewDayHour = address;
00032     return 0;
00033 }
00034 
00035 /*
00036 There are three programs available [0|1|2]; any of which can be allocated to a given day [0-6].
00037 Each program contains four transitions with an index [0|1|2|3].
00038 A transition is defined to be a short (16 bit) and consists of:
00039 +---------+--------+--------+---------+
00040 | 15 - 13 |   12   |   11   | 10 - 00 |
00041 +---------+--------+--------+---------+
00042 |         | in use | switch | minute  |
00043 |         | yes/no | on/off | in day  |
00044 |         |   1/0  |  1/0   | 0-1439  |
00045 +---------+--------+--------+---------+
00046 */
00047 static int16_t encodeTransition(bool inuse, bool onoff, int minutes)
00048 {
00049     int16_t    transition  = minutes;
00050                transition &= 0x07FF;
00051     if (onoff) transition |= 0x0800;
00052     if (inuse) transition |= 0x1000;
00053     return transition;
00054 }
00055 static void decodeTransition(int16_t transition, bool* pinuse, bool* ponoff, int* pminutes)
00056 {
00057     *pinuse   = transition & 0x1000;
00058     *ponoff   = transition & 0x0800;
00059     *pminutes = transition & 0x07FF;
00060 }
00061 
00062 static int compareTransition (const void * a, const void * b) //-ve a goes before b; 0 same; +ve a goes after b
00063 {
00064     bool  inUseA,   inUseB;
00065     bool     onA,      onB;
00066     int minutesA, minutesB;
00067     decodeTransition(*(int16_t*)a, &inUseA, &onA, &minutesA);
00068     decodeTransition(*(int16_t*)b, &inUseB, &onB, &minutesB);
00069     
00070     if (!inUseA && !inUseB) return  0;
00071     if (!inUseA)            return +1;
00072     if (!inUseB)            return -1;
00073     
00074     if (minutesA < programNewDayHour * 60) minutesA += 1440;
00075     if (minutesB < programNewDayHour * 60) minutesB += 1440;
00076     
00077     if (minutesA < minutesB) return -1;
00078     if (minutesA > minutesB) return +1;
00079     return 0;
00080 }
00081 static void sort(int16_t* pProgram)
00082 {
00083     qsort (pProgram, 4, sizeof(int16_t), compareTransition);
00084 }
00085 
00086 //[+|-][00-23][00-59];
00087 void ProgramToString(int program, int buflen, char* buffer)
00088 {
00089     if (buflen < 25) return;
00090     char* p = buffer;
00091     for (int i = 0; i < TRANSITIONS_COUNT; i++)
00092     {
00093         int16_t transition = programs[program][i];
00094         bool  inuse;
00095         bool  on;
00096         int   minuteUnits;
00097         decodeTransition(transition, &inuse, &on, &minuteUnits);
00098         if (!inuse) continue;
00099         
00100         int minuteTens  = minuteUnits / 10; minuteUnits %= 10;
00101         int   hourUnits = minuteTens  /  6; minuteTens  %=  6;
00102         int   hourTens  =   hourUnits / 10;   hourUnits %= 10;
00103         
00104         if (p > buffer) *p++ = ' ';
00105         *p++ = on ? '+' : '-';
00106         *p++ = hourTens    + '0';
00107         *p++ = hourUnits   + '0';
00108         *p++ = minuteTens  + '0';
00109         *p++ = minuteUnits + '0';
00110     }
00111     *p = 0;
00112 }
00113 void ProgramSendAjax()
00114 {
00115     for (int program = 0; program < PROGRAMS_COUNT; program++)
00116     {
00117         for (int transition = 0; transition < TRANSITIONS_COUNT; transition++)
00118         {
00119             bool  inuse;
00120             bool  on;
00121             int   minuteUnits;
00122             decodeTransition(programs[program][transition], &inuse, &on, &minuteUnits);
00123             if (!inuse) continue;
00124             
00125             int minuteTens  = minuteUnits / 10; minuteUnits %= 10;
00126             int   hourUnits = minuteTens  /  6; minuteTens  %=  6;
00127             int   hourTens  =   hourUnits / 10;   hourUnits %= 10;
00128             
00129             if (transition) HttpAddChar(' ');
00130             HttpAddChar(on ? '+' : '-');
00131             HttpAddChar(hourTens    + '0');
00132             HttpAddChar(hourUnits   + '0');
00133             HttpAddChar(minuteTens  + '0');
00134             HttpAddChar(minuteUnits + '0');
00135         }
00136         HttpAddChar('\n');
00137     }
00138 }
00139 static void handleParseDelim(int program, int* pIndex, bool* pInUse, bool* pOn, int* pHourTens,  int* pHourUnits, int* pMinuteTens, int* pMinuteUnits)
00140 {
00141     int hour = *pHourTens * 10 + *pHourUnits;
00142     if (hour   <  0) *pInUse = false;
00143     if (hour   > 23) *pInUse = false;
00144     
00145     int minute = *pMinuteTens * 10 + *pMinuteUnits;
00146     if (minute <  0) *pInUse = false;
00147     if (minute > 59) *pInUse = false;
00148     
00149     int minutes = hour * 60 + minute;
00150     
00151     int16_t transition = encodeTransition(*pInUse, *pOn, minutes);
00152     programs[program][*pIndex] = transition;
00153     
00154     *pIndex      += 1;
00155     *pInUse       = 0;
00156     *pOn          = 0;
00157     *pHourTens    = 0;
00158     *pHourUnits   = 0;
00159     *pMinuteTens  = 0;
00160     *pMinuteUnits = 0;
00161 
00162 }
00163 void ProgramParse(int program, char* p)
00164 {
00165     int            i = 0;
00166     bool       inUse = 0;  bool         on = 0;
00167     int    hourUnits = 0;  int    hourTens = 0;
00168     int  minuteUnits = 0;  int  minuteTens = 0;
00169     while (*p && i < TRANSITIONS_COUNT) 
00170     {
00171         if      (*p == '+')              { on = true ; }
00172         else if (*p == '-')              { on = false; }
00173         else if (*p >= '0' && *p <= '9') { inUse = true; hourTens = hourUnits; hourUnits = minuteTens; minuteTens = minuteUnits; minuteUnits = *p - '0'; }
00174         else if (*p == ' ')              { handleParseDelim(program, &i, &inUse, &on, &hourTens, &hourUnits, &minuteTens, &minuteUnits); }
00175         p++;
00176     }
00177     while (i < TRANSITIONS_COUNT) handleParseDelim(program, &i, &inUse, &on, &hourTens, &hourUnits, &minuteTens, &minuteUnits);
00178     sort(&programs[program][0]);
00179     FramWrite(iPrograms + program * 8, 8, &programs[program]);
00180 }
00181 
00182 static bool readProgramTimerOutput()
00183 {   
00184 
00185     if (!ClkTimeIsSet()) return 0;
00186 
00187     struct tm tm;
00188     ClkNowTmLocal(&tm);
00189     
00190     int dayOfWeek = tm.tm_wday;
00191     int minutesNow = tm.tm_hour * 60 + tm.tm_min;
00192     if (tm.tm_hour < programNewDayHour) //Before 2am should be matched against yesterday's program.
00193     {
00194         dayOfWeek--;
00195         if (dayOfWeek < 0) dayOfWeek = 6;
00196     }
00197     
00198     int program = programDay[dayOfWeek];
00199     
00200     bool calling = 0;
00201     for (int i = 0; i < TRANSITIONS_COUNT; i++)
00202     {
00203         int16_t transition = programs[program][i];
00204         bool inuse;
00205         bool on;
00206         int  minutes;
00207         decodeTransition(transition, &inuse, &on, &minutes);
00208         if (!inuse) continue;
00209         if (minutes <= minutesNow) calling = on;
00210     }
00211     
00212     return calling;
00213 }
00214 
00215 bool ProgramTimerOutput;
00216 
00217 int ProgramMain()
00218 {    
00219     ProgramTimerOutput = readProgramTimerOutput();
00220     return 0;
00221 }