@@ -276,146 +276,55 @@ void init()
276276 // this needs to be called before setup() or some functions won't
277277 // work there
278278
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-
343279/******************************** CLOCK STUFF *********************************/
344280
281+ /* We assume 5V operating frequency and FUSE.OSCCFG -> 16MHz */
282+
345283 int64_t cpu_freq ;
346284
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+
416324
417325 #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
418326 /* Calculate actual F_CPU with error values from signature row */
327+ uint8_t sigrow_val = SIGROW .OSC16ERR5V ;
419328 cpu_freq *= (1024 + sigrow_val );
420329 cpu_freq /= 1024 ;
421330 #endif /* (CORRECT_F_CPU == 1) */
0 commit comments