#include <ioavr>
#include <inavr>
#include <stdint>
#include <stdio.h>
#include <string.h>
#define FOSC 16000000UL
#define BAUD 9600UL
#define STR_LEN 64
__no_init uint16_t ovfs;
uint32_t total_ticks;
_no_init uint16_t current_ticks;
uint8_t stringToSend[STR_LEN];
#pragma vector = TIMER3_OVF_vect
__interrupt void Timer3_OVF_vect(void){
ovfs++;
}
void config_timer3();
void config_usart3();
void transmit_usart(uint8_t char_to_send);
int main()
{
uint8_t MCUSRbackup = MCUSR;
MCUSR = 0;
memset(stringToSend,0,16*sizeof(uint8_t));
uint8_t isResetByWD = (MCUSRbackup & (1<<WDRF));
// enable timer here
// it has interrupt on ovf
config_usart3();
if( (ovfs > 0 || current_ticks > 0) && isResetByWD){
uint32_t total_ticks = ((uint32_t)ovfs*65536
UL) + current_ticks;
uint32_t knum = 2048UL * 16000UL;
uint32_t fkhz = knum / total_ticks;
uint32_t rest = knum % total_ticks;
uint32_t fhz = fkhz*1000 + (1000UL*rest)/total_ticks;
snprintf(stringToSend,STR_LEN,"f=%lu\n",fhz);
uint8_t stringLen = strlen(stringToSend);
int i;
for(i = 0; i < stringLen; i++){
transmit_usart(stringToSend[i]);
}
}
config_timer3();
__enable_interrupt();
// setup wd
WDTCSR |= ((1<<WDTCE) | (1<<WDE));
WDTCSR |= (1<<WDE);
asm("WDR");
while(1){
current_ticks = TCNT3;
}
return 0;
}
void config_timer3(){
// mode normal -- no prescaler -- Tovf aprox 4ms
TCNT3 = 0;
ovfs = 0;
current_ticks = 0;
TIMSK3 |= (1<<TOIE3);
TCCR3B |= (1<<CS30);
}
void config_usart3(){
uint16_t baud_rate = (FOSC/16UL)/BAUD_RATE - 1;
UBRR3H = (baud_rate >> 8) & 0x00FF;
UBRR3L = (baud_rate & 0x00FF);
UCSR3C |= ((1<<UCSZ31) | (1<<UCSZ30)); // 8bit
UCRS3B |= ( (1<<RXEN3) | (1<<TXEN3 )); // enable receive and transmit
}
void transmit_usart(uint8_t char_to_send){
while( !(UCSR3A & (1<<UDRE3)) ){
;
}
UDR3 = char_to_send;
}