Repository for import to local machine

Dependencies:   DMBasicGUI DMSupport

Committer:
jmitc91516
Date:
Mon Jul 31 15:37:57 2017 +0000
Revision:
8:26e49e6955bd
Parent:
1:a5258871b33d
Method ramp scrolling improved, and more bitmaps moved to QSPI memory

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jmitc91516 1:a5258871b33d 1 /*
jmitc91516 1:a5258871b33d 2 This class consists of static functions that handle the real time clock [RTC] on the GC.
jmitc91516 1:a5258871b33d 3 It contains only static functions, and cannot be instantiated.
jmitc91516 1:a5258871b33d 4 */
jmitc91516 1:a5258871b33d 5
jmitc91516 1:a5258871b33d 6 #include "GCRealTimeClock.h"
jmitc91516 1:a5258871b33d 7
jmitc91516 1:a5258871b33d 8
jmitc91516 1:a5258871b33d 9 /*
jmitc91516 1:a5258871b33d 10 Gets the various time fields from the relevant GC registers
jmitc91516 1:a5258871b33d 11 using the "QRTC000r" command, where 'r' is the register number
jmitc91516 1:a5258871b33d 12 for each field. Returns the command responses, as strings,
jmitc91516 1:a5258871b33d 13 in the buffers specified.
jmitc91516 1:a5258871b33d 14
jmitc91516 1:a5258871b33d 15 Note that, to avoid rollover (see comments in function 'GetGCClockTime'),
jmitc91516 1:a5258871b33d 16 we do minimal processing between getting each response.
jmitc91516 1:a5258871b33d 17
jmitc91516 1:a5258871b33d 18 Args: a pointer to the USBHostGC instance that corresponds to the GC,
jmitc91516 1:a5258871b33d 19 a pointer to the USBDeviceConnected instance that (also) corresponds to the GC
jmitc91516 1:a5258871b33d 20 pointers to the buffers to contain the time fields - it is up to the caller
jmitc91516 1:a5258871b33d 21 to make sure these are large enough for a GC response
jmitc91516 1:a5258871b33d 22
jmitc91516 1:a5258871b33d 23 Returns true if it succeeded, false if it failed (e.g. the GC gave an error, etc)
jmitc91516 1:a5258871b33d 24 */
jmitc91516 1:a5258871b33d 25 bool GCRealTimeClock::GetTimeFieldsFromGC(USBDeviceConnected* usbDevice,
jmitc91516 1:a5258871b33d 26 USBHostGC* usbHostGC,
jmitc91516 1:a5258871b33d 27 char *gcSecondsResponse,
jmitc91516 1:a5258871b33d 28 char *gcMinutesResponse,
jmitc91516 1:a5258871b33d 29 char *gcHoursResponse,
jmitc91516 1:a5258871b33d 30 char *gcDateResponse,
jmitc91516 1:a5258871b33d 31 char *gcMonthResponse,
jmitc91516 1:a5258871b33d 32 char *gcYearResponse)
jmitc91516 1:a5258871b33d 33 {
jmitc91516 1:a5258871b33d 34 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 35 usbHostGC->SetDeviceReport(usbDevice, "QRTC0000", gcSecondsResponse);
jmitc91516 1:a5258871b33d 36 if(gcSecondsResponse[0] == 'E') {
jmitc91516 1:a5258871b33d 37 // Assume "EPKT"
jmitc91516 1:a5258871b33d 38 return false;
jmitc91516 1:a5258871b33d 39 }
jmitc91516 1:a5258871b33d 40
jmitc91516 1:a5258871b33d 41 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 42 usbHostGC->SetDeviceReport(usbDevice, "QRTC0001", gcMinutesResponse);
jmitc91516 1:a5258871b33d 43 if(gcMinutesResponse[0] == 'E') {
jmitc91516 1:a5258871b33d 44 // Assume "EPKT"
jmitc91516 1:a5258871b33d 45 return false;
jmitc91516 1:a5258871b33d 46 }
jmitc91516 1:a5258871b33d 47
jmitc91516 1:a5258871b33d 48 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 49 usbHostGC->SetDeviceReport(usbDevice, "QRTC0002", gcHoursResponse);
jmitc91516 1:a5258871b33d 50 if(gcHoursResponse[0] == 'E') {
jmitc91516 1:a5258871b33d 51 // Assume "EPKT"
jmitc91516 1:a5258871b33d 52 return false;
jmitc91516 1:a5258871b33d 53 }
jmitc91516 1:a5258871b33d 54
jmitc91516 1:a5258871b33d 55 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 56 usbHostGC->SetDeviceReport(usbDevice, "QRTC0004", gcDateResponse);
jmitc91516 1:a5258871b33d 57 if(gcDateResponse[0] == 'E') {
jmitc91516 1:a5258871b33d 58 // Assume "EPKT"
jmitc91516 1:a5258871b33d 59 return false;
jmitc91516 1:a5258871b33d 60 }
jmitc91516 1:a5258871b33d 61
jmitc91516 1:a5258871b33d 62 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 63 usbHostGC->SetDeviceReport(usbDevice, "QRTC0005", gcMonthResponse);
jmitc91516 1:a5258871b33d 64 if(gcMonthResponse[0] == 'E') {
jmitc91516 1:a5258871b33d 65 // Assume "EPKT"
jmitc91516 1:a5258871b33d 66 return false;
jmitc91516 1:a5258871b33d 67 }
jmitc91516 1:a5258871b33d 68
jmitc91516 1:a5258871b33d 69 while(usbHostGC->ExecutingSetDeviceReport()) {}
jmitc91516 1:a5258871b33d 70 usbHostGC->SetDeviceReport(usbDevice, "QRTC0006", gcYearResponse);
jmitc91516 1:a5258871b33d 71 if(gcYearResponse[0] == 'E') {
jmitc91516 1:a5258871b33d 72 // Assume "EPKT"
jmitc91516 1:a5258871b33d 73 return false;
jmitc91516 1:a5258871b33d 74 }
jmitc91516 1:a5258871b33d 75
jmitc91516 1:a5258871b33d 76 // If we get here, all the above must have succeeded
jmitc91516 1:a5258871b33d 77 return true;
jmitc91516 1:a5258871b33d 78 }
jmitc91516 1:a5258871b33d 79
jmitc91516 1:a5258871b33d 80 /*
jmitc91516 1:a5258871b33d 81 Constructs a time value from the GC responses returned by 'GetTimeFieldsFromGC()'.
jmitc91516 1:a5258871b33d 82 Fills a 'tm' struct - see the <ctime> (time.h) system include file.
jmitc91516 1:a5258871b33d 83
jmitc91516 1:a5258871b33d 84 We expect the responses to look like "DRTCnnnn", where "nnnn" is the value
jmitc91516 1:a5258871b33d 85 of the relevant register, so we expect the register value to start in array element 4.
jmitc91516 1:a5258871b33d 86
jmitc91516 1:a5258871b33d 87 For a full description of the register values, see the DS1307 Real-Time Clock documentation,
jmitc91516 1:a5258871b33d 88 which can currently be found here:
jmitc91516 1:a5258871b33d 89
jmitc91516 1:a5258871b33d 90 V:\Development\500 Series GC\Main Instrument\Documentation\Electronic\DS1307 IIC RTCC Chip.pdf
jmitc91516 1:a5258871b33d 91
jmitc91516 1:a5258871b33d 92 [V: is the Ellutia File Server.]
jmitc91516 1:a5258871b33d 93
jmitc91516 1:a5258871b33d 94 *** The register values are in binary coded decimal format. ***
jmitc91516 1:a5258871b33d 95
jmitc91516 1:a5258871b33d 96
jmitc91516 1:a5258871b33d 97 Args: a pointer to a 'tm' struct to be filled with the time value
jmitc91516 1:a5258871b33d 98 pointers to the buffers that contain each of the time fields
jmitc91516 1:a5258871b33d 99 returned by the GC in our 'GetTimeFieldsFromGC()' function
jmitc91516 1:a5258871b33d 100
jmitc91516 1:a5258871b33d 101 No return code.
jmitc91516 1:a5258871b33d 102 */
jmitc91516 1:a5258871b33d 103 void GCRealTimeClock::MakeTimeValueFromGCTimeFields(struct tm *timeValue,
jmitc91516 1:a5258871b33d 104 char *gcSecondsResponse,
jmitc91516 1:a5258871b33d 105 char *gcMinutesResponse,
jmitc91516 1:a5258871b33d 106 char *gcHoursResponse,
jmitc91516 1:a5258871b33d 107 char *gcDateResponse,
jmitc91516 1:a5258871b33d 108 char *gcMonthResponse,
jmitc91516 1:a5258871b33d 109 char *gcYearResponse)
jmitc91516 1:a5258871b33d 110 {
jmitc91516 1:a5258871b33d 111 int secondsValue;
jmitc91516 1:a5258871b33d 112 sscanf(&gcSecondsResponse[4], "%d", &secondsValue);
jmitc91516 1:a5258871b33d 113
jmitc91516 1:a5258871b33d 114 int secondsUnitsDigit = secondsValue & 0xF;
jmitc91516 1:a5258871b33d 115 int secondsTensDigit = (secondsValue & 0x70) >> 4;
jmitc91516 1:a5258871b33d 116 timeValue->tm_sec = secondsUnitsDigit + (secondsTensDigit * 10);
jmitc91516 1:a5258871b33d 117
jmitc91516 1:a5258871b33d 118
jmitc91516 1:a5258871b33d 119 int minutesValue;
jmitc91516 1:a5258871b33d 120 sscanf(&gcMinutesResponse[4], "%d", &minutesValue);
jmitc91516 1:a5258871b33d 121
jmitc91516 1:a5258871b33d 122 int minutesUnitsDigit = minutesValue & 0xF;
jmitc91516 1:a5258871b33d 123 int minutesTensDigit = (minutesValue & 0x70) >> 4;
jmitc91516 1:a5258871b33d 124 timeValue->tm_min = minutesUnitsDigit + (minutesTensDigit * 10);
jmitc91516 1:a5258871b33d 125
jmitc91516 1:a5258871b33d 126
jmitc91516 1:a5258871b33d 127 int hoursValue;
jmitc91516 1:a5258871b33d 128 sscanf(&gcHoursResponse[4], "%d", &hoursValue);
jmitc91516 1:a5258871b33d 129
jmitc91516 1:a5258871b33d 130 // Note that, while the GC real-time clock can work in 12 or 24 hour mode,
jmitc91516 1:a5258871b33d 131 // the 'tm' struct can only handle 24 hour clock values.
jmitc91516 1:a5258871b33d 132 int hoursUnitsDigit = hoursValue & 0xF;
jmitc91516 1:a5258871b33d 133 int hoursTensDigit = 0;
jmitc91516 1:a5258871b33d 134 if(hoursValue & 0x40) {
jmitc91516 1:a5258871b33d 135 // 12 hour mode - hours range is 01-12 -
jmitc91516 1:a5258871b33d 136 // but tm struct needs hours to start at zero, not one
jmitc91516 1:a5258871b33d 137 hoursTensDigit = (hoursValue & 0x10) >> 4;
jmitc91516 1:a5258871b33d 138 timeValue->tm_hour = hoursUnitsDigit + (hoursTensDigit * 10) - 1;
jmitc91516 1:a5258871b33d 139 if(hoursValue & 0x20) {
jmitc91516 1:a5258871b33d 140 // pm (else am)
jmitc91516 1:a5258871b33d 141 timeValue->tm_hour += 12;
jmitc91516 1:a5258871b33d 142 }
jmitc91516 1:a5258871b33d 143 } else {
jmitc91516 1:a5258871b33d 144 // 24 hour mode - hours range is 00-23
jmitc91516 1:a5258871b33d 145 hoursTensDigit = (hoursValue & 0x30) >> 4;
jmitc91516 1:a5258871b33d 146 timeValue->tm_hour = hoursUnitsDigit + (hoursTensDigit * 10);
jmitc91516 1:a5258871b33d 147 }
jmitc91516 1:a5258871b33d 148
jmitc91516 1:a5258871b33d 149
jmitc91516 1:a5258871b33d 150 int dateValue;
jmitc91516 1:a5258871b33d 151 sscanf(&gcDateResponse[4], "%d", &dateValue);
jmitc91516 1:a5258871b33d 152
jmitc91516 1:a5258871b33d 153 int dateUnitsDigit = dateValue & 0xF;
jmitc91516 1:a5258871b33d 154 int dateTensDigit = (dateValue & 0x30) >> 4;
jmitc91516 1:a5258871b33d 155 timeValue->tm_mday = dateUnitsDigit + (dateTensDigit * 10);
jmitc91516 1:a5258871b33d 156
jmitc91516 1:a5258871b33d 157
jmitc91516 1:a5258871b33d 158 int monthValue;
jmitc91516 1:a5258871b33d 159 sscanf(&gcMonthResponse[4], "%d", &monthValue);
jmitc91516 1:a5258871b33d 160
jmitc91516 1:a5258871b33d 161 // GC month value range is 1-12 - but 'tm' struct month range is 0-11
jmitc91516 1:a5258871b33d 162 int monthUnitsDigit = monthValue & 0xF;
jmitc91516 1:a5258871b33d 163 int monthTensDigit = (monthValue & 0x10) >> 4;
jmitc91516 1:a5258871b33d 164 timeValue->tm_mon = monthUnitsDigit + (monthTensDigit * 10) - 1;
jmitc91516 1:a5258871b33d 165
jmitc91516 1:a5258871b33d 166
jmitc91516 1:a5258871b33d 167 int yearValue;
jmitc91516 1:a5258871b33d 168 sscanf(&gcYearResponse[4], "%d", &yearValue);
jmitc91516 1:a5258871b33d 169
jmitc91516 1:a5258871b33d 170 // GC year value is 00-99 - but 'tm' struct year value
jmitc91516 1:a5258871b33d 171 // is the number of years since 1900
jmitc91516 1:a5258871b33d 172 int yearUnitsDigit = yearValue & 0xF;
jmitc91516 1:a5258871b33d 173 int yearTensDigit = (yearValue & 0xF0) >> 4;
jmitc91516 1:a5258871b33d 174 timeValue->tm_year = yearUnitsDigit + (yearTensDigit * 10) + 100;
jmitc91516 1:a5258871b33d 175 }
jmitc91516 1:a5258871b33d 176
jmitc91516 1:a5258871b33d 177
jmitc91516 1:a5258871b33d 178 /*
jmitc91516 1:a5258871b33d 179 Get the time and date from the GC's real time clock,
jmitc91516 1:a5258871b33d 180 and return it in a time_t variable provided by the caller
jmitc91516 1:a5258871b33d 181
jmitc91516 1:a5258871b33d 182 Args: a pointer to the USBHostGC instance that corresponds to the GC,
jmitc91516 1:a5258871b33d 183 a pointer to the USBDeviceConnected instance that (also) corresponds to the GC
jmitc91516 1:a5258871b33d 184 a pointer to a time_t variable, which we will set to the GC time
jmitc91516 1:a5258871b33d 185
jmitc91516 1:a5258871b33d 186 Returns true if it succeeded, false if it failed (e.g. the GC gave an error, etc)
jmitc91516 1:a5258871b33d 187 */
jmitc91516 1:a5258871b33d 188 bool GCRealTimeClock::GetGCClockTime(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC, time_t *clockTime)
jmitc91516 1:a5258871b33d 189 {
jmitc91516 1:a5258871b33d 190 // The seconds, minutes, hours, date (i.e. day of the month), month and year are kept in separate registers
jmitc91516 1:a5258871b33d 191 // in the GC, so we get them separately. This means we must guard against 'rollover' -
jmitc91516 1:a5258871b33d 192 // e.g. the GC time when we get the minutes is 11:59, but when we get the hours
jmitc91516 1:a5258871b33d 193 // it is 12:00, so we think the time is 12:59.
jmitc91516 1:a5258871b33d 194 //
jmitc91516 1:a5258871b33d 195 // We do this in two ways:
jmitc91516 1:a5258871b33d 196 //
jmitc91516 1:a5258871b33d 197 // 1 - we do minimal processing between getting each value (see also function 'GetTimeFieldsFromGC')
jmitc91516 1:a5258871b33d 198 // 2 - we get the time twice - if the first value is greater than the second,
jmitc91516 1:a5258871b33d 199 // we assume that the first must have rolled over, so we use the second,
jmitc91516 1:a5258871b33d 200 // otherwise we use the first (they surely cannot both rollover unless
jmitc91516 1:a5258871b33d 201 // they are exactly 60 seconds apart, which is very unlikely - or 60 minutes,
jmitc91516 1:a5258871b33d 202 // 1 day, etc, which is even more unlikely). Also note that, since we get
jmitc91516 1:a5258871b33d 203 // the components in ascending order of 'size', any rollover will always
jmitc91516 1:a5258871b33d 204 // make the time value greater than it should be, not less.
jmitc91516 1:a5258871b33d 205
jmitc91516 1:a5258871b33d 206
jmitc91516 1:a5258871b33d 207 // Date and time value 1
jmitc91516 1:a5258871b33d 208 char seconds1[20];
jmitc91516 1:a5258871b33d 209 char minutes1[20];
jmitc91516 1:a5258871b33d 210 char hours1[20];
jmitc91516 1:a5258871b33d 211 char date1[20];
jmitc91516 1:a5258871b33d 212 char month1[20];
jmitc91516 1:a5258871b33d 213 char year1[20];
jmitc91516 1:a5258871b33d 214 if(!GetTimeFieldsFromGC(usbDevice, usbHostGC, seconds1, minutes1, hours1, date1, month1, year1)) {
jmitc91516 1:a5258871b33d 215 return false;
jmitc91516 1:a5258871b33d 216 }
jmitc91516 1:a5258871b33d 217
jmitc91516 1:a5258871b33d 218 // *** Do nothing between these two 'GetTimeFieldsFromGC' calls ***
jmitc91516 1:a5258871b33d 219
jmitc91516 1:a5258871b33d 220 // Date and time value 2
jmitc91516 1:a5258871b33d 221 char seconds2[20];
jmitc91516 1:a5258871b33d 222 char minutes2[20];
jmitc91516 1:a5258871b33d 223 char hours2[20];
jmitc91516 1:a5258871b33d 224 char date2[20];
jmitc91516 1:a5258871b33d 225 char month2[20];
jmitc91516 1:a5258871b33d 226 char year2[20];
jmitc91516 1:a5258871b33d 227 if(!GetTimeFieldsFromGC(usbDevice, usbHostGC, seconds2, minutes2, hours2, date2, month2, year2)) {
jmitc91516 1:a5258871b33d 228 return false;
jmitc91516 1:a5258871b33d 229 }
jmitc91516 1:a5258871b33d 230
jmitc91516 1:a5258871b33d 231
jmitc91516 1:a5258871b33d 232 struct tm time1;
jmitc91516 1:a5258871b33d 233 MakeTimeValueFromGCTimeFields(&time1, seconds1, minutes1, hours1, date1, month1, year1);
jmitc91516 1:a5258871b33d 234
jmitc91516 1:a5258871b33d 235 time_t time_t1 = mktime(&time1);
jmitc91516 1:a5258871b33d 236
jmitc91516 1:a5258871b33d 237
jmitc91516 1:a5258871b33d 238 struct tm time2;
jmitc91516 1:a5258871b33d 239 MakeTimeValueFromGCTimeFields(&time2, seconds2, minutes2, hours2, date2, month2, year2);
jmitc91516 1:a5258871b33d 240
jmitc91516 1:a5258871b33d 241 time_t time_t2 = mktime(&time2);
jmitc91516 1:a5258871b33d 242
jmitc91516 1:a5258871b33d 243
jmitc91516 1:a5258871b33d 244 // time_t1 should be less than time_t2, since we obtained the values from which we calculated it (slightly) earlier.
jmitc91516 1:a5258871b33d 245 // If so, use time_t1. If not, assume one or more of time_t1's constituent values must have been affected by rollover,
jmitc91516 1:a5258871b33d 246 // and use time_t2. (Note that if time_t2 was affected by rollover, its value will (even more) be greater than time_t1,
jmitc91516 1:a5258871b33d 247 // so we will ignore it anyway.)
jmitc91516 1:a5258871b33d 248
jmitc91516 1:a5258871b33d 249 *clockTime = (time_t1 < time_t2) ? time_t1 : time_t2;
jmitc91516 1:a5258871b33d 250
jmitc91516 1:a5258871b33d 251 return true;
jmitc91516 1:a5258871b33d 252 }
jmitc91516 1:a5258871b33d 253
jmitc91516 1:a5258871b33d 254
jmitc91516 1:a5258871b33d 255 /*
jmitc91516 1:a5258871b33d 256 Get the time and date from the GC's real time clock,
jmitc91516 1:a5258871b33d 257 and set the LPC4088 RTC to match.
jmitc91516 1:a5258871b33d 258
jmitc91516 1:a5258871b33d 259 Args: a pointer to the USBHostGC instance that corresponds to the GC,
jmitc91516 1:a5258871b33d 260 a pointer to the USBDeviceConnected instance that (also) corresponds to the GC
jmitc91516 1:a5258871b33d 261
jmitc91516 1:a5258871b33d 262 Returns true if it succeeded, false if it failed (e.g. the GC gave an error, etc)
jmitc91516 1:a5258871b33d 263 */
jmitc91516 1:a5258871b33d 264 bool GCRealTimeClock::SetLPC4088RealTimeClockToMatchGC(USBDeviceConnected* usbDevice, USBHostGC* usbHostGC)
jmitc91516 1:a5258871b33d 265 {
jmitc91516 1:a5258871b33d 266 time_t timeToSet;
jmitc91516 1:a5258871b33d 267
jmitc91516 1:a5258871b33d 268 if(GetGCClockTime(usbDevice, usbHostGC, &timeToSet)) {
jmitc91516 1:a5258871b33d 269
jmitc91516 1:a5258871b33d 270 set_time(timeToSet);
jmitc91516 1:a5258871b33d 271
jmitc91516 1:a5258871b33d 272 return true;
jmitc91516 1:a5258871b33d 273 }
jmitc91516 1:a5258871b33d 274
jmitc91516 1:a5258871b33d 275 // 'else' ...
jmitc91516 1:a5258871b33d 276 return false;
jmitc91516 1:a5258871b33d 277 }
jmitc91516 1:a5258871b33d 278