It works now, my blinky is flashing away like a wild thing but I’d still like to understand what’s going on.
I selected the 16/20MHz internal clock as system clock but have this not running in standby.
(How do you read the FREQSEL
bits in the in the Oscillator Configuration Fuse to find out if its running at 16 or 20MHz?)
I removed the #define MILLIS_USE_TIMERA0 1
and init_millis();
I played around with the #define F_CPU
value - it made not difference to the flash rate.
The millis() still expands to millis rather than an unsigned long returned by the function millis().
How does this work when I’m trying to load an unsigned long value into my debounce variable?
I’m a bit confused about setting the main clock prescaler (data sheet implied it defaulted to 6 after a reset) and the need to define F_CPU. But when I set it to 6 (commented out code), my blinky flash rate slowed right down so by the time my code runs, the main clock prescaler cannot still be 6.
I think the Arduino framework is doing stuff I’m not aware of.
I’m only using this framework so I can leverage on millis (and some other Arduino libraries).
If you can shed any light on what’s happening, I’d still appreciate the information.
//#ifdef F_CPU
//#undef F_CPU
//#endif
//#define F_CPU 32000UL
//#define F_CPU 3333333UL
#include <Arduino.h>
#include <avr/interrupt.h> // so we can use interrupt vector names
#include <util/delay.h> // needed for the delay functions
/* pin information
ATtiny402
----u---
VDD| |GND
PWR PA6| |PA3 SIG
SW_M PA7| |PA0 UDIP
BUZ PA1| |PA2 SW_P
--------
*/
#define SIG_bp 3
#define rtc_period 960 // 960 is a rate of 1Hz
void system_init(); // placeholder for compiler
void bop(){ // debug routine
VPORTA_IN |= (1<< SIG_bp); // toggle LED1
_delay_ms(10);
VPORTA_IN |= (1<<SIG_bp); // toggle LED1
}
void setup() {
// put your setup code here, to run once:
system_init();
}
void loop() {
// put your main code here, to run repeatedly:
static unsigned long last_SW_M_time; // debounce timer
if (millis() - last_SW_M_time > 50){ // debug routine to flash LED
VPORTA_IN |= (1<< SIG_bp); // toggle SIG
last_SW_M_time = millis(); // reset debounce timer
}
}
void mcu_init(void) /* MCU initialization */
{
/* On AVR devices all peripherals are enable from power on reset, this
* disables all peripherals to save power. Driver shall enable
* peripheral if used */
/* Set all pins to low power mode */
for (uint8_t i = 0; i < 8; i++) {
*((uint8_t *)&PORTA + 0x10 + i) |= 1 << PORT_PULLUPEN_bp;
}
}
void pin_init(void){ /* PIN initialization */
/* pin information
ATtiny402
----u---
VDD| |GND
PWR PA6| |PA3 SIG
SW_M PA7| |PA0 UDIP
BUZ PA1| |PA2 SW_P
--------
*/
// define output pins
VPORTA_DIR |= (1<<SIG_bp); // debug
// set output pins LOW
VPORTA_OUT &= ~((1<<SIG_bp)); // debug
}
void CLKCTRL_init(void){ /* Main clock initialization */
/* Set the Main clock to internal 32kHz oscillator*/
//_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSCULP32K_gc);
/* Set the Main clock to internal 16/20MHz oscillator*/
_PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSC20M_gc);
/* disable the 16/20MHz oscillator in standby mode*/
_PROTECTED_WRITE(CLKCTRL.OSC20MCTRLA, 0 << CLKCTRL_RUNSTDBY_bp);
/* run the 32kHz oscillator in standby mode*/
_PROTECTED_WRITE(CLKCTRL.OSC32KCTRLA, 1 << CLKCTRL_RUNSTDBY_bp);
/* Set the Main clock prescaler divisor to 6X and enable the Main clock prescaler */
//_PROTECTED_WRITE(CLKCTRL.MCLKCTRLB, CLKCTRL_PDIV_6X_gc | 1 << CLKCTRL_PEN_bp);
/* ensure 20MHz isn't forced on*/
_PROTECTED_WRITE(CLKCTRL.OSC20MCTRLA, 0 << CLKCTRL_RUNSTDBY_bp);
/* wait for system oscillator changing to finish */
while (CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm) {
}
}
void RTC_0_init(void){ /* Realtime clock initialization */ //- may not need this
/* Wait for all register to be synchronized */
while (RTC.STATUS > 0);
/* 32KHz Internal Ultra Low Power Oscillator (OSCULP32K) */
RTC.CLKSEL = RTC_CLKSEL_INT32K_gc;
/* Period: */
RTC.PER = rtc_period;
/* Compare Match Interrupt disabled, Overflow Interrupt enabled */
RTC.INTCTRL = (0 << RTC_CMP_bp) | (1 << RTC_OVF_bp);
/* Prescaler of 32, enable and run in standby */
RTC.CTRLA = RTC_PRESCALER_DIV32_gc | (1 << RTC_RTCEN_bp) | (1 << RTC_RUNSTDBY_bp);
}
void CPUINT_init(void){ /* Interrupt initialisation */
/* Enable interrupts */
sei();
}
void system_init(){ /* system initialization */
mcu_init();
pin_init();
CLKCTRL_init();
RTC_0_init();
//VREF_0_init();
//ADC_0_initialization();
//EVENT_SYSTEM_0_initialization();
//CPUINT_init();
//SLPCTRL_init();
//BOD_init();
}
ISR(RTC_CNT_vect){ // RTC interrupt
/* Insert your RTC Overflow interrupt handling code */
if (RTC.INTFLAGS & RTC_OVF_bm){
//VPORTA_OUT ^= (1<<SIG_bp); // toggle SIG
}
/* Overflow interrupt flag has to be cleared manually */
RTC.INTFLAGS = RTC_OVF_bm | RTC_CMP_bm;
}