You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
atmega-geiger/src/main.c

130 lines
2.8 KiB

#include "twi.h"
#include "ssd1306.h"
#include "sevenseg.h"
#include "adc.h"
#include "iopins.h"
#include <avr/interrupt.h>
const uint16_t adc_target16_acceptable = 900;
const uint16_t adc_target16 = 972;
//const uint8_t adc_target8 = 243;
static bool g_pwm_on = false;
static volatile uint16_t tick_counter = 0;
static volatile bool tick_counter_changed = false;
// Tick
ISR(INT0_vect)
{
tick_counter++;
tick_counter_changed = true;
}
static void init_isr() {
as_input(D2);
// using INT0 - arduino pin D2
EICRA = _BV(ISC01) | _BV(ISC00); // rising edge
EIMSK = _BV(INT0);
}
static void init_pwm_out() {
// Output is OC0A
as_output(D5);
// initialize the timer
// Fast PWM mode, Output to OC0A
// clock is 16MHz, presc /64, counting to 80 -> freq 3125Hz
// Duty cycle = appx. 60%
OCR0A = 80;
OCR0B = 46;
TCCR0A = _BV(WGM00) | _BV(WGM01);
TCCR0B = _BV(CS01) | _BV(CS00) | _BV(WGM02);
}
static void pwm_on() {
TCCR0A |= _BV(COM0B1);
g_pwm_on = true;
}
static void pwm_off() {
TCCR0A &= ~_BV(COM0B1);
g_pwm_on = false;
}
void main() {
TWI_Init();
adc_init();
init_pwm_out();
ssd1306_128x32_i2c_init();
ssd1306_clearScreen();
struct SevenSeg sseg = {
.x0 = 0,
.y0 = 0,
.charwidth = 17,
.thick = 3,
//.charwidth = 16,
//.thick = 1,
.spacing = 4,
};
init_isr();
sei();
// TODO show loading icon
sseg_number(&sseg, 0, 5, 0);
// request ADC meas
adc_async_start_measure_word(0);
// uint16_t cnt = 0;
uint16_t analog;
uint16_t count_boost_fail = 0;
for (;;) {
if (adc_async_ready()) {
analog = adc_async_get_result_word();
adc_async_start_measure_word(0);
bool good_voltage = analog >= adc_target16;
if (g_pwm_on) {
if (good_voltage) {
pwm_off();
count_boost_fail = 0;
} else {
count_boost_fail++;
}
}
else if (!good_voltage) {
pwm_on();
}
// If fail to reach target voltage in reasonable time,
// show weak battery icon and stop trying.
if (count_boost_fail > 50000 && analog < adc_target16_acceptable) {
// TODO weak battery icon
sseg_number(&sseg, 9999, 5, 0);
pwm_off();
for(;;) {}
}
// TODO synchronization?
if (tick_counter_changed) {
tick_counter_changed = false;
sseg_number(&sseg, tick_counter, 5, 0);
}
// if (++cnt > 10000) {
// sseg_number(&sseg, analog, 5, 0);
// cnt = 0;
// }
}
}
}