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