@@ -273,146 +273,55 @@ void init()
273273 // this needs to be called before setup() or some functions won't
274274 // work there
275275
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-
340276/******************************** CLOCK STUFF *********************************/
341277
278+ /* We assume 5V operating frequency and FUSE.OSCCFG -> 16MHz */
279+
342280 int64_t cpu_freq ;
343281
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+
413321
414322 #if (PERFORM_SIGROW_CORRECTION_F_CPU == 1 )
415323 /* Calculate actual F_CPU with error values from signature row */
324+ uint8_t sigrow_val = SIGROW .OSC16ERR5V ;
416325 cpu_freq *= (1024 + sigrow_val );
417326 cpu_freq /= 1024 ;
418327 #endif /* (CORRECT_F_CPU == 1) */
0 commit comments