@@ -273,146 +273,55 @@ void init()
273
273
// this needs to be called before setup() or some functions won't
274
274
// work there
275
275
276
- /*************************** GET VCC & FUSE SETTING ***************************/
277
-
278
-
279
- /* Measure VDD using ADC */
280
- uint8_t supply_voltage ;
281
-
282
- /* Initialize AC reference (what we are measuring) - 1.5V known */
283
- VREF .CTRLA |= VREF_AC0REFSEL_1V5_gc ;
284
-
285
- /* Enable AC reference */
286
- VREF .CTRLB |= VREF_AC0REFEN_bm ;
287
-
288
- /* DAC to max -- output reference voltage */
289
- AC0 .DACREF = 0xFF ;
290
-
291
- /* Enable DAC REF by selecting it as input and enabling AC */
292
- AC0 .MUXCTRLA |= AC_MUXNEG_DACREF_gc ;
293
- AC0 .CTRLA |= ADC_ENABLE_bm ;
294
-
295
- /* Initialize ADC reference (VDD) */
296
- ADC0 .CTRLC = ADC_REFSEL_VDDREF_gc ;
297
-
298
- /* Initialize MUX (DAC/AC reference from VREF) */
299
- ADC0 .MUXPOS = ADC_MUXPOS_DACREF_gc ;
300
-
301
- /* Enable ADC */
302
- ADC0 .CTRLA |= ADC_ENABLE_bm ;
303
-
304
- /* Start a conversion */
305
- ADC0 .COMMAND |= ADC_STCONV_bm ;
306
-
307
- /* Wait until result is ready */
308
- while (!(ADC0 .INTFLAGS & ADC_RESRDY_bm ));
309
-
310
- /* Result ready */
311
- /* supply_voltage = (VIN * 1024)/result where VIN = 1.5V from VREF */
312
- uint16_t adc_result = ADC0 .RES ;
313
-
314
- uint16_t voltage = (15 * 1024 ) / adc_result ; /* using 1.5 << 1 to avoid using float */
315
-
316
- /* Only for the purposes of staying within safe operating range -- approximate */
317
- if (voltage >= 48 ){ /* 4.8V+ -> 5V */
318
- supply_voltage = VCC_5V0 ;
319
- } else if (voltage >= 30 ){ /* 3V-4V7 -> 3V3 */
320
- supply_voltage = VCC_3V3 ;
321
- } else { /* < 3V -> 1V8 */
322
- supply_voltage = VCC_1V8 ;
323
- }
324
-
325
- /* Fuse setting for 16/20MHz oscillator */
326
- uint8_t fuse_setting = FUSE .OSCCFG & FUSE_FREQSEL_gm ;
327
-
328
- /* Deinitialize ADC, AC & VREF */
329
- ADC0 .CTRLA = 0x00 ;
330
- ADC0 .MUXPOS = 0x00 ;
331
- ADC0 .CTRLC = 0x00 ;
332
-
333
- AC0 .CTRLA = 0x00 ;
334
- AC0 .MUXCTRLA = 0x00 ;
335
- AC0 .DACREF = 0xFF ;
336
-
337
- VREF .CTRLB = 0x00 ;
338
- VREF .CTRLA = 0x00 ;
339
-
340
276
/******************************** CLOCK STUFF *********************************/
341
277
278
+ /* We assume 5V operating frequency and FUSE.OSCCFG -> 16MHz */
279
+
342
280
int64_t cpu_freq ;
343
281
344
- #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
345
- int8_t sigrow_val = 0 ;
346
- #endif
347
-
348
- /* Initialize clock divider to stay within safe operating area */
349
-
350
- if (supply_voltage >= VCC_5V0 ){
351
-
352
- /* Disable system clock prescaler - F_CPU should now be ~16/20MHz */
353
- _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , 0x00 );
354
-
355
- /* Assign cpu_freq value and sigrow_val depending on fuse setting */
356
- if (fuse_setting == FREQSEL_20MHZ_gc ){
357
- cpu_freq = 20000000 ;
358
-
359
- #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
360
- sigrow_val = SIGROW .OSC20ERR5V ;
361
- #endif
362
-
363
- } else { /* fuse_setting == FREQSEL_16MHZ_gc */
364
- cpu_freq = 16000000 ;
365
-
366
- #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
367
- sigrow_val = SIGROW .OSC16ERR5V ;
368
- #endif
369
-
370
- }
371
-
372
- } else if (supply_voltage == VCC_3V3 ) {
373
-
374
- /* Enable system clock prescaler to DIV2 - F_CPU should now be ~8/10MHz */
375
- _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc ));
376
-
377
- /* Assign cpu_freq value and sigrow_val depending on fuse setting */
378
- if (fuse_setting == FREQSEL_20MHZ_gc ){
379
- cpu_freq = 10000000 ;
380
-
381
- #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
382
- sigrow_val = SIGROW .OSC20ERR3V ;
383
- #endif
384
-
385
- } else { /* fuse_setting == FREQSEL_16MHZ_gc */
386
- cpu_freq = 8000000 ;
387
-
388
- #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
389
- sigrow_val = SIGROW .OSC16ERR3V ;
390
- #endif
391
- }
392
-
393
- } else {
394
- /* Shouldn't get here but just in case... */
395
-
396
- /* Enable system clock prescaler to DIV4 - F_CPU should now be ~4/5MHz */
397
- _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc ));
398
-
399
-
400
- if (fuse_setting == FREQSEL_20MHZ_gc ){
401
- cpu_freq = 5000000 ;
402
- #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
403
- sigrow_val = SIGROW .OSC20ERR3V ;
404
- #endif
405
-
406
- } else { /* fuse_setting == FREQSEL_16MHZ_gc */
407
- cpu_freq = 4000000 ;
408
- #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
409
- sigrow_val = SIGROW .OSC16ERR3V ;
410
- #endif
411
- }
412
- }
282
+ #if (F_CPU == 16000000 )
283
+ cpu_freq = 16000000 ;
284
+
285
+ /* No division on clock */
286
+ _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , 0x00 );
287
+
288
+ #elif (F_CPU == 8000000 )
289
+ cpu_freq = 8000000 ;
290
+
291
+ /* Clock DIV2 */
292
+ _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , (CLKCTRL_PEN_bm | CLKCTRL_PDIV_2X_gc ));
293
+
294
+ #elif (F_CPU == 4000000 )
295
+ cpu_freq = 4000000 ;
296
+
297
+ /* Clock DIV4 */
298
+ _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , (CLKCTRL_PEN_bm | CLKCTRL_PDIV_4X_gc ))
299
+
300
+ #elif (F_CPU == 2000000 )
301
+ cpu_freq = 2000000 ;
302
+
303
+ /* Clock DIV8 */
304
+ _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , (CLKCTRL_PEN_bm | CLKCTRL_PDIV_8X_gc ))
305
+ #else
306
+
307
+ #ifndef F_CPU
308
+ # warning "F_CPU not defined"
309
+ #define F_CPU 16000000
310
+ #endif
311
+
312
+ # warning "F_CPU defined as an invalid value - may cause undefined behavior"
313
+
314
+ /* Default value is 16MHz */
315
+ cpu_freq = 16000000 ;
316
+
317
+ /* No division on clock */
318
+ _PROTECTED_WRITE (CLKCTRL_MCLKCTRLB , 0x00 );
319
+ #endif
320
+
413
321
414
322
#if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
415
323
/* Calculate actual F_CPU with error values from signature row */
324
+ uint8_t sigrow_val = SIGROW .OSC16ERR5V ;
416
325
cpu_freq *= (1024 + sigrow_val );
417
326
cpu_freq /= 1024 ;
418
327
#endif /* (CORRECT_F_CPU == 1) */
0 commit comments