Central Heating controller using the real time clock, PHY module for internet, 1-wire interface for temperature sensors, a system log and a configuration file
Dependencies: net 1-wire lpc1768 crypto clock web fram log
/media/uploads/andrewboyson/heating.sch
/media/uploads/andrewboyson/heating.brd
/media/uploads/andrewboyson/eagle.epf
heating/program.c@20:904a4f043f2c, 2019-01-08 (annotated)
- Committer:
- andrewboyson
- Date:
- Tue Jan 08 14:08:33 2019 +0000
- Revision:
- 20:904a4f043f2c
- Parent:
- 0:3c04f4b47041
- Child:
- 47:229338b3adcb
Updated clock library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 0:3c04f4b47041 | 1 | #include <stdint.h> |
andrewboyson | 0:3c04f4b47041 | 2 | #include <stdlib.h> |
andrewboyson | 0:3c04f4b47041 | 3 | #include <stdbool.h> |
andrewboyson | 0:3c04f4b47041 | 4 | |
andrewboyson | 20:904a4f043f2c | 5 | #include "rtc.h" |
andrewboyson | 20:904a4f043f2c | 6 | #include "clktime.h" |
andrewboyson | 20:904a4f043f2c | 7 | #include "clk.h" |
andrewboyson | 20:904a4f043f2c | 8 | #include "log.h" |
andrewboyson | 20:904a4f043f2c | 9 | #include "fram.h" |
andrewboyson | 0:3c04f4b47041 | 10 | |
andrewboyson | 0:3c04f4b47041 | 11 | #define PROGRAMS 3 |
andrewboyson | 0:3c04f4b47041 | 12 | #define TRANSITIONS 4 |
andrewboyson | 0:3c04f4b47041 | 13 | |
andrewboyson | 0:3c04f4b47041 | 14 | static char programDay[7]; static int iDay; |
andrewboyson | 0:3c04f4b47041 | 15 | static int16_t programs[PROGRAMS][TRANSITIONS]; static int iPrograms; |
andrewboyson | 0:3c04f4b47041 | 16 | static char programNewDayHour; static int iNewDayHour; |
andrewboyson | 0:3c04f4b47041 | 17 | |
andrewboyson | 0:3c04f4b47041 | 18 | |
andrewboyson | 0:3c04f4b47041 | 19 | int ProgramGetDay (int i) { return (int) programDay[i]; } |
andrewboyson | 0:3c04f4b47041 | 20 | int ProgramGetNewDayHour() { return (int) programNewDayHour;} |
andrewboyson | 0:3c04f4b47041 | 21 | |
andrewboyson | 0:3c04f4b47041 | 22 | void ProgramSetDay (int i, int value) { programDay [i] = (char)value; FramWrite(iDay + i, 1, &programDay [i]); } |
andrewboyson | 0:3c04f4b47041 | 23 | void ProgramSetNewDayHour( int value) { programNewDayHour = (char)value; FramWrite(iNewDayHour, 1, &programNewDayHour ); } |
andrewboyson | 0:3c04f4b47041 | 24 | |
andrewboyson | 0:3c04f4b47041 | 25 | int ProgramInit() |
andrewboyson | 0:3c04f4b47041 | 26 | { |
andrewboyson | 0:3c04f4b47041 | 27 | char def1; |
andrewboyson | 0:3c04f4b47041 | 28 | int address; |
andrewboyson | 0:3c04f4b47041 | 29 | int programSize = PROGRAMS * TRANSITIONS * sizeof(int16_t); |
andrewboyson | 0:3c04f4b47041 | 30 | address = FramLoad(7, programDay, NULL); if (address < 0) return -1; iDay = address; |
andrewboyson | 0:3c04f4b47041 | 31 | address = FramLoad(programSize, programs, NULL); if (address < 0) return -1; iPrograms = address; //3 x 4 x 2 |
andrewboyson | 0:3c04f4b47041 | 32 | def1 = 2; address = FramLoad(1, &programNewDayHour, &def1); if (address < 0) return -1; iNewDayHour = address; |
andrewboyson | 0:3c04f4b47041 | 33 | return 0; |
andrewboyson | 0:3c04f4b47041 | 34 | } |
andrewboyson | 0:3c04f4b47041 | 35 | |
andrewboyson | 0:3c04f4b47041 | 36 | /* |
andrewboyson | 0:3c04f4b47041 | 37 | There are three programs available [0|1|2]; any of which can be allocated to a given day [0-6]. |
andrewboyson | 0:3c04f4b47041 | 38 | Each program contains four transitions with an index [0|1|2|3]. |
andrewboyson | 0:3c04f4b47041 | 39 | A transition is defined to be a short (16 bit) and consists of: |
andrewboyson | 0:3c04f4b47041 | 40 | +---------+--------+--------+---------+ |
andrewboyson | 0:3c04f4b47041 | 41 | | 15 - 13 | 12 | 11 | 10 - 00 | |
andrewboyson | 0:3c04f4b47041 | 42 | +---------+--------+--------+---------+ |
andrewboyson | 0:3c04f4b47041 | 43 | | | in use | switch | minute | |
andrewboyson | 0:3c04f4b47041 | 44 | | | yes/no | on/off | in day | |
andrewboyson | 0:3c04f4b47041 | 45 | | | 1/0 | 1/0 | 0-1439 | |
andrewboyson | 0:3c04f4b47041 | 46 | +---------+--------+--------+---------+ |
andrewboyson | 0:3c04f4b47041 | 47 | */ |
andrewboyson | 0:3c04f4b47041 | 48 | static int16_t encodeTransition(bool inuse, bool onoff, int minutes) |
andrewboyson | 0:3c04f4b47041 | 49 | { |
andrewboyson | 0:3c04f4b47041 | 50 | int16_t transition = minutes; |
andrewboyson | 0:3c04f4b47041 | 51 | transition &= 0x07FF; |
andrewboyson | 0:3c04f4b47041 | 52 | if (onoff) transition |= 0x0800; |
andrewboyson | 0:3c04f4b47041 | 53 | if (inuse) transition |= 0x1000; |
andrewboyson | 0:3c04f4b47041 | 54 | return transition; |
andrewboyson | 0:3c04f4b47041 | 55 | } |
andrewboyson | 0:3c04f4b47041 | 56 | static void decodeTransition(int16_t transition, bool* pinuse, bool* ponoff, int* pminutes) |
andrewboyson | 0:3c04f4b47041 | 57 | { |
andrewboyson | 0:3c04f4b47041 | 58 | *pinuse = transition & 0x1000; |
andrewboyson | 0:3c04f4b47041 | 59 | *ponoff = transition & 0x0800; |
andrewboyson | 0:3c04f4b47041 | 60 | *pminutes = transition & 0x07FF; |
andrewboyson | 0:3c04f4b47041 | 61 | } |
andrewboyson | 0:3c04f4b47041 | 62 | |
andrewboyson | 0:3c04f4b47041 | 63 | static int compareTransition (const void * a, const void * b) //-ve a goes before b; 0 same; +ve a goes after b |
andrewboyson | 0:3c04f4b47041 | 64 | { |
andrewboyson | 0:3c04f4b47041 | 65 | bool inUseA, inUseB; |
andrewboyson | 0:3c04f4b47041 | 66 | bool onA, onB; |
andrewboyson | 0:3c04f4b47041 | 67 | int minutesA, minutesB; |
andrewboyson | 0:3c04f4b47041 | 68 | decodeTransition(*(int16_t*)a, &inUseA, &onA, &minutesA); |
andrewboyson | 0:3c04f4b47041 | 69 | decodeTransition(*(int16_t*)b, &inUseB, &onB, &minutesB); |
andrewboyson | 0:3c04f4b47041 | 70 | |
andrewboyson | 0:3c04f4b47041 | 71 | if (!inUseA && !inUseB) return 0; |
andrewboyson | 0:3c04f4b47041 | 72 | if (!inUseA) return +1; |
andrewboyson | 0:3c04f4b47041 | 73 | if (!inUseB) return -1; |
andrewboyson | 0:3c04f4b47041 | 74 | |
andrewboyson | 0:3c04f4b47041 | 75 | if (minutesA < programNewDayHour * 60) minutesA += 1440; |
andrewboyson | 0:3c04f4b47041 | 76 | if (minutesB < programNewDayHour * 60) minutesB += 1440; |
andrewboyson | 0:3c04f4b47041 | 77 | |
andrewboyson | 0:3c04f4b47041 | 78 | if (minutesA < minutesB) return -1; |
andrewboyson | 0:3c04f4b47041 | 79 | if (minutesA > minutesB) return +1; |
andrewboyson | 0:3c04f4b47041 | 80 | return 0; |
andrewboyson | 0:3c04f4b47041 | 81 | } |
andrewboyson | 0:3c04f4b47041 | 82 | static void sort(int16_t* pProgram) |
andrewboyson | 0:3c04f4b47041 | 83 | { |
andrewboyson | 0:3c04f4b47041 | 84 | qsort (pProgram, 4, sizeof(int16_t), compareTransition); |
andrewboyson | 0:3c04f4b47041 | 85 | } |
andrewboyson | 0:3c04f4b47041 | 86 | |
andrewboyson | 0:3c04f4b47041 | 87 | //[+|-][00-23][00-59]; |
andrewboyson | 0:3c04f4b47041 | 88 | void ProgramToString(int program, int buflen, char* buffer) |
andrewboyson | 0:3c04f4b47041 | 89 | { |
andrewboyson | 0:3c04f4b47041 | 90 | if (buflen < 25) return; |
andrewboyson | 0:3c04f4b47041 | 91 | char* p = buffer; |
andrewboyson | 0:3c04f4b47041 | 92 | for (int i = 0; i < TRANSITIONS; i++) |
andrewboyson | 0:3c04f4b47041 | 93 | { |
andrewboyson | 0:3c04f4b47041 | 94 | int16_t transition = programs[program][i]; |
andrewboyson | 0:3c04f4b47041 | 95 | bool inuse; |
andrewboyson | 0:3c04f4b47041 | 96 | bool on; |
andrewboyson | 0:3c04f4b47041 | 97 | int minuteUnits; |
andrewboyson | 0:3c04f4b47041 | 98 | decodeTransition(transition, &inuse, &on, &minuteUnits); |
andrewboyson | 0:3c04f4b47041 | 99 | if (!inuse) continue; |
andrewboyson | 0:3c04f4b47041 | 100 | |
andrewboyson | 0:3c04f4b47041 | 101 | int minuteTens = minuteUnits / 10; minuteUnits %= 10; |
andrewboyson | 0:3c04f4b47041 | 102 | int hourUnits = minuteTens / 6; minuteTens %= 6; |
andrewboyson | 0:3c04f4b47041 | 103 | int hourTens = hourUnits / 10; hourUnits %= 10; |
andrewboyson | 0:3c04f4b47041 | 104 | |
andrewboyson | 0:3c04f4b47041 | 105 | if (p > buffer) *p++ = ' '; |
andrewboyson | 0:3c04f4b47041 | 106 | *p++ = on ? '+' : '-'; |
andrewboyson | 0:3c04f4b47041 | 107 | *p++ = hourTens + '0'; |
andrewboyson | 0:3c04f4b47041 | 108 | *p++ = hourUnits + '0'; |
andrewboyson | 0:3c04f4b47041 | 109 | *p++ = minuteTens + '0'; |
andrewboyson | 0:3c04f4b47041 | 110 | *p++ = minuteUnits + '0'; |
andrewboyson | 0:3c04f4b47041 | 111 | } |
andrewboyson | 0:3c04f4b47041 | 112 | *p = 0; |
andrewboyson | 0:3c04f4b47041 | 113 | } |
andrewboyson | 0:3c04f4b47041 | 114 | static void handleParseDelim(int program, int* pIndex, bool* pInUse, bool* pOn, int* pHourTens, int* pHourUnits, int* pMinuteTens, int* pMinuteUnits) |
andrewboyson | 0:3c04f4b47041 | 115 | { |
andrewboyson | 0:3c04f4b47041 | 116 | int hour = *pHourTens * 10 + *pHourUnits; |
andrewboyson | 0:3c04f4b47041 | 117 | if (hour < 0) *pInUse = false; |
andrewboyson | 0:3c04f4b47041 | 118 | if (hour > 23) *pInUse = false; |
andrewboyson | 0:3c04f4b47041 | 119 | |
andrewboyson | 0:3c04f4b47041 | 120 | int minute = *pMinuteTens * 10 + *pMinuteUnits; |
andrewboyson | 0:3c04f4b47041 | 121 | if (minute < 0) *pInUse = false; |
andrewboyson | 0:3c04f4b47041 | 122 | if (minute > 59) *pInUse = false; |
andrewboyson | 0:3c04f4b47041 | 123 | |
andrewboyson | 0:3c04f4b47041 | 124 | int minutes = hour * 60 + minute; |
andrewboyson | 0:3c04f4b47041 | 125 | |
andrewboyson | 0:3c04f4b47041 | 126 | int16_t transition = encodeTransition(*pInUse, *pOn, minutes); |
andrewboyson | 0:3c04f4b47041 | 127 | programs[program][*pIndex] = transition; |
andrewboyson | 0:3c04f4b47041 | 128 | |
andrewboyson | 0:3c04f4b47041 | 129 | *pIndex += 1; |
andrewboyson | 0:3c04f4b47041 | 130 | *pInUse = 0; |
andrewboyson | 0:3c04f4b47041 | 131 | *pOn = 0; |
andrewboyson | 0:3c04f4b47041 | 132 | *pHourTens = 0; |
andrewboyson | 0:3c04f4b47041 | 133 | *pHourUnits = 0; |
andrewboyson | 0:3c04f4b47041 | 134 | *pMinuteTens = 0; |
andrewboyson | 0:3c04f4b47041 | 135 | *pMinuteUnits = 0; |
andrewboyson | 0:3c04f4b47041 | 136 | |
andrewboyson | 0:3c04f4b47041 | 137 | } |
andrewboyson | 0:3c04f4b47041 | 138 | void ProgramParse(int program, char* p) |
andrewboyson | 0:3c04f4b47041 | 139 | { |
andrewboyson | 0:3c04f4b47041 | 140 | int i = 0; |
andrewboyson | 0:3c04f4b47041 | 141 | bool inUse = 0; bool on = 0; |
andrewboyson | 0:3c04f4b47041 | 142 | int hourUnits = 0; int hourTens = 0; |
andrewboyson | 0:3c04f4b47041 | 143 | int minuteUnits = 0; int minuteTens = 0; |
andrewboyson | 0:3c04f4b47041 | 144 | while (*p && i < TRANSITIONS) |
andrewboyson | 0:3c04f4b47041 | 145 | { |
andrewboyson | 0:3c04f4b47041 | 146 | if (*p == '+') { on = true ; } |
andrewboyson | 0:3c04f4b47041 | 147 | else if (*p == '-') { on = false; } |
andrewboyson | 0:3c04f4b47041 | 148 | else if (*p >= '0' && *p <= '9') { inUse = true; hourTens = hourUnits; hourUnits = minuteTens; minuteTens = minuteUnits; minuteUnits = *p - '0'; } |
andrewboyson | 0:3c04f4b47041 | 149 | else if (*p == ' ') { handleParseDelim(program, &i, &inUse, &on, &hourTens, &hourUnits, &minuteTens, &minuteUnits); } |
andrewboyson | 0:3c04f4b47041 | 150 | p++; |
andrewboyson | 0:3c04f4b47041 | 151 | } |
andrewboyson | 0:3c04f4b47041 | 152 | while (i < TRANSITIONS) handleParseDelim(program, &i, &inUse, &on, &hourTens, &hourUnits, &minuteTens, &minuteUnits); |
andrewboyson | 0:3c04f4b47041 | 153 | sort(&programs[program][0]); |
andrewboyson | 0:3c04f4b47041 | 154 | FramWrite(iPrograms + program * 8, 8, &programs[program]); |
andrewboyson | 0:3c04f4b47041 | 155 | } |
andrewboyson | 0:3c04f4b47041 | 156 | |
andrewboyson | 0:3c04f4b47041 | 157 | static bool readProgramTimerOutput() |
andrewboyson | 0:3c04f4b47041 | 158 | { |
andrewboyson | 0:3c04f4b47041 | 159 | |
andrewboyson | 20:904a4f043f2c | 160 | if (!ClkTimeIsSet()) return 0; |
andrewboyson | 0:3c04f4b47041 | 161 | |
andrewboyson | 0:3c04f4b47041 | 162 | struct tm tm; |
andrewboyson | 20:904a4f043f2c | 163 | ClkNowTmLocal(&tm); |
andrewboyson | 0:3c04f4b47041 | 164 | |
andrewboyson | 0:3c04f4b47041 | 165 | int dayOfWeek = tm.tm_wday; |
andrewboyson | 0:3c04f4b47041 | 166 | int minutesNow = tm.tm_hour * 60 + tm.tm_min; |
andrewboyson | 0:3c04f4b47041 | 167 | if (tm.tm_hour < programNewDayHour) //Before 2am should be matched against yesterday's program. |
andrewboyson | 0:3c04f4b47041 | 168 | { |
andrewboyson | 0:3c04f4b47041 | 169 | dayOfWeek--; |
andrewboyson | 0:3c04f4b47041 | 170 | if (dayOfWeek < 0) dayOfWeek = 6; |
andrewboyson | 0:3c04f4b47041 | 171 | } |
andrewboyson | 0:3c04f4b47041 | 172 | |
andrewboyson | 0:3c04f4b47041 | 173 | int program = programDay[dayOfWeek]; |
andrewboyson | 0:3c04f4b47041 | 174 | |
andrewboyson | 0:3c04f4b47041 | 175 | bool calling = 0; |
andrewboyson | 0:3c04f4b47041 | 176 | for (int i = 0; i < TRANSITIONS; i++) |
andrewboyson | 0:3c04f4b47041 | 177 | { |
andrewboyson | 0:3c04f4b47041 | 178 | int16_t transition = programs[program][i]; |
andrewboyson | 0:3c04f4b47041 | 179 | bool inuse; |
andrewboyson | 0:3c04f4b47041 | 180 | bool on; |
andrewboyson | 0:3c04f4b47041 | 181 | int minutes; |
andrewboyson | 0:3c04f4b47041 | 182 | decodeTransition(transition, &inuse, &on, &minutes); |
andrewboyson | 0:3c04f4b47041 | 183 | if (!inuse) continue; |
andrewboyson | 0:3c04f4b47041 | 184 | if (minutes <= minutesNow) calling = on; |
andrewboyson | 0:3c04f4b47041 | 185 | } |
andrewboyson | 0:3c04f4b47041 | 186 | |
andrewboyson | 0:3c04f4b47041 | 187 | return calling; |
andrewboyson | 0:3c04f4b47041 | 188 | } |
andrewboyson | 0:3c04f4b47041 | 189 | |
andrewboyson | 0:3c04f4b47041 | 190 | bool ProgramTimerOutput; |
andrewboyson | 0:3c04f4b47041 | 191 | |
andrewboyson | 0:3c04f4b47041 | 192 | int ProgramMain() |
andrewboyson | 0:3c04f4b47041 | 193 | { |
andrewboyson | 0:3c04f4b47041 | 194 | ProgramTimerOutput = readProgramTimerOutput(); |
andrewboyson | 0:3c04f4b47041 | 195 | return 0; |
andrewboyson | 0:3c04f4b47041 | 196 | } |