MAXREFDES70# Code Documentation  V02.00
High-precision long battery life heat/flow meter
 All Data Structures Files Functions Variables Enumerator Macros Pages
MAXREFDES70.c
Go to the documentation of this file.
1 
62 //Micro Specific Include Files
63 #include "em_device.h"
64 #include "em_chip.h"
65 #include "em_cmu.h"
66 #include "em_emu.h"
67 #include "em_gpio.h"
68 
69 //Standard library call Include Files
70 #include <stdio.h>
71 #include <stdlib.h>
72 #include <time.h>
73 #include <stdbool.h>
74 
75 #include "lookUpTables.h"
76 #include "dogm163.h"
77 
78 /*******************************Opcode and Register Definition*********************************/
79 //MAX35101 Opcode Defines
80 #define TOF_UP 0x00
81 #define TOF_DOWN 0x01
82 #define TOF_DIFF 0x02
83 #define TEMPERATURE 0x03
84 #define RESET 0x04
85 #define INITIALIZE 0x05
86 #define TRANSFER_TO_FLASH 0x06
87 #define EVTMG1 0x07
88 #define EVTMG2 0x08
89 #define EVTMG3 0x09
90 #define HALT 0x0a
91 #define LDO_TIMED 0x0b
92 #define LDO_ON 0x0c
93 #define LDO_OFF 0x0d
94 #define CALIBRATES 0x0e
95 #define READ_FLASH 0x90
96 #define WRITE_FLASH 0x10
97 #define BLOCK_ERASE_FLASH 0x13
98 
99 //MAX35101 Register Memory Map Base Address
100 //(Write Opcode Values, Read routines will set the MSBit to get correct read opcode value)
101 #define SECONDS 0x30
102 #define MINS_HRS 0x31
103 #define DAY_DATE 0x32
104 #define MONTH_YEAR 0x33
105 #define INTERRUPT_STATUS 0xFE
106 #define T1_REG 0xE7
107 #define T2_REG 0xE9
108 #define T3_REG 0xEB
109 #define T4_REG 0xED
110 #define T1_AVG 0xF0
111 #define T2_AVG 0xF2
112 #define T3_AVG 0xF4
113 #define T4_AVG 0xF6
114 #define HIT1UP_REG 0xC5
115 #define HIT2UP_REG 0xC7
116 #define HIT3UP_REG 0xC9
117 #define HIT4UP_REG 0xCB
118 #define HIT5UP_REG 0xCD
119 #define HIT6UP_REG 0xCF
120 #define AVGUP_REG 0xD1
121 #define HIT1DOWN_REG 0xD4
122 #define HIT2DOWN_REG 0xD6
123 #define HIT3DOWN_REG 0xD8
124 #define HIT4DOWN_REG 0xDA
125 #define HIT5DOWN_REG 0xDC
126 #define HIT6DOWN_REG 0xDE
127 #define AVGDOWN_REG 0xE0
128 #define TOF_DIFF_REG 0xE2
129 #define TOF_DIFF_AVG_REG 0xE5
130 
131 //MAX35101 Bit weighting definition for interrupt status Register
132 #define INTERRUPT_REG_TO 0x8000
133 #define INTERRUPT_REG_TOF 0x1000
134 #define INTERRUPT_REG_TE 0x0800
135 #define INTERRUPT_REG_TOF_EVTMG 0x0200
136 #define INTERRUPT_REG_TEMP_EVTMG 0x0100
137 #define INTERRUPT_REG_TOF_FLASH 0x0080
138 /*******************************END - Opcode and Register Definition*********************************/
139 
140 
141 //Use 3 temperature ports, identify the hot inlet as T1, cold as T2, reference as T3 (Reading the ports from MAX35101)
142 #define NUMBER_TEMPERATUE_PORTS_USED 3
143 #define HOT_TEMP_PORT 0
144 #define COLD_TEMP_PORT 1
145 #define REFERENCE_TEMP_PORT 2
146 /*******************************Data Structure Definitions*********************************/
147 /*Temperature port, all temperature ports, hit data, flow data, energy data, Point-in-Time data, */
148 
149 #define USING_EVENT_TIMING_MODES_READ_AVERAGE
150 
151 //A Temperature results structure, containing raw data, and actually calculated temp (Relevant if its an inlet of outlet RTD)
152 typedef struct {
153  uint32_t Register_Value;
156 
157 //An array of temperature ports, Inlet RTD, outlet RTD, and reference. All temperature data
158 typedef struct {
161 
162 //Hit data and ratio data for TOF
163 typedef struct {
164  uint32_t Hit1Data;
165  uint32_t Hit2Data;
166  uint32_t Hit3Data;
167  uint32_t Hit4Data;
168  uint32_t Hit5Data;
169  uint32_t Hit6Data;
170  uint32_t HitAverageData;
171  char t1Ratiot2;
174 
175 
176 typedef struct{
177  struct tm Time;
178  uint32_t milliSeconds;
179 }tm_withMilli;
180 
181 typedef struct {
182 
183 #ifndef USING_EVENT_TIMING_MODES_READ_AVERAGE
184  Hit_ResultsStruct HitDownData;
185  Hit_ResultsStruct HitUpData;
186 #endif
187  int32_t TOF_DiffData;
194 
195 typedef struct {
201 
202 typedef struct { //POT is a Point in Time
208 
209 
210 
211 /* Display Mode */
212  enum {
226 } ;
227  /******************************* END - Data Structure Definitions*********************************/
228 
229 
230  /******************************* Some GLOBAL variables, and Function Definitions*********************************/
231  //Global Generic Defines
232 #define T4MHZ (float)250/(float)1000000000 //Assume Ideal 250nS t4MHz period
233 #define LSBIT_TOF_VALUE (1/(float)65536) * T4MHZ //Fractional portion of a TOF measurement is quantized to a 16 bit value of the 4MHz Clock
234 #ifndef PI
235 #define PI 3.14 //Make sure this is defines somewhere
236 #endif
237 #define SECONDS_PER_HR 3600
238 
239  //Global Variables
240 TemperatureResultsAllPortsStruct Last_TempUpdate; //The Most Recent temperature measurement, stored here since temperature updates and tof updates occur at different rates
241 static volatile uint32_t msTicks; /* counts 1ms timeTicks */
242 
243 //#define NUMBER_OF_POTS_BEFORE_CALCULATION 4 //Number of data points to collect before doing the piecewise integration, giving the resulting energy consumption
244 //PointOfTimeSampleDataStruct POT_Data[NUMBER_OF_POTS_BEFORE_CALCULATION + 1]; //Actual array of datapoints
245 //PointOfTimeSampleDataStruct POT_Data_WrapAround; //Must keep last point of previous accumulation to use as first point of the next accumulation etc.
246 PointOfTimeSampleDataStruct POT_Data[1]; //Actual array of datapoints
248 int POTCount = 0; //Tracker
249 float TotalEnergy = 0; //TOTAL ENERGY is STORED HERE //todo: customer must save/transmit this data at their defined rate, resetting the variable for continual accumulations
250 float TotalVolume_m3 = 0;
251 int POR = 0; //Flag keeping track of a power on reset
252 uint16_t TDF, TDM, TMF, TMM; //current working TDF, TDM, TMF, TMM values.
253 uint16_t reg = 0;
254 char output[49]; // Characters to display on LCD screen
255 
256 uint8_t DisplayMode = Display_Off; //What mode is the screen displaying
257 uint8_t previousDisplayMode = Display_Off; //What mode was the screen displaying previously
259 #define MAX_DISPLAY_REPEAT 9000 //without pressing SW2, LCD keeps on for 1 hour and then turns off.
260 bool displayPowerOff = true;
261 bool EVT_STARTED = false;
262 uint32_t delayCount = 0;
263 
264 void Display(void);
265 void MAX35101_SetTime(void);
266 
267 
268 //Usable Calculation routines
269 bool Calcuate_Temperature(uint32_t tempRegisterData, uint32_t RefRegisterData, float* TempDestination);
270 bool Calculate_TOF_Velocity(int32_t TOF_DiffData, float* FlowVelocity, float Temperature, float* TOF_DIFF_DeltaT_S);
271 void Calculate_TimeDifference( tm_withMilli* t1, tm_withMilli* t2, float* difference_sec);
272 bool Calculate_Volumetric_Flow( float Velocity_mPerS, float* VolumetricFlow_m3PerS, float* VolumetricGainfactor, float*VolumetricFlowCorrected_m3PerS);
273 bool Calculate_Mass_Flow(float VolumetricFlow_m3PerS, float* MassFlow_kgPerHr, float Temperature);
274 bool Calculate_Enthalpy(float TemperatureAtCold, float TemperatureAtHot, float* EnthalpyAtCold_JperKg, float* EnthalpyAtHot_JperKg, float* DeltaEnthalpy_JperKg);
277 
278 //Usable MAX35101 communication routines
279 bool MAX35101_Send_Opcode(char opcode);
280 bool MAX35101_Read_Register(char address, uint16_t* results);
281 bool MAX35101_Read_2WordValue(char startingAddress, uint32_t* results);
282 bool MAX35101_Update_TOF_DIFFData(Flow_ResultsStruct* TOF_DIFF_Results);
283 bool MAX35101_UpdateAndGetTime(tm_withMilli* RTCTimeStamp);
285 bool MAX35101_Write_Register(char address, uint16_t DatatoWrite);
287 
288 //usable generic routines
289 float LinearInterpolation (float X1Low, float X2High, float Y1Low, float Y2High, float XnewLookup);
290 
291 // Format a floating number to a string.
292 // Newlib-nano formatted printing and parsing of floating number requires large code footprint.
293 // Not enough space with 32k flash available on the device.
294 int FloatToString (float fNumber, uint8_t precision, char* output);
295 
296 //Micro specific block communication setup routines
297 //todo: rewrite the specific functions for the mirco of use
298 extern void Delay(uint32_t dlyTicks);
299 static void SPI_setup(uint8_t spiNumber, uint8_t location, bool master);
300 void init(void);
301 
302 static void GpioSetup(void);
303 
304 bool SPI_Send_Byte(char dataByte);
305 bool SPI_Read_Word(uint16_t* results);
306 bool MAX35101_SendConfigs(void); //Generic writing all data registers
307 #define MAX35101_CS_Low() GPIO_PinOutClear(gpioPortB, 8)
308 #define MAX35101_CS_High() GPIO_PinOutSet(gpioPortB, 8)
309 
310 /******************************* END - Some GLOBAL variables, and Function Definitions*********************************/
311 
312 
313 /******************************* Meter Calculation routines*********************************/
314 #define RTD_RREF_VALUE 1000
315 bool Calcuate_Temperature(uint32_t tempRegisterData, uint32_t RefRegisterData, float* TempDestination)
316 {
317  float RTDtoRREF_Ratio, RTDResistanceValue_ohms;
318  int XCord, YCord;
319  bool success = false;
320 
321  RTDtoRREF_Ratio = (float) tempRegisterData / (float) RefRegisterData;//Time for RTD#/RREF
322  RTDResistanceValue_ohms = RTDtoRREF_Ratio * RTD_RREF_VALUE;//Ration time RREF = resistance of the RTD#
323 
324  //Find the X coordinate in the lookup table by fixing the T to zero: X coordinate is whole degrees C
325  for (XCord = 0; ((PT1000_LOOKUPTABLE[XCord][0] < RTDResistanceValue_ohms) && (XCord < 101)); XCord++) //Start at 0 Degree C, a deference lookup table is resistance of RTD (ohms)
326  {;} //Purely searching for the index
327  XCord--; //we stopped when the Resistance of a whole degree was greater than what we wanted, decrement the whole degree and search for the Y
328  //Find the Y coordinate in the lookup table by fixing the X to the found value: Y coordinate is 0.1 Degrees C
329  for (YCord = 0; ((PT1000_LOOKUPTABLE[XCord][YCord] < RTDResistanceValue_ohms) && (YCord < 10)); YCord++) //Start at 0 Degree C, a deference lookup table is resistance of RTD (ohms)
330  {;}//Purely searching for the index
331  YCord--; //we stopped when the Resistance of a 0.1 degree was greater than what we wanted, decrement
332 
333  *TempDestination = LinearInterpolation
334  (
335  PT1000_LOOKUPTABLE[XCord][YCord], //X1 - //Index was past
336  PT1000_LOOKUPTABLE[XCord][YCord + 1], //X2
337  (XCord + (YCord * 0.1)), //Y1 //index into LUT is degree and .1 degree
338  (XCord + (YCord + 1) * 0.1), //Y2 //Add whole to decimal portion and the interpolated value to the .1 then thats the TEMP
339  RTDResistanceValue_ohms //New X of interest
340  );//Returns new Y
341  return success;
342 }
343 
344 
345 #define PIPELENGTH_IN_FLOW_M 0.0717 //todo: DN20 or DN25 - Specifications - update to spool body
346 bool Calculate_Flow_Parameters(Flow_ResultsStruct* TOF_DIFF_ResultsToUse, TemperatureResultsAllPortsStruct* TemperatureResultsToUse)
347 {
348  bool success = false;
350  TOF_DIFF_ResultsToUse->TOF_DiffData,
351  &TOF_DIFF_ResultsToUse->FlowVelocity_mPerS,
352  TemperatureResultsToUse->TempResultsAllPorts[HOT_TEMP_PORT].TemperatureDegreeC,
353  &TOF_DIFF_ResultsToUse->TOF_DIFF_DeltaT_S
354  );
355  Calculate_Volumetric_Flow(TOF_DIFF_ResultsToUse->FlowVelocity_mPerS, &TOF_DIFF_ResultsToUse->VolumetricFlow_m3PerS, &TOF_DIFF_ResultsToUse->VolumetricFlowGainFactor, &TOF_DIFF_ResultsToUse->VolumetricFlowCorrected_m3PerS);
356  return success;
357 }
358 
359 bool Calculate_TOF_Velocity(int32_t TOF_DiffData, float* FlowVelocity, float Temperature, float* TOF_DIFF_DeltaT_S)
360 {
361  bool success = false;
362  float SpeedOfSound_mperS, VelocityCalcNumerator_m2perS, VelocityCalcDenominatore_m, Velocity_mPers = 0;
363  int TempAtJunncture = (int) Temperature;
364  //Current table is mapped with degrees C, just insert whole degree and read out velocity (speed of sound m/S)
365  SpeedOfSound_mperS = LinearInterpolation
366  (
367  TempAtJunncture, //X1
368  TempAtJunncture + 1, //X2 (increment of 1 is next lookup value +1C)
369  (float)SPEED_OF_SOUND_LOOKUP[TempAtJunncture], //Y1
370  (float)SPEED_OF_SOUND_LOOKUP[TempAtJunncture + 1], //Y2
371  Temperature //New X of interest
372  );//Returns new Y
373  //Calculate the TOF Differential (Delta t) time in seconds. TODO:Is seconds best?
374  *TOF_DIFF_DeltaT_S = (float) TOF_DiffData * LSBIT_TOF_VALUE;
375  //velocity calculation numerator (Detlat * Co^2)
376  VelocityCalcNumerator_m2perS = *TOF_DIFF_DeltaT_S * SpeedOfSound_mperS* SpeedOfSound_mperS;
377  //Velocity calculation denominator is 2 * Length of path in flow
378  VelocityCalcDenominatore_m = 2 * PIPELENGTH_IN_FLOW_M;
379  Velocity_mPers = VelocityCalcNumerator_m2perS / VelocityCalcDenominatore_m; //final divsion
380  *FlowVelocity = Velocity_mPers;
381  return success;
382 }
383 
384 #define PIPERADIUS_M 0.008
385 bool Calculate_Volumetric_Flow( float Velocity_mPerS, float* VolumetricFlow_m3PerS, float* VolumetricGainfactor, float*VolumetricFlowCorrected_m3PerS)
386 {
387  bool success = false;
388  int XCord;
389  float CrossSectionalArea_m2;
390  //determine cross sectional area (PI*R*R)
391  CrossSectionalArea_m2 = PI * PIPERADIUS_M * PIPERADIUS_M;
392 
393  //Determine volumetric flow for a given velocity ( Q = V * A )
394  *VolumetricFlow_m3PerS = Velocity_mPerS * CrossSectionalArea_m2;
395 
396  //Find the Volumetric Flow Adjustment Gain Coefficient from the lookup Table
397  //Find the X coordinate in the lookup table. XCord is the Meter Volumetric Flow Reading
398  for (XCord = 0; ((VOLUMETRIC_FLOW_CORRECTION_TABLE[XCord][0] < *VolumetricFlow_m3PerS * SECONDS_PER_HR) ); XCord++)
399  {;}//Purely searching for the index
400 
401  *VolumetricGainfactor = LinearInterpolation
402  (
403  VOLUMETRIC_FLOW_CORRECTION_TABLE[XCord-1][0], //X1 - //Index was past
404  VOLUMETRIC_FLOW_CORRECTION_TABLE[XCord][0], //X2
405  VOLUMETRIC_FLOW_CORRECTION_TABLE[XCord-1][1], //Y1 //A de-referenced lookup table item is gain correction (unitless)
406  VOLUMETRIC_FLOW_CORRECTION_TABLE[XCord][1], //Y2
407  (*VolumetricFlow_m3PerS * SECONDS_PER_HR) //New X of interest
408  );//Returns new Y
409 
410  *VolumetricFlowCorrected_m3PerS = (*VolumetricGainfactor) * (*VolumetricFlow_m3PerS);
411  return success;
412 }
413 
414 
415 //todo: customer define their nominal 0C Platinum RTD resistance (PT1k = 1000 ohms)
416  //todo:The radius of the pipe used to determine cross sectional area (PI*R*R) - update to spool body
417 bool Calculate_Energy_Parameters(Flow_ResultsStruct* TOF_DIFF_ResultsToUse, TemperatureResultsAllPortsStruct* TemperatureResultsToUse, Energy_ResultsStruct* EnergyToUse)
418 {
419  bool success = false;
421  TOF_DIFF_ResultsToUse->VolumetricFlowCorrected_m3PerS,
422  &EnergyToUse->MassFlow_kgPerh,
423  TemperatureResultsToUse->TempResultsAllPorts[HOT_TEMP_PORT].TemperatureDegreeC
424  );
426  TemperatureResultsToUse->TempResultsAllPorts[COLD_TEMP_PORT].TemperatureDegreeC,
427  TemperatureResultsToUse->TempResultsAllPorts[HOT_TEMP_PORT].TemperatureDegreeC,
428  &EnergyToUse->EnthalpyAtCold_JperKg,
429  &EnergyToUse->EnthalpyAtHot_JperKg,
430  &EnergyToUse->EnthalpyDelta_JperKg
431  );
432  return success;
433 }
434 
435 //Mass flow of the water flowing across the heat meter (kg/3)
436 bool Calculate_Mass_Flow(float VolumetricFlowCorrected_m3PerS, float* MassFlow_kgPerHr, float Temperature)
437 {
438  bool success = false;
439  float WaterDensityatTemp_kgPerm3, VolumetricFlowCorrected_m3PerH;
440  int TempAtJunncture = (int)(Temperature); //Get the temperature of the water where the TOF measurement was taken, Truncate
441  WaterDensityatTemp_kgPerm3 = LinearInterpolation //Current table is mapped with degrees C, just insert whole degree and read out density
442  (
443  TempAtJunncture, //X1
444  TempAtJunncture + 1, //X2
445  WATER_DENSITY_LOOKUPTABLE[TempAtJunncture], //Y1 //A de-referenced lookup table item is density kg/m3
446  WATER_DENSITY_LOOKUPTABLE[TempAtJunncture + 1], //Y2
447  Temperature //New X of interest
448  );//Returns new Y
449  //Determine Mass flow for a given volumetric flow rate and Density
450  VolumetricFlowCorrected_m3PerH = VolumetricFlowCorrected_m3PerS * SECONDS_PER_HR;
451  *MassFlow_kgPerHr = VolumetricFlowCorrected_m3PerH * WaterDensityatTemp_kgPerm3;
452  return success;
453 }
454 
455 bool Calculate_Enthalpy(float TemperatureAtCold, float TemperatureAtHot, float* EnthalpyAtCold_JperKg, float* EnthalpyAtHot_JperKg, float* DeltaEnthalpy_JperKg)
456 {
457  bool success = false;
458  int TempAtJunncture = (int)(TemperatureAtCold); //Get the temperature of the water where the TOF measurement was taken, Truncate
459  *EnthalpyAtCold_JperKg = LinearInterpolation
460  (
461  TempAtJunncture, //X1
462  TempAtJunncture + 1, //X2 (increment of 1 is next lookup value +1C)
463  WATER_ENTHALPY_LOOKUPTABLE[TempAtJunncture], //Y1 //A de-referenced lookup table item is enthalpy j/kg
464  WATER_ENTHALPY_LOOKUPTABLE[TempAtJunncture + 1], //Y2
465  TemperatureAtCold //New X of interest
466  );//Returns new Y
467 
468  TempAtJunncture = (int)(TemperatureAtHot); //Get the temperature of the water where the TOF measurement was taken, Truncate
469  *EnthalpyAtHot_JperKg = LinearInterpolation
470  (
471  TempAtJunncture, //X1
472  TempAtJunncture + 1, //X2 (increment of 1 is next lookup value +1C)
473  WATER_ENTHALPY_LOOKUPTABLE[TempAtJunncture], //Y1 //A de-referenced lookup table item is enthalpy j/kg
474  WATER_ENTHALPY_LOOKUPTABLE[TempAtJunncture + 1], //Y2
475  TemperatureAtHot //New X of interest
476  );//Returns new Y
477  //Calculate the The delta Enthalpy in J/Kg
478  *DeltaEnthalpy_JperKg = *EnthalpyAtHot_JperKg - *EnthalpyAtCold_JperKg;
479  return success;
480 }
481 
482 void Calculate_TimeDifference( tm_withMilli* t1, tm_withMilli* t2, float* difference_sec)
483 {
484  time_t t_t1, t_t2;
485  float milliSecAdd = 0;
486 
487  t_t1 = mktime(&t1->Time);
488  t_t2 = mktime(&t2->Time);
489  *difference_sec = (float) difftime (t_t2,t_t1 ); //todo change to double
490 
491  if( t2->milliSeconds > t1->milliSeconds)
492  milliSecAdd = t2->milliSeconds - t1->milliSeconds;
493  else
494  {
495  milliSecAdd = (1000 + t2->milliSeconds) - t1->milliSeconds;
496  *difference_sec = *difference_sec - 1; //there must be atlease a one second difference if t2
497  }
498 
499  *difference_sec = *difference_sec + (milliSecAdd/1000);
500 }
501 
505 {
506  bool success = false;
507  float TimeDifference_sec = 0;
508 
509  Calculate_TimeDifference(&POT1->POT_TimeData, &POT2->POT_TimeData, &TimeDifference_sec);
511 // energyAddition[energyAdditionsTracker++] = energyAddition1;
512  *EnergyForTime_J += energyAddition1;
513  return success;
514 }
515 
519 {
520  bool success = false;
521  float TimeDifference_sec = 0;
522 
523  Calculate_TimeDifference(&POT1->POT_TimeData, &POT2->POT_TimeData, &TimeDifference_sec);
525  //volumeAddition[volueAdditionsTracker++] = volumeAddition1;
526  *Volume_m3 += volumeAddition1;
527  return success;
528 }
529 
530 
531 //generic interpolation routine
532 float LinearInterpolation (float X1Low, float X2High, float Y1Low, float Y2High, float XnewLookup)
533 {
534  float XnewLookupRatio, Xrange, Yrange, YReturnLookupValue;
535  Xrange = (X2High-X1Low);
536  Yrange = (Y2High-Y1Low);
537  XnewLookupRatio = (XnewLookup - X1Low)/ Xrange;
538  YReturnLookupValue = Y1Low + Yrange*XnewLookupRatio;
539  return (YReturnLookupValue);
540 }
541 
542 
543 int FloatToString (float fNumber, uint8_t precision, char* output)
544 {
545  int base = 1;
546  int length1 = 0, length2 = 0;
547  for (int loop = 0; loop < precision; loop++)
548  base *= 10;
549  fNumber > 0? (fNumber += (0.5/base)) : (fNumber -= (0.5/base));
550 
551  length1 = snprintf(output, 16, "%d", (int)fNumber);
552 
553  if(precision <= 0)
554  return length1;
555  else
556  {
557  fNumber > 0? (fNumber = fNumber - (int)fNumber) : (fNumber = (int)fNumber - fNumber);
558  fNumber *= base;
559 
560  output[length1] = '.';
561  length2 = snprintf(&output[length1+1], 16, "%0*d", precision, (int)fNumber);
562 
563  return length1 + length2 + 1;
564 
565  }
566 }
567 
568 /******************************* END - Meter Calculation routines*********************************/
569 
570 
571 /******************************* MAX35101 Getting results data from MAX35101 *********************************/
573 {
574  bool success = false;
575 
576  //Update Temp Structure RREF
577  success |=
579  &TempResultsToUpdate->TempResultsAllPorts[REFERENCE_TEMP_PORT].Register_Value); //Read the interrupt register
580 
581  //Update Temp Structure1
582  success |=
584  &TempResultsToUpdate->TempResultsAllPorts[HOT_TEMP_PORT].Register_Value);//Read the interrupt register
586  TempResultsToUpdate->TempResultsAllPorts[HOT_TEMP_PORT].Register_Value,
588  &TempResultsToUpdate->TempResultsAllPorts[HOT_TEMP_PORT].TemperatureDegreeC);
589 
590  //Update Temp Structure2
591  success |=
593  &TempResultsToUpdate->TempResultsAllPorts[COLD_TEMP_PORT].Register_Value);//Read the interrupt register
595  TempResultsToUpdate->TempResultsAllPorts[COLD_TEMP_PORT].Register_Value,
597  &TempResultsToUpdate->TempResultsAllPorts[COLD_TEMP_PORT].TemperatureDegreeC);
598 
599  return success;
600 }
601 
602 
604 {
605  bool success = false;
606  //Update TOF Diff Average (This is what to read out in Event Timing mode)
607  success |= MAX35101_Read_2WordValue(TOF_DIFF_AVG_REG, &TOF_DIFF_Results->TOF_DiffData);
608 
609  return success;
610 }
611 
613 {
614  bool success = false;
615 
616 #ifndef USING_EVENT_TIMING_MODES_READ_AVERAGE
617  //Update TOF Down
619  &TOF_DIFF_Results->HitDownData.Hit1Data);
621  &TOF_DIFF_Results->HitDownData.Hit2Data);
623  &TOF_DIFF_Results->HitDownData.Hit3Data);
625  &TOF_DIFF_Results->HitDownData.Hit4Data);
627  &TOF_DIFF_Results->HitDownData.Hit5Data);
629  &TOF_DIFF_Results->HitDownData.Hit6Data);
631  &TOF_DIFF_Results->HitDownData.Hit6Data);
633  &TOF_DIFF_Results->HitDownData.HitAverageData);
634 
635  //Update TOF Up
637  &TOF_DIFF_Results->HitUpData.Hit1Data);
639  &TOF_DIFF_Results->HitUpData.Hit2Data);
641  &TOF_DIFF_Results->HitUpData.Hit3Data);
643  &TOF_DIFF_Results->HitUpData.Hit4Data);
645  &TOF_DIFF_Results->HitUpData.Hit5Data);
647  &TOF_DIFF_Results->HitUpData.Hit6Data);
649  &TOF_DIFF_Results->HitUpData.HitAverageData);
650 
651  //Update TOF Diff
652  success |= MAX35101_Read_2WordValue(TOF_DIFF_REG, &TOF_DIFF_Results->TOF_DiffData);
653 #else
654  //Update TOF Diff
655  success |= MAX35101_Read_2WordValue(TOF_DIFF_REG, &TOF_DIFF_Results->TOF_DiffData);
656 #endif
657 
658  return success;
659 }
660 
661 //Read the RTC values from the MAX35101 and updat a time data structure pointed to by the funtion call pass parameter
663  bool success = false;
664  uint16_t readData = 0;
665 
666  success = MAX35101_Read_Register(SECONDS, &readData);
667  RTCTimeStamp->Time.tm_sec = ((((readData & 0x00F0) >> 4 ) * 10) + (readData & 0x000F));
668  RTCTimeStamp->milliSeconds = ((((readData & 0xF000) >> 12 ) * 100) + ((readData & 0x0F00)>>8) *10 );
669 
670  success |= MAX35101_Read_Register(MINS_HRS, &readData);
671  RTCTimeStamp->Time.tm_min = ((( readData & 0xF000) >> 12) * 10) + ((readData & 0x0F00) >> 8);
672  //RTCTimeStamp->Time.tm_hour= (((( readData & 0x0030) >> 4) * 20) + ((readData & 0x0008) >> 3) * 10) + (readData & 0x0007);
673  RTCTimeStamp->Time.tm_hour= ((( readData & 0x0030) >> 4) * 10) + (readData & 0x000F);
674 
675  success |= MAX35101_Read_Register(DAY_DATE, &readData);
676  RTCTimeStamp->Time.tm_mday = ((((readData & 0x0030) >> 4 ) * 10) + (readData & 0x000F));
677 
678  success |= MAX35101_Read_Register(MONTH_YEAR, &readData);
679  RTCTimeStamp->Time.tm_mon = ((( readData & 0x1000) >> 12) * 10) + ((readData & 0x0F00) >> 8);
680  RTCTimeStamp->Time.tm_year = ((((readData & 0x00F0) >> 4 ) * 10) + (readData & 0x000F)) + 100; //tm_year is years since 1900
681 
682  return success;
683 }
684 
686 {
688  Delay(1); //Blind Wait LDO stabilize
689  return true;
690 }
691 
693 {
695  return true;
696 }
697 
698 bool MAX35101_Write_Flash(uint16_t StartingFlashAddress, uint16_t WriteLength, uint16_t* DataToWrite)
699 {
700  bool success;
701  int i;
702  uint16_t FlashAddressToWrite;
703 
705  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
706  NVIC_DisableIRQ(GPIO_ODD_IRQn);
707  for ( i = 0; i < WriteLength; i++ )
708  {
709  FlashAddressToWrite = StartingFlashAddress + (2*i); //Need to increment the address since it is only 1 word writing capability
710  MAX35101_CS_Low(); //Modulate CS#
711  success = SPI_Send_Byte(WRITE_FLASH); //Transmit the write flash command code
712  success = SPI_Send_Byte((char) (FlashAddressToWrite >> 8)); //Transmit the Flash Address (MUST be Even)
713  success = SPI_Send_Byte((char) (FlashAddressToWrite & 0x00FF)); //Transmit the 8 bits
714  success = SPI_Send_Byte((char) (( *(DataToWrite + i) ) >> 8)); //Transmit the Data
715  success = SPI_Send_Byte((char) (( *(DataToWrite + i) & 0x00FF))); //Transmit the 8 bits
716  MAX35101_CS_High(); //Modulate CS#
717  Delay (1); //Blind 1 ms delay for word write time
718  }
719  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
720  NVIC_EnableIRQ(GPIO_ODD_IRQn);
721 
723  return success;
724 }
725 
726 bool MAX35101_Read_Flash(uint16_t FlashAddress, uint16_t ReadLength, uint16_t* DataToRead)
727 {
728  bool success;
729  int i;
730 
732  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
733  NVIC_DisableIRQ(GPIO_ODD_IRQn);
734  MAX35101_CS_Low(); //Modulate CS#
735  success = SPI_Send_Byte(READ_FLASH); //Transmit the read flash command code
736  success = SPI_Send_Byte((char) (FlashAddress >> 8)); //Transmit the Flash Address (MUST be Even)
737  success = SPI_Send_Byte((char) (FlashAddress & 0x00FF)); //Transmit the 8 bits
738  for ( i = 0; i < ReadLength; i++ )
739  {
740  success = SPI_Read_Word( (DataToRead + i) ); //Read
741  }
742  MAX35101_CS_High(); //Modulate CS#
743  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
744  NVIC_EnableIRQ(GPIO_ODD_IRQn);
746  return success;
747 }
748 
749 bool MAX35101_BlockErase_Flash(uint16_t AddressBlock)
750 {
751  bool success;
753  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
754  NVIC_DisableIRQ(GPIO_ODD_IRQn);
755  MAX35101_CS_Low(); //Modulate CS#
756  success = SPI_Send_Byte(BLOCK_ERASE_FLASH); //Transmit the read Block Erase command code
757  success = SPI_Send_Byte((char) (AddressBlock >> 8)); //Transmit the Block Address
758  success = SPI_Send_Byte((char) (AddressBlock & 0x00FF)); //Transmit the 8 bits
759  MAX35101_CS_High(); //Modulate CS#
760  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
761  NVIC_EnableIRQ(GPIO_ODD_IRQn);
762  Delay(60);
764 
765  return success;
766 }
767 /******************************* END - MAX35101 Getting results data from MAX35101 *********************************/
768 uint32_t flags;
769 // GPIO Interrupt handler
771 {
772  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
773  NVIC_DisableIRQ(GPIO_ODD_IRQn);
774  // Get interrupts flags.
775  flags = GPIO_IntGet();
776 
777  if(flags & (1<< 7)) // SW4 is pressed
778  {
779  //todo: implement factory date/time settings, work together with SW3.
780  GPIO_IntClear(1 << 7);
781  }
782  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
783  NVIC_EnableIRQ(GPIO_ODD_IRQn);
784 }
785 
786 // GPIO Interrupt handler
787 // System will be in micro deep sleep with the MAX35101 running an infinite event timing mode
788 // Upon temperature completion of a EVTMG sequence or TOF sequence completion the INT#
789 // pin of the MAX35101 becomes active and the data must be read by my micro
791 
793 {
794  uint8_t pinState = 0;
795  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
796  NVIC_DisableIRQ(GPIO_ODD_IRQn);
797  // Get interrupts flags.
798  flags = GPIO_IntGet();
799  // Process interrupts based on interrupt resources.
800  // SW2 is pressed, display information.
801  if(flags & (1 << 0))
802  {
803  delayCount = 0;
804  while(!GPIO_PinInGet(gpioPortA, 0))
805  delayCount += 1;
806 
807  if(delayCount < 3) // not a real press
808  ;
809  else if(delayCount < 1000000) // good, normal press
810  {
811  DisplayMode++;
812  displayRepeat = 0;
813  if (DisplayMode == Display_Last)
815  }
816  // long press in TDF, TDM, TMF, TMM modes means to change register.
817  //else if((DisplayMode == Display_TDF_Config) | (DisplayMode == Display_TDM_Config) | (DisplayMode == Display_TMF_Config) |(DisplayMode == Display_TMM_Config))
818 
819  else if(DisplayMode == Display_TDF_Config)
820  {
821  DOGM163_ClearChars(0, 0, 48);
822  DOGM163_PrintChars(0, 0, 16, "Change TDF[3:0]:");
823  FloatToString((TDF + 1)*0.5, 1, output);
824  DOGM163_PrintChars(1, 0, 16, output);
825  DOGM163_PrintChars(1, 9, 7, "Seconds");
826  DOGM163_PrintChars(2, 0, 16, "LongPress:Accept");
827 
828  while(1)
829  {
830  delayCount = 0;
831  while(!GPIO_PinInGet(gpioPortA, 0))
832  delayCount += 1;
833 
834  if(delayCount < 3) // not a real press
835  ;
836  else if(delayCount < 1000000) // good, normal press
837  {
838  if(TDF == 0x0F)
839  TDF = 0x00;
840  else
841  TDF++;
842  FloatToString((TDF + 1)*0.5, 1, output);
843  DOGM163_PrintChars(1, 0, 16, " "); // clear 3 digits for TDF.
844  DOGM163_PrintChars(1, 0, 16, output);
845  }
846  else // accept the value.
847  {
849  reg = (reg & 0x0FFF) | (TDF << 12);
851 
852  //DisplayMode++;
853  displayRepeat = 0;
854  break;
855  }
856  }
857  }
858 
859  else if(DisplayMode == Display_TDM_Config)
860  {
861  DOGM163_ClearChars(0, 0, 48);
862  DOGM163_PrintChars(0, 0, 16, "Change TDM[4:0]:");
863  snprintf(output, 16, "%d", TDM + 1);
864  DOGM163_PrintChars(1, 0, 16, output);
865  DOGM163_PrintChars(1, 10, 6, "Cycles");
866  DOGM163_PrintChars(2, 0, 16, "LongPress:Accept");
867 
868  while(1)
869  {
870  delayCount = 0;
871  while(!GPIO_PinInGet(gpioPortA, 0))
872  delayCount += 1;
873 
874  if(delayCount < 3) // not a real press
875  ;
876  else if(delayCount < 1000000) // good, normal press
877  {
878  if(TDM == 0x1F)
879  TDM = 0x00;
880  else
881  TDM++;
882  snprintf(output, 16, "%d", TDM + 1);
883  DOGM163_PrintChars(1, 0, 16, " "); //clear 2 digits for TDM.
884  DOGM163_PrintChars(1, 0, 16, output);
885  }
886  else // accept the value.
887  {
889  reg = (reg & 0xF07F) | (TDM << 7);
891 
892  //DisplayMode++;
893  displayRepeat = 0;
894  break;
895  }
896  }
897  }
898 
899  else if(DisplayMode == Display_TMF_Config)
900  {
901  DOGM163_ClearChars(0, 0, 48);
902  DOGM163_PrintChars(0, 0, 16, "Change TMF[5:0]:");
903  snprintf(output, 16, "%d", TMF + 1);
904  DOGM163_PrintChars(1, 0, 16, output);
905  DOGM163_PrintChars(1, 9, 7, "Seconds");
906  DOGM163_PrintChars(2, 0, 16, "LongPress:Accept");
907 
908  while(1)
909  {
910  delayCount = 0;
911  while(!GPIO_PinInGet(gpioPortA, 0))
912  delayCount += 1;
913 
914  if(delayCount < 3) // not a real press
915  ;
916  else if(delayCount < 1000000) // good, normal press
917  {
918  if(TMF == 0x3F)
919  TMF = 0x00;
920  else
921  TMF++;
922  snprintf(output, 16, "%d", TMF + 1);
923  DOGM163_PrintChars(1, 0, 16, " "); //clear 2 digits for TMF.
924  DOGM163_PrintChars(1, 0, 16, output);
925  }
926  else // accept the value.
927  {
929  reg = (reg & 0xFF80) | (TMF << 1);
931 
932  //DisplayMode++;
933  displayRepeat = 0;
934  break;
935  }
936  }
937  }
938 
939  else if(DisplayMode == Display_TMM_Config)
940  {
941  DOGM163_ClearChars(0, 0, 48);
942  DOGM163_PrintChars(0, 0, 16, "Change TMM[4:0]:");
943  snprintf(output, 16, "%d", TMM + 1);
944  DOGM163_PrintChars(1, 0, 16, output);
945  DOGM163_PrintChars(1, 10, 6, "Cycles");
946  DOGM163_PrintChars(2, 0, 16, "LongPress:Accept");
947 
948  while(1)
949  {
950  delayCount = 0;
951  while(!GPIO_PinInGet(gpioPortA, 0))
952  delayCount += 1;
953 
954  if(delayCount < 3) // not a real press
955  ;
956  else if(delayCount < 1000000) // good, normal press
957  {
958  if(TMM == 0x1F)
959  TMM = 0x00;
960  else
961  TMM++;
962  snprintf(output, 16, "%d", TMM + 1);
963  DOGM163_PrintChars(1, 0, 16, " "); //clear 2 digits for TMM.
964  DOGM163_PrintChars(1, 0, 16, output);
965  }
966  else // accept the value.
967  {
969  reg = (reg & 0x07FF) | (TMM << 11);
971 
972  //DisplayMode++;
973  displayRepeat = 0;
974  break;
975  }
976  }
977  }
978  else if((delayCount > 10000000) & !EVT_STARTED) // if not started, long press to activate the meter.
979  {
980  DOGM163_ClearChars(0, 0, 48);
981  DOGM163_PrintChars(0, 0, 16, "Activating");
982  DOGM163_PrintChars(1, 0, 16, "The");
983  DOGM163_PrintChars(2, 0, 16, "Meter...");
985  EVT_STARTED = true;
986  for(int loop=0; loop<10000000; loop++)
987  {
988  pinState = GPIO_PinInGet(gpioPortA, 0);
989  }
990  }
991  else // 1000,000 to 10,000,000, turn off the display
992  {
994  }
995 
996  GPIO_IntClear(1 << 0); // Acknowledge interrupt
997  }
998 
999  //Interrupt# Pin from MAX35101. Read the Interrupt Status Register and then read associated register data.
1000  else if(flags & (1 << 2))
1001  {
1003  if ((InterruptRegisterValue & INTERRUPT_REG_TO) != 0x00) //Timeout has occurred
1004  {
1005  // todo: timeout error handling.
1006  }
1007 
1008  // Temp Sequence is completed
1010  {
1011  //Get all the Temp data and update the Last Temp structure.
1012  MAX35101_Update_TemperatureData(&Last_TempUpdate);
1013  }
1014 
1015  // TOF Sequence is completed.
1017  {
1018  // Get all the TOF Data and update the Point-in-Time Snap shot.
1019  MAX35101_Update_TOF_AVG_DIFFData(&POT_Data[POTCount].POT_FlowFactors);
1020  // Get all the Time Data and update the Point-in-Time Snap shot.
1021  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1022  // Copy the most recent Temp Data into Point-in-time snap shots.
1024 
1025  // Do all the math calculations on the Raw Data found in the structures.
1026  Calculate_Flow_Parameters(&POT_Data[POTCount].POT_FlowFactors, &POT_Data[POTCount].POT_TemperatureData);
1027  Calculate_Energy_Parameters(&POT_Data[POTCount].POT_FlowFactors, &POT_Data[POTCount].POT_TemperatureData, &POT_Data[POTCount].POT_EnergyFactors);
1028  // Calculate volume for two given points in time data sets.
1029  Calculate_Piecewise_Volume (&POT_Data_Last, &POT_Data[POTCount], &TotalVolume_m3);
1030  // Calculate energy for two given points in time data sets.
1031  Calculate_Piecewiese_Energy(&POT_Data_Last, &POT_Data[POTCount], &TotalEnergy);
1032  POT_Data_Last = POT_Data[POTCount];
1033  }
1034 
1035  // Acknowledge interrupt.
1036  GPIO_IntClear(1 << 2);
1037  }
1038 
1039  else if(flags & (1<< 14)) // SW3 is pressed
1040  {
1041  // Pin press debouncing. Just do something to delay.
1042  for(int loop=0; loop<1000; loop++)
1043  {
1044  pinState = GPIO_PinInGet(gpioPortC, 14);
1045  }
1046 
1047  // Check if SW3 is still pressed. Works as a debouncing filter.
1048  if(!pinState && DisplayMode)
1049  {
1050  // Factory date/time setting.
1051  MAX35101_SetTime();
1052  }
1053  // Acknowledge interrupt.
1054  GPIO_IntClear(1 << 14);
1055  }
1056  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
1057  NVIC_EnableIRQ(GPIO_ODD_IRQn);
1058 }
1059 
1060 int main(void)
1061 {
1062 
1063  CHIP_Init(); // Specific Micro Chip errata
1064 
1065  // Setup SysTick Timer for 1 msec interrupts
1066  if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000))
1067  {
1068  while (1);
1069  }
1070 
1071  init(); //more micro specific initialization routines
1072 
1073 
1074  MAX35101_Send_Opcode(RESET); //Blindly send the MAX35101 reset, in case it is currently running an Event Timing mode
1075  Delay(100); //Blind wait
1076  MAX35101_Send_Opcode(INITIALIZE); //Send the initialization command, see datasheet
1077  Delay(100); //Blind wait
1078 
1079  MAX35101_Write_Register(MINS_HRS, 0x5923); //Set the time
1080  MAX35101_Write_Register(DAY_DATE, 0x0019); //Set the Date
1081  MAX35101_Write_Register(MONTH_YEAR, 0x0914);//Set the year
1082 
1083  // start infinite loop.
1084  //MAX35101_Send_Opcode(EVTMG1);
1085 
1086  while(1)
1087  {
1088  if(DisplayMode != Display_Off)
1089  Display();
1090  else
1091  EMU_EnterEM3(false);
1092 
1093  }
1094 }
1095 
1096 void Display(void)
1097 {
1098  int POTCountShown; // Which is the LAST valid data point taken, this is what we will show
1099 
1100  POTCountShown = POTCount;
1101 
1102  //only update the screen twice a second.
1103  Delay(500);
1104 
1105  // Refresh the screen during normal display modes.
1106  DOGM163_ClearChars(0, 0, 48);
1107 
1108  // Power on and initialize the display if display power is off.
1109  if(displayPowerOff)
1110  {
1111  DOGM163_Init();
1112  displayPowerOff = false;
1113  }
1114 
1115  // Power off the display if the same info has been displayed for MAX_DISPLAY_REPEAT times.
1117  {
1118  displayRepeat ++;
1120  {
1121  DOGM163_PowerOff();
1122  displayPowerOff = true;
1123  displayRepeat = 0;
1126  return;
1127  }
1128  }
1129 
1130  switch (DisplayMode)
1131  {
1132  case Display_Welcome:
1135  break;
1136  case Display_Clock:
1137  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1138 
1139  DOGM163_PrintChars(0, 0, 16, "Real Time Clock:");
1140  sprintf(output, "%02d/%02d/%04d",
1141  POT_Data[POTCountShown].POT_TimeData.Time.tm_mon,
1142  POT_Data[POTCountShown].POT_TimeData.Time.tm_mday,
1143  POT_Data[POTCountShown].POT_TimeData.Time.tm_year + 1900);
1144  DOGM163_PrintChars(1, 0, 16, output);
1145 
1146  sprintf(output, "%02d:%02d:%02d",
1147  POT_Data[POTCountShown].POT_TimeData.Time.tm_hour,
1148  POT_Data[POTCountShown].POT_TimeData.Time.tm_min,
1149  POT_Data[POTCountShown].POT_TimeData.Time.tm_sec);
1150  DOGM163_PrintChars(2, 0, 16, output);
1152  break;
1153  case Display_Temp:
1154  DOGM163_PrintChars(0, 0, 16, "RTD Temperature:");
1155 
1156  sprintf(output, "RTD1:");
1157  FloatToString(POT_Data[POTCountShown].POT_TemperatureData.TempResultsAllPorts[HOT_TEMP_PORT].TemperatureDegreeC, 3, &output[5]);
1158  strcat(output, " C");
1159  DOGM163_PrintChars(1, 0, 16, output);
1160 
1161  sprintf(output, "RTD2:");
1162  FloatToString(POT_Data[POTCountShown].POT_TemperatureData.TempResultsAllPorts[COLD_TEMP_PORT].TemperatureDegreeC, 3, &output[5]);
1163  strcat(output, " C");
1164  DOGM163_PrintChars(2, 0, 16, output);
1165 
1167  break;
1168  case Display_TOFDIFF:
1169 
1170  DOGM163_PrintChars(0, 0, 16, "TOF Difference:");
1171  sprintf(output, "%d",(int) (POT_Data[POTCountShown].POT_FlowFactors.TOF_DIFF_DeltaT_S* 1000000000000));
1172  DOGM163_PrintChars(1, 0, 16, output);
1173  DOGM163_PrintChars(2, 0, 16, "ps");
1175  break;
1176 
1178 
1179  DOGM163_PrintChars(0, 0, 16, "Flow Rate:");
1180  FloatToString(POT_Data[POTCountShown].POT_FlowFactors.VolumetricFlowCorrected_m3PerS* 60 * 1000, 3, output);
1181  DOGM163_PrintChars(1, 0, 16, output);
1182  DOGM163_PrintChars(2, 0, 16, "LPM");
1184  break;
1185 
1186  case Display_Total_Volume:
1187 
1188  DOGM163_PrintChars(0, 0, 16, "Totalizer:");
1189  FloatToString(TotalVolume_m3 * 1000, 3, output); // 1 m3 = 1000 liters.
1190  DOGM163_PrintChars(1, 0, 16, output);
1191  DOGM163_PrintChars(2, 0, 16, "Liters");
1193  break;
1194 
1195  case Display_Energy:
1196  DOGM163_PrintChars(0, 0, 16, "Total Energy:");
1197  snprintf(output, 16, "%d", (int) (TotalEnergy * 0.00094781712)); // 1 BTU = 1055.05585 joules.
1198  DOGM163_PrintChars(1, 0, 16, output);
1199  DOGM163_PrintChars(2, 0, 16, "BTU");
1201  break;
1202 
1203  case Display_TDF_Config:
1204  MAX35101_Read_Register(0x3F,&reg);
1205  TDF = (reg & 0xF000) >> 12;
1206  FloatToString((TDF + 1)*0.5, 1, output);
1207  DOGM163_PrintChars(0, 0, 16, "TDF[3:0] Reg");
1208  DOGM163_PrintChars(1, 0, 16, output);
1209  DOGM163_PrintChars(1, 9, 7, "Seconds");
1210  DOGM163_PrintChars(2, 0, 16, "LongPress:Change");
1212 
1213  break;
1214 
1215  case Display_TDM_Config:
1216  MAX35101_Read_Register(0x3F,&reg);
1217  TDM = (reg & 0x0F80) >> 7;
1218  snprintf(output, 16, "%d", TDM + 1);
1219  DOGM163_PrintChars(0, 0, 16, "TDM[4:0] Reg");
1220  DOGM163_PrintChars(1, 0, 16, output);
1221  DOGM163_PrintChars(1, 10, 6, "Cycles");
1222  DOGM163_PrintChars(2, 0, 16, "LongPress:Change");
1224 
1225  break;
1226 
1227  case Display_TMF_Config:
1228  MAX35101_Read_Register(0x3F,&reg);
1229  TMF = (reg & 0x007E) >> 1;
1230  snprintf(output, 16, "%d", TMF + 1);
1231  DOGM163_PrintChars(0, 0, 16, "TMF[5:0] Reg");
1232  DOGM163_PrintChars(1, 0, 16, output);
1233  DOGM163_PrintChars(1, 9, 7, "Seconds");
1234  DOGM163_PrintChars(2, 0, 16, "LongPress:Change");
1236 
1237  break;
1238 
1239  case Display_TMM_Config:
1240  MAX35101_Read_Register(0x40,&reg);
1241  TMM = (reg & 0xF800) >> 11;
1242  snprintf(output, 16, "%d", TMM + 1);
1243  DOGM163_PrintChars(0, 0, 16, "TMM[4:0] Reg");
1244  DOGM163_PrintChars(1, 0, 16, output);
1245  DOGM163_PrintChars(1, 10, 6, "Cycles");
1246  DOGM163_PrintChars(2, 0, 16, "LongPress:Change");
1248 
1249  break;
1250 
1251  default:
1252  break;
1253  }
1254 }
1255 
1256 
1257 /******************************* MAX35101 SPI sequence Specific SPI ROUNTINES *********************************/
1258 bool MAX35101_SendConfigs(void) //need to rewrite
1259 {
1260 
1261  MAX35101_Write_Register(0x38, 0x1311);
1262  MAX35101_Write_Register(0x39, 0xA3F2);
1263  MAX35101_Write_Register(0x3A, 0x0809);
1264  MAX35101_Write_Register(0x3B, 0x0A0B);
1265  MAX35101_Write_Register(0x3C, 0x0C0D);
1266  MAX35101_Write_Register(0x3D, 0x0048);
1267  MAX35101_Write_Register(0x3E, 0x0048);
1268 
1269 
1270  MAX35101_Write_Register(0x3F, 0x0180); // TOF_DIFF: 0.5s, 4 cycles, Temp: 1s, 2 cycles.
1271  MAX35101_Write_Register(0x40, 0x0FCF); // Use calibration, at the beginning of TOF_DIFF and TEMP sequences.
1272  // Measure T1, T2, T3. PRECYC = 3, PORTCYC = 512us.
1273 
1274 
1275  MAX35101_Write_Register(0x41, 0x0108);
1276  MAX35101_Write_Register(0x42, 0x0343); // CMP_EN=0, CMP_SEL=0, INT_EN=1, ET_CONT=1, CONT_INT=0, clock settling=5.13ms, 4MHz calibration=4 32kHz cycles.
1277  MAX35101_Write_Register(0x43, 0x0080); // 32K_BP=0, 32K_EN=0(no 32KOUT), enable 32kHz, no alarm, no watch dog.
1278 
1280  Delay(1000);
1281  return true;
1282 }
1283 
1284 bool MAX35101_Send_Opcode(char opcode)//Single Byte Opcode Send ONLY (Modulates the CS# line)
1285 {
1286  bool success;
1287  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
1288  NVIC_DisableIRQ(GPIO_ODD_IRQn);
1289  MAX35101_CS_Low(); //Modulate CS#
1290  success = SPI_Send_Byte(opcode); //Transmit the 8 bits over the SPI Bus
1291  MAX35101_CS_High(); //Modulate CS#
1292  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
1293  NVIC_EnableIRQ(GPIO_ODD_IRQn);
1294  return success;
1295 }
1296 
1297 bool MAX35101_Read_2WordValue(char startingAddress, uint32_t* results)//Read two words that make up a temperature reading or Average, TOF read or waverage, Modulates CS# line, Sends address, reads 32 bits data
1298 {
1299  bool success = false;
1300  uint16_t Readresults1, Readresults2 = 0;
1301 
1302  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
1303  NVIC_DisableIRQ(GPIO_ODD_IRQn);
1304  startingAddress |= 0x80;//Read Opcodes Always have MSB of Opcode (address) Set
1305  MAX35101_CS_Low(); //Modulate CS#
1306  success = SPI_Send_Byte(startingAddress);//Transmit the 8 bits over the SPI Bus
1307  success |= SPI_Read_Word(&Readresults1);
1308  success |= SPI_Read_Word(&Readresults2);
1309  MAX35101_CS_High(); //Modulate CS#
1310  *results = (((uint32_t) Readresults1 << 16) + Readresults2);//Combine the 2 words into one 32 bits number
1311  success = false;
1312  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
1313  NVIC_EnableIRQ(GPIO_ODD_IRQn);
1314  return success;
1315 }
1316 
1317 bool MAX35101_Read_Register(char address, uint16_t* results)//Read one word register only, Modulates CS# line, Sends address, reads data
1318 {
1319  bool success;
1320  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
1321  NVIC_DisableIRQ(GPIO_ODD_IRQn);
1322  address |= 0x80; //Read Opcodes Always have MSB of Opcode (address) Set
1323  MAX35101_CS_Low(); //Modulate CS#
1324  success = SPI_Send_Byte(address); //Transmit the 8 bits over the SPI Bus
1325  success |= SPI_Read_Word(results);
1326  MAX35101_CS_High(); //Modulate CS#
1327  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
1328  NVIC_EnableIRQ(GPIO_ODD_IRQn);
1329  return success;
1330 }
1331 
1332 bool MAX35101_Write_Register(char address, uint16_t DatatoWrite)// one word register only, Modulates CS# line, Sends address, reads data
1333 {
1334  bool success;
1335  NVIC_DisableIRQ(GPIO_EVEN_IRQn);
1336  NVIC_DisableIRQ(GPIO_ODD_IRQn);
1337  MAX35101_CS_Low(); //Modulate CS#
1338  success = SPI_Send_Byte(address); //Transmit the 8 bits over the SPI Bus
1339  success = SPI_Send_Byte((char) (DatatoWrite >> 8)); //Transmit the 8 bits over the SPI Bus
1340  success = SPI_Send_Byte((char) (DatatoWrite & 0x00FF)); //Transmit the 8 bits over the SPI Bus
1341  MAX35101_CS_High(); //Modulate CS#
1342  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
1343  NVIC_EnableIRQ(GPIO_ODD_IRQn);
1344  return success;
1345 }
1346 /******************************* END - MAX35101 SPI sequence Specific SPI ROUNTINES *********************************/
1347 
1348 
1349 /******************************* Micro Specific Routines and SPI Block ROUNTINES *********************************/
1350 
1351 void init(void)
1352 {
1353  /* Enable clocks to USART1 and GPIO. */
1354  CMU_ClockEnable(cmuClock_USART1, true);
1355  CMU_ClockEnable(cmuClock_GPIO, true);
1356 
1357  /* Set MAXREFDES70 GPIOs to normal working mode. */
1358  GpioSetup();
1359 
1360  /* The design by default sample at the trailing edge (CLKPHA = USART_CTRL_CLKPHA); */
1361  SPI_setup(1, 0, true);
1362 
1363  // Initialize the DOGM163 display.
1364  DOGM163_Init();
1365 
1366  // Print welcome message for 2 seconds.
1368 
1369  //char output[16];
1370 
1371  //FloatToString(3.5, 3, output);
1372 
1373  Delay(5000);
1374 
1375 
1376  DOGM163_PowerOff();
1377 
1378  MAX35101_SendConfigs(); //Send standard configurations to MAX35101, these are ALL stored in flash and therefore don't need to be sent if the FLASH is preprogrammed
1379 }
1380 
1381 /**************************************
1382  * @brief SysTick_Handler
1383  * Interrupt Service Routine for system tick counter
1384  *************************************/
1385 void SysTick_Handler(void) {
1386  msTicks++; /* increment counter necessary in Delay()*/
1387 }
1388 
1389 /***************************************/
1393 extern void Delay(uint32_t dlyTicks) {
1394  uint32_t curTicks;
1395 
1396  curTicks = msTicks;
1397  while ((msTicks - curTicks) < dlyTicks)
1398  ;
1399 }
1400 
1401 
1402 #define HFRCO_FREQUENCY 14000000
1403 #define SPI_PERCLK_FREQUENCY HFRCO_FREQUENCY
1404 #define SPI_BAUDRATE 1000000
1405 #define NO_RX 0
1406 #define NO_TX NO_RX
1407 
1408 void USART2_sendBuffer(char* txBuffer, int bytesToSend) {
1409  USART_TypeDef *uart = USART1;
1410  int ii;
1411  /* Sending the data */
1412  for (ii = 0; ii < bytesToSend; ii++) {
1413  /* Waiting for the usart to be ready */
1414  while (!(uart->STATUS & USART_STATUS_TXBL))
1415  ;
1416 
1417  if (txBuffer != 0) {
1418  /* Writing next byte to USART */
1419  uart->TXDATA = *txBuffer;
1420  txBuffer++;
1421  } else {
1422  uart->TXDATA = 0;
1423  }
1424  }
1425  /*Waiting for transmission of last byte */
1426  while (!(uart->STATUS & USART_STATUS_TXC))
1427  ;
1428 }
1429 
1430 bool SPI_Send_Byte(char dataByte)//Change this implementation to your Hardware
1431 {
1432  bool success = true;
1433  //SPI2_setupRXInt(NO_RX, NO_RX); /* Setting up RX interrupt for master */
1434  USART2_sendBuffer(&dataByte, 1); /* Transmitting data */
1435  return success;
1436 }
1437 
1438 bool SPI_Read_Word(uint16_t* results)//Change this implementation to your Hardware
1439 {
1440  bool success = true;
1441  USART_TypeDef *spi = USART1;
1442  uint8_t rxdataByte1, rxdataByte2;
1443  spi->CMD = USART_CMD_CLEARRX; //Clear the receive Buffer
1444  USART2_sendBuffer(NO_TX, 1); /* Receiving data by transmitting dummy data to slave */
1445  rxdataByte1 = spi->RXDATA;
1446  USART2_sendBuffer(NO_TX, 1); /* Receiving data by transmitting dummy data to slave */
1447  rxdataByte2 = spi->RXDATA;
1448  *results = (uint16_t) (rxdataByte2 + (rxdataByte1 << 8));
1449  return success;
1450 }
1451 
1452 /**************************************************************************/
1458 static void SPI_setup(uint8_t spiNumber, uint8_t location, bool master) {
1459  USART_TypeDef *spi;
1460  GPIO_Mode_TypeDef gpioModeMosi;
1461  GPIO_Mode_TypeDef gpioModeMiso;
1462  // GPIO_Mode_TypeDef gpioModeCs ;
1463  GPIO_Mode_TypeDef gpioModeClk;
1464 
1465  /* Determining USART */
1466  spi = USART1;
1467 
1468  /* Setting baudrate */
1469  spi->CLKDIV = 128 * (SPI_PERCLK_FREQUENCY / SPI_BAUDRATE - 2); //SPI_BAUDRATE
1470 
1471  /* Configure SPI */
1472  /* Using synchronous (SPI) mode*/
1473  spi->CTRL = USART_CTRL_SYNC | USART_CTRL_MSBF; // | USART_CTRL_CLKPHA;
1474  /* Clearing old transfers/receptions, and disabling interrupts */
1475  spi->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
1476  spi->IEN = 0;
1477  /* Enabling pins and setting location */
1478  //spi->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN | USART_ROUTE_CSPEN | (location << 8);
1479  spi->ROUTE = USART_ROUTE_TXPEN | USART_ROUTE_RXPEN | USART_ROUTE_CLKPEN
1480  | (location << 8);
1481 
1482  /* Set to master and to control the CS line */
1483  if (master) {
1484  /* Enabling Master, TX and RX */
1485  spi->CMD = USART_CMD_MASTEREN | USART_CMD_TXEN | USART_CMD_RXEN;
1486  // spi->CTRL |= USART_CTRL_AUTOCS;
1487 
1488  /* Set GPIO config to master */
1489  gpioModeMosi = gpioModePushPull;
1490  gpioModeMiso = gpioModeInput;
1491  // gpioModeCs = gpioModePushPull;
1492  gpioModeClk = gpioModePushPull;
1493  } else {
1494  /* Enabling TX and RX */
1495  spi->CMD = USART_CMD_TXEN | USART_CMD_RXEN;
1496  }
1497 
1498  /* Clear previous interrupts */
1499  spi->IFC = _USART_IFC_MASK;
1500 
1501  /* IO configuration */
1502  GPIO_PinModeSet(gpioPortC, 0, gpioModeMosi, 0); /* MOSI */
1503  GPIO_PinModeSet(gpioPortC, 1, gpioModeMiso, 0); /* MISO */
1504 // GPIO_PinModeSet(gpioPortC, 14, gpioModeCs, 0); /* CS */
1505  GPIO_PinModeSet(gpioPortB, 7, gpioModeClk, 0); /* Clock */
1506 }
1507 
1508 
1509 
1510 /**************************************************************************/
1516 static void GpioSetup(void) {
1517  /* DOGM163 CS pin (PB11). */
1518  GPIO_PinModeSet(gpioPortB, 11, gpioModePushPull, 1);
1519  /* DOGM163 RS pin (PB13). */
1520  GPIO_PinModeSet(gpioPortB, 13, gpioModePushPull, 0);
1521 
1522  /* MAX35101 COM_OUT/UP_DN pin (PC15). */
1523  GPIO_PinModeSet(gpioPortC, 15, gpioModeInput, 0);
1524  GPIO_IntConfig(gpioPortC, 15, false, true, false);
1525  /* MAX35101 WDO pin (PE12). */
1526  GPIO_PinModeSet(gpioPortE, 12, gpioModeInputPullFilter, 1);
1527  GPIO_IntConfig(gpioPortE, 12, false, true, false);
1528  /* MAX35101 INT pin (PF2). */
1529  GPIO_PinModeSet(gpioPortF, 2, gpioModeInputPullFilter, 1);
1530  GPIO_IntConfig(gpioPortF, 2, false, true, true );
1531 
1532  /* MAX35101 RST pin (PE13). */
1533  GPIO_PinModeSet(gpioPortE, 13, gpioModePushPull, 1);
1534  /* MAX35101 CS pin (PB8). */
1535  GPIO_PinModeSet(gpioPortB, 8, gpioModePushPull, 1);
1536 
1537  /* DOGM163 power switch on(PD6). */
1538  GPIO_PinModeSet(gpioPortD, 6, gpioModePushPull, 1);
1539 
1540  /* SPI SCLK pin (PB7). */
1541  GPIO_PinModeSet(gpioPortB, 7, gpioModePushPull, 0);
1542  /* SPI MOSI pin (PC0). */
1543  GPIO_PinModeSet(gpioPortC, 0, gpioModePushPull, 0);
1544  /* SPI MISO pin (PC1). */
1545  GPIO_PinModeSet(gpioPortC, 1, gpioModeInput, 0);
1546 
1547  /* SW2 pin (PA0). */
1548  GPIO_PinModeSet(gpioPortA, 0, gpioModeInputPullFilter, 1);
1549  GPIO_IntConfig(gpioPortA, 0, false, true, true );
1550  /* SW3 pin (PC14). */
1551  GPIO_PinModeSet(gpioPortC, 14, gpioModeInputPullFilter, 1);
1552  GPIO_IntConfig(gpioPortC, 14, false, true, true );
1553  /* SW4 pin (PD7). */
1554  GPIO_PinModeSet(gpioPortD, 7, gpioModeInputPullFilter, 1);
1555  GPIO_IntConfig(gpioPortD, 7, false, true, true );
1556 
1557 }
1558 
1560 {
1561  char output[49];
1562  uint16_t year;
1563  uint8_t month, date, hour, minute;
1564 
1565  DOGM163_ClearChars(0, 0, 48);
1566 
1567  DOGM163_PrintChars(1, 0, 16, "SW2:ACCEPT");
1568  DOGM163_PrintChars(2, 0, 16, "SW3:UP SW4:DOWN");
1569 
1570  // Set year.
1571  DOGM163_ClearChars(0, 0, 16);
1572  DOGM163_PrintChars(0, 0, 16, "SET YEAR:");
1573 
1574  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1575  year = POT_Data[POTCount].POT_TimeData.Time.tm_year + 1900;
1576  sprintf(output, "%04d",year);
1577  DOGM163_PrintChars(0, 10, 4, output);
1578 
1579  for(int loop = 0; loop < 10000000; loop++)
1580  {
1581  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low).
1582  {
1583  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1584  GPIO_PinInGet(gpioPortA, 0);
1585 
1586  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low) verified.
1587  {
1588  // write year/month to register.
1589  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1590  month = POT_Data[POTCount].POT_TimeData.Time.tm_mon;
1591  MAX35101_Write_Register(MONTH_YEAR, ((((month/10)<<4) + month%10)<<8) + (((year-2000)/10)<<4) + (year-2000)%10);
1592  break;
1593  }
1594  }
1595  else if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low).
1596  {
1597  loop = 0;
1598  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1599  GPIO_PinInGet(gpioPortC, 14);
1600 
1601  if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low) verified.
1602  {
1603  if(year < 2099)
1604  year += 1;
1605  sprintf(output, "%04d",year);
1606  DOGM163_PrintChars(0, 10, 4, output);
1607  }
1608  }
1609  else if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low).
1610  {
1611  loop = 0;
1612  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1613  GPIO_PinInGet(gpioPortD, 7);
1614 
1615  if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low) verified.
1616  {
1617  if(year > 2000)
1618  year -= 1;
1619  sprintf(output, "%04d",year);
1620  DOGM163_PrintChars(0, 10, 4, output);
1621  }
1622  }
1623  } // Set year.
1624 
1625  // Set month.
1626  DOGM163_ClearChars(0, 0, 16);
1627  DOGM163_PrintChars(0, 0, 16, "SET MONTH:");
1628 
1629  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1630  month = POT_Data[POTCount].POT_TimeData.Time.tm_mon;
1631  sprintf(output, "%02d",month);
1632  DOGM163_PrintChars(0, 11, 2, output);
1633 
1634  for(int loop = 0; loop < 10000000; loop++)
1635  {
1636  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low).
1637  {
1638  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1639  GPIO_PinInGet(gpioPortA, 0);
1640 
1641  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low) verified.
1642  {
1643  // write year/month to register.
1644  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1645  year = POT_Data[POTCount].POT_TimeData.Time.tm_year + 1900;
1646  MAX35101_Write_Register(MONTH_YEAR, ((((month/10)<<4) + month%10)<<8) + (((year-2000)/10)<<4) + (year-2000)%10);
1647  break;
1648  }
1649  }
1650  else if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low).
1651  {
1652  loop = 0;
1653  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1654  GPIO_PinInGet(gpioPortC, 14);
1655 
1656  if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low) verified.
1657  {
1658  if(month < 12)
1659  month += 1;
1660  sprintf(output, "%02d",month);
1661  DOGM163_PrintChars(0, 11, 2, output);
1662  }
1663  }
1664  else if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low).
1665  {
1666  loop = 0;
1667  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1668  GPIO_PinInGet(gpioPortD, 7);
1669 
1670  if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low) verified.
1671  {
1672  if(month > 1)
1673  month -= 1;
1674  sprintf(output, "%02d",month);
1675  DOGM163_PrintChars(0, 11, 2, output);
1676  }
1677  }
1678  } // Set month.
1679 
1680  // Set date.
1681  DOGM163_ClearChars(0, 0, 16);
1682  DOGM163_PrintChars(0, 0, 16, "SET DATE:");
1683 
1684  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1685  date = POT_Data[POTCount].POT_TimeData.Time.tm_mday;
1686  sprintf(output, "%02d",date);
1687  DOGM163_PrintChars(0, 10, 2, output);
1688 
1689  for(int loop = 0; loop < 10000000; loop++)
1690  {
1691  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low).
1692  {
1693  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1694  GPIO_PinInGet(gpioPortA, 0);
1695 
1696  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low) verified.
1697  {
1698  // write date to register.
1699  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1700  MAX35101_Write_Register(DAY_DATE, ((date/10)<<4) + date%10);
1701  break;
1702  }
1703  }
1704  else if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low).
1705  {
1706  loop = 0;
1707  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1708  GPIO_PinInGet(gpioPortC, 14);
1709 
1710  if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low) verified.
1711  {
1712  if(date < 31)
1713  date += 1;
1714  sprintf(output, "%02d",date);
1715  DOGM163_PrintChars(0, 10, 2, output);
1716  }
1717  }
1718  else if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low).
1719  {
1720  loop = 0;
1721  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1722  GPIO_PinInGet(gpioPortD, 7);
1723 
1724  if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low) verified.
1725  {
1726  if(date > 1)
1727  date -= 1;
1728  sprintf(output, "%02d",date);
1729  DOGM163_PrintChars(0, 10, 2, output);
1730  }
1731  }
1732  } // Set date.
1733 
1734  // Set hour.
1735  DOGM163_ClearChars(0, 0, 16);
1736  DOGM163_PrintChars(0, 0, 16, "SET HOUR:");
1737 
1738  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1739  hour = POT_Data[POTCount].POT_TimeData.Time.tm_hour;
1740  sprintf(output, "%02d",hour);
1741  DOGM163_PrintChars(0, 10, 2, output);
1742 
1743  for(int loop = 0; loop < 10000000; loop++)
1744  {
1745  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low).
1746  {
1747  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1748  GPIO_PinInGet(gpioPortA, 0);
1749 
1750  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low) verified.
1751  {
1752  // write hour/minute to register.
1753  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1754  minute = POT_Data[POTCount].POT_TimeData.Time.tm_min;
1755  MAX35101_Write_Register(MINS_HRS, ((((minute/10)<<4) + minute%10)<<8) + ((hour/10)<<4) + hour%10);
1756  break;
1757  }
1758  }
1759  else if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low).
1760  {
1761  loop = 0;
1762  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1763  GPIO_PinInGet(gpioPortC, 14);
1764 
1765  if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low) verified.
1766  {
1767  if(hour < 23)
1768  hour += 1;
1769  sprintf(output, "%02d",hour);
1770  DOGM163_PrintChars(0, 10, 2, output);
1771  }
1772  }
1773  else if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low).
1774  {
1775  loop = 0;
1776  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1777  GPIO_PinInGet(gpioPortD, 7);
1778 
1779  if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low) verified.
1780  {
1781  if(hour > 0)
1782  hour -= 1;
1783  sprintf(output, "%02d",hour);
1784  DOGM163_PrintChars(0, 10, 2, output);
1785  }
1786  }
1787  } // Set hour.
1788 
1789  // Set minute.
1790  DOGM163_ClearChars(0, 0, 16);
1791  DOGM163_PrintChars(0, 0, 16, "SET MINUTE:");
1792 
1793  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1794  minute = POT_Data[POTCount].POT_TimeData.Time.tm_min;
1795  sprintf(output, "%02d",minute);
1796  DOGM163_PrintChars(0, 12, 2, output);
1797 
1798  for(int loop = 0; loop < 10000000; loop++)
1799  {
1800  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low).
1801  {
1802  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1803  GPIO_PinInGet(gpioPortA, 0);
1804 
1805  if(!GPIO_PinInGet(gpioPortA, 0)) // SW2 pushed down (low) verified.
1806  {
1807  // write hour/minute to register.
1808  MAX35101_UpdateAndGetTime(&POT_Data[POTCount].POT_TimeData);
1809  hour = POT_Data[POTCount].POT_TimeData.Time.tm_hour;
1810  MAX35101_Write_Register(MINS_HRS, ((((minute/10)<<4) + minute%10)<<8) + ((hour/10)<<4) + hour%10);
1811  break;
1812  }
1813  }
1814  else if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low).
1815  {
1816  loop = 0;
1817  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1818  GPIO_PinInGet(gpioPortC, 14);
1819 
1820  if(!GPIO_PinInGet(gpioPortC, 14)) // SW3 pushed down (low) verified.
1821  {
1822  if(minute < 59)
1823  minute += 1;
1824  sprintf(output, "%02d",minute);
1825  DOGM163_PrintChars(0, 12, 2, output);
1826  }
1827  }
1828  else if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low).
1829  {
1830  loop = 0;
1831  for(int loop1 = 0; loop1 < 300000; loop1++) // Pin press debouncing.
1832  GPIO_PinInGet(gpioPortD, 7);
1833 
1834  if(!GPIO_PinInGet(gpioPortD, 7)) // SW4 pushed down (low) verified.
1835  {
1836  if(minute > 0)
1837  minute -= 1;
1838  sprintf(output, "%02d",minute);
1839  DOGM163_PrintChars(0, 12, 2, output);
1840  }
1841  }
1842  } // Set minute.
1843 }
1844 
1845