@@ -73,6 +73,11 @@ bool hwInit(void)
7373 while (!MY_SERIALDEVICE) {}
7474#endif
7575#endif
76+
77+ SYSCTRL->VREF .reg |= SYSCTRL_VREF_TSEN; // Enable the temperature sensor
78+ while (ADC->STATUS .bit .SYNCBUSY ==
79+ 1 ); // Wait for synchronization of registers between the clock domains
80+
7681 const uint8_t eepInit = eep.begin (MY_EXT_EEPROM_TWI_CLOCK, &Wire);
7782#if defined(SENSEBENDER_GW_SAMD_V1)
7883 // check connection to external EEPROM - only sensebender GW
@@ -178,7 +183,68 @@ uint16_t hwCPUFrequency(void)
178183
179184int8_t hwCPUTemperature (void )
180185{
181- return -127 ; // not implemented yet
186+ // taken from https://github.com/arduino/ArduinoCore-samd/pull/277
187+ // Set to 12 bits resolution
188+ ADC->CTRLB .reg = ADC_CTRLB_RESSEL_12BIT | ADC_CTRLB_PRESCALER_DIV256;
189+ syncADC ();
190+ // Ensure we are sampling slowly
191+ ADC->SAMPCTRL .reg = ADC_SAMPCTRL_SAMPLEN (0x3f );
192+ syncADC ();
193+ // Set ADC reference to internal 1v
194+ ADC->INPUTCTRL .bit .GAIN = ADC_INPUTCTRL_GAIN_1X_Val;
195+ ADC->REFCTRL .bit .REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val;
196+ syncADC ();
197+ // Select MUXPOS as temperature channel, and MUXNEG as internal ground
198+ ADC->INPUTCTRL .bit .MUXPOS = ADC_INPUTCTRL_MUXPOS_TEMP_Val;
199+ ADC->INPUTCTRL .bit .MUXNEG = ADC_INPUTCTRL_MUXNEG_GND_Val;
200+ syncADC ();
201+ // Enable ADC
202+ ADC->CTRLA .bit .ENABLE = 1 ;
203+ syncADC ();
204+ // Start ADC conversion
205+ ADC->SWTRIG .bit .START = 1 ;
206+ // Clear the Data Ready flag
207+ ADC->INTFLAG .reg = ADC_INTFLAG_RESRDY;
208+ syncADC ();
209+ // Start conversion again, since The first conversion after the reference is changed must not be used.
210+ ADC->SWTRIG .bit .START = 1 ;
211+ // Wait until ADC conversion is done
212+ while (!(ADC->INTFLAG .bit .RESRDY ));
213+ syncADC ();
214+ // Get result
215+ // This is signed so that the math later is done signed
216+ const int32_t adcReading = ADC->RESULT .reg ;
217+ // Clear result ready flag
218+ ADC->INTFLAG .reg = ADC_INTFLAG_RESRDY;
219+ syncADC ();
220+ // Disable ADC
221+ ADC->CTRLA .bit .ENABLE = 0 ;
222+ syncADC ();
223+ // Factory room temperature readings
224+ const uint8_t roomInteger = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_INT_ADDR &
225+ FUSES_ROOM_TEMP_VAL_INT_Msk)
226+ >> FUSES_ROOM_TEMP_VAL_INT_Pos;
227+ const uint8_t roomDecimal = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_DEC_ADDR &
228+ FUSES_ROOM_TEMP_VAL_DEC_Msk)
229+ >> FUSES_ROOM_TEMP_VAL_DEC_Pos;
230+ const int32_t roomReading = ((*(uint32_t *)FUSES_ROOM_ADC_VAL_ADDR & FUSES_ROOM_ADC_VAL_Msk) >>
231+ FUSES_ROOM_ADC_VAL_Pos);
232+ const int32_t roomTemperature = 1000 * roomInteger + 100 * roomDecimal;
233+ // Factory hot temperature readings
234+ const uint8_t hotInteger = (*(uint32_t *)FUSES_HOT_TEMP_VAL_INT_ADDR & FUSES_HOT_TEMP_VAL_INT_Msk)
235+ >>
236+ FUSES_HOT_TEMP_VAL_INT_Pos;
237+ const uint8_t hotDecimal = (*(uint32_t *)FUSES_HOT_TEMP_VAL_DEC_ADDR & FUSES_HOT_TEMP_VAL_DEC_Msk)
238+ >>
239+ FUSES_HOT_TEMP_VAL_DEC_Pos;
240+ const int32_t hotReading = ((*(uint32_t *)FUSES_HOT_ADC_VAL_ADDR & FUSES_HOT_ADC_VAL_Msk) >>
241+ FUSES_HOT_ADC_VAL_Pos);
242+ const int32_t hotTemperature = 1000 * hotInteger + 100 * hotDecimal;
243+ // Linear interpolation of temperature using factory room temperature and hot temperature
244+ const int32_t temperature = roomTemperature + ((hotTemperature - roomTemperature) *
245+ (adcReading - roomReading)) / (hotReading - roomReading);
246+ return static_cast <int8_t >(((temperature / 1000 ) - MY_SAMD_TEMPERATURE_OFFSET) /
247+ MY_SAMD_TEMPERATURE_GAIN);
182248}
183249
184250
0 commit comments