usv/h and other improvements, use float
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Empty battery
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "ssd1306.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
void show_empty_battery()
|
||||
{
|
||||
ssd1306_clearScreen();
|
||||
|
||||
// *********
|
||||
// **** *
|
||||
// **** x *
|
||||
// **** *
|
||||
// *********
|
||||
|
||||
#define capwid 6
|
||||
#define hei 24
|
||||
#define caphei 12
|
||||
#define wid 50
|
||||
#define thic 2
|
||||
#define inpad 2
|
||||
#define charge 2
|
||||
|
||||
#define ofsx ((DISPLAY_W - capwid - wid)/2)
|
||||
#define ofsy ((DISPLAY_H - hei)/2)
|
||||
|
||||
const uint8_t rects[6][4] = {
|
||||
// cap
|
||||
{
|
||||
0, (hei - caphei) / 2,
|
||||
capwid - 1, hei - (hei - caphei) / 2 - 1
|
||||
},
|
||||
// left line
|
||||
{
|
||||
capwid, 0,
|
||||
capwid+thic - 1, hei - 1
|
||||
},
|
||||
// top line
|
||||
{
|
||||
capwid + thic, 0,
|
||||
capwid + wid - thic - 1, thic - 1
|
||||
},
|
||||
// right line
|
||||
{
|
||||
capwid + wid - thic, 0,
|
||||
capwid + wid - 1, hei - 1
|
||||
},
|
||||
// "remaining charge" line
|
||||
{
|
||||
capwid + wid - thic - inpad - charge, thic + inpad,
|
||||
capwid + wid - thic - inpad - 1, hei - thic - inpad - 1
|
||||
},
|
||||
// bottom line
|
||||
{
|
||||
capwid + thic, hei - thic,
|
||||
capwid + wid - thic - 1, hei - 1
|
||||
}
|
||||
};
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
ssd1306_fillRect(
|
||||
ofsx + rects[i][0],
|
||||
ofsy + rects[i][1],
|
||||
ofsx + rects[i][2],
|
||||
ofsy + rects[i][3]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Loading
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "ssd1306.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
|
||||
void show_loading_screen(uint8_t progress_percent, bool clear)
|
||||
{
|
||||
if (clear) {
|
||||
ssd1306_clearScreen();
|
||||
}
|
||||
|
||||
// bar in a box
|
||||
|
||||
#define hei 20
|
||||
#define wid DISPLAY_W
|
||||
#define thic 2
|
||||
#define inpad 3
|
||||
|
||||
#define ofsx ((DISPLAY_W - wid)/2)
|
||||
#define ofsy ((DISPLAY_H - hei)/2)
|
||||
|
||||
const uint8_t rects[4][4] = {
|
||||
// top
|
||||
{
|
||||
0, 0,
|
||||
wid - 1, thic - 1
|
||||
},
|
||||
// left
|
||||
{
|
||||
0, thic,
|
||||
thic - 1, hei - thic - 1
|
||||
},
|
||||
// right
|
||||
{
|
||||
wid - thic, thic,
|
||||
wid - 1, hei - thic - 1
|
||||
},
|
||||
// bot
|
||||
{
|
||||
0, hei - thic,
|
||||
wid - 1, hei - 1
|
||||
},
|
||||
};
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
ssd1306_fillRect(
|
||||
ofsx + rects[i][0],
|
||||
ofsy + rects[i][1],
|
||||
ofsx + rects[i][2],
|
||||
ofsy + rects[i][3]
|
||||
);
|
||||
}
|
||||
//
|
||||
ssd1306_fillRect(
|
||||
ofsx + thic + inpad,
|
||||
ofsy + thic + inpad,
|
||||
ofsx + (uint8_t)(((uint16_t)wid * (uint16_t)progress_percent)/(uint16_t)100) - thic - inpad - 1,
|
||||
ofsy + hei - thic - inpad - 1
|
||||
);
|
||||
}
|
||||
+2
-2
@@ -12,8 +12,8 @@
|
||||
static volatile bool is_pwm_on = false;
|
||||
|
||||
// tube starting voltage is 350V
|
||||
#define TURN_ON_VOLTAGE 355.0
|
||||
#define TURN_OFF_VOLTAGE 380.0
|
||||
#define TURN_ON_VOLTAGE 360.0
|
||||
#define TURN_OFF_VOLTAGE 390.0
|
||||
#define MINIMAL_VOLTAGE 350.0
|
||||
|
||||
// sensing via resistive divider
|
||||
|
||||
+6
-1
@@ -19,6 +19,8 @@ void __attribute__((noreturn)) main()
|
||||
{
|
||||
init_user_interface();
|
||||
|
||||
show_loading_screen(0, true);
|
||||
|
||||
init_timebase();
|
||||
init_radiation();
|
||||
|
||||
@@ -54,10 +56,13 @@ void __attribute__((noreturn)) shutdown_due_to_weak_battery()
|
||||
cli();
|
||||
hv_disable();
|
||||
|
||||
show_empty_battery_icon();
|
||||
show_empty_battery();
|
||||
// try to preserve power; but the display will still drain the battery.
|
||||
// we should probably shut it off too.
|
||||
|
||||
_delay_ms(2000);
|
||||
turn_off_display();
|
||||
|
||||
for (;;) {
|
||||
sleep_enable();
|
||||
sleep_cpu();
|
||||
|
||||
+134
-6
@@ -8,23 +8,35 @@
|
||||
#include "iopins.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdbool.h>
|
||||
#include <util/atomic.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#define MEAS_BIN_COUNT 120
|
||||
typedef uint8_t meas_bin_t;
|
||||
#define MEAS_MAX_COUNT 255
|
||||
typedef uint8_t ticks_t;
|
||||
typedef uint8_t binnum_t;
|
||||
#define TICKS_MAX 255
|
||||
|
||||
#define NEEDED_TICKS_FOR_VALUE_DISPLAY 5
|
||||
|
||||
#define TICKS_NEEDED_FOR_AUTORANGE 15
|
||||
|
||||
uint16_t get_tick_count_in_bins(binnum_t bincount);
|
||||
|
||||
/// measurements in the last X seconds
|
||||
static volatile meas_bin_t measurements[MEAS_BIN_COUNT];
|
||||
static volatile ticks_t measurements[MEAS_BIN_COUNT];
|
||||
/// Currently active measurement bin, increments once per second
|
||||
static volatile uint8_t meas_bin = 0;
|
||||
static volatile binnum_t meas_bin = 0;
|
||||
static volatile binnum_t meas_oldest_bin = 0;
|
||||
static volatile binnum_t num_live_bins = 1;
|
||||
|
||||
static volatile binnum_t num_observed_bins = 60;
|
||||
|
||||
// geiger tube pin change interrupt
|
||||
ISR(INT0_vect)
|
||||
{
|
||||
if (measurements[meas_bin] < MEAS_MAX_COUNT) {
|
||||
if (measurements[meas_bin] < TICKS_MAX) {
|
||||
measurements[meas_bin]++;
|
||||
}
|
||||
req_update_display = true;
|
||||
@@ -33,11 +45,41 @@ ISR(INT0_vect)
|
||||
void second_callback_irq()
|
||||
{
|
||||
meas_bin++;
|
||||
if (num_live_bins < MEAS_BIN_COUNT) {
|
||||
num_live_bins++;
|
||||
}
|
||||
if (meas_bin >= MEAS_BIN_COUNT) {
|
||||
meas_bin = 0;
|
||||
}
|
||||
|
||||
if (meas_oldest_bin == meas_bin) {
|
||||
meas_oldest_bin++;
|
||||
if (meas_oldest_bin >= MEAS_BIN_COUNT) {
|
||||
meas_oldest_bin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
measurements[meas_bin] = 0;
|
||||
req_update_display = true;
|
||||
|
||||
/* autoranging */
|
||||
|
||||
uint16_t count;
|
||||
bool found_range = 0;
|
||||
for (int i = 5; i <= 60; i += 5) {
|
||||
count = get_tick_count_in_bins(i);
|
||||
if (count > TICKS_NEEDED_FOR_AUTORANGE) {
|
||||
num_observed_bins = i * 2;
|
||||
if (num_observed_bins > num_live_bins) {
|
||||
num_observed_bins = num_live_bins;
|
||||
}
|
||||
found_range = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found_range) {
|
||||
num_observed_bins = num_live_bins;
|
||||
}
|
||||
}
|
||||
|
||||
void init_radiation() {
|
||||
@@ -50,3 +92,89 @@ void init_radiation() {
|
||||
EICRA = _BV(ISC01) | _BV(ISC00); // rising edge
|
||||
EIMSK = _BV(INT0);
|
||||
}
|
||||
|
||||
uint8_t rad_get_progress() {
|
||||
ticks_t ticks = get_tick_count_in_bins(num_live_bins);
|
||||
|
||||
if (ticks >= NEEDED_TICKS_FOR_VALUE_DISPLAY) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
return (((uint16_t)ticks * 100) / (uint16_t)NEEDED_TICKS_FOR_VALUE_DISPLAY);
|
||||
}
|
||||
|
||||
uint16_t get_tick_count_in_bins(binnum_t bincount) {
|
||||
if (bincount == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t all_ticks = 0;
|
||||
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||
|
||||
// going backwards
|
||||
binnum_t bin = meas_bin;
|
||||
for (;;) {
|
||||
ticks_t in_bin = measurements[bin];
|
||||
if ((0xFFFF - all_ticks) < in_bin) {
|
||||
all_ticks = 0xFFFF;
|
||||
} else {
|
||||
all_ticks += in_bin;
|
||||
}
|
||||
|
||||
if (bin == meas_oldest_bin) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (bincount > 0) {
|
||||
bincount--;
|
||||
if (bincount == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bin > 0) {
|
||||
bin--;
|
||||
} else {
|
||||
bin = MEAS_BIN_COUNT - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return all_ticks;
|
||||
}
|
||||
|
||||
uint16_t rad_get_cpm() {
|
||||
// bins take 1 second
|
||||
|
||||
float count = get_tick_count_in_bins(num_observed_bins);
|
||||
float cpm = (count / (float)num_observed_bins) * 60.0f;
|
||||
return (uint16_t) roundf(cpm * 10.0f);
|
||||
}
|
||||
|
||||
uint16_t rad_get_usvh(uint8_t *out_decimals) {
|
||||
float count = get_tick_count_in_bins(num_observed_bins);
|
||||
float cpm = (count / (float)num_observed_bins) * 60.0f;
|
||||
|
||||
// https://sites.google.com/site/diygeigercounter/technical/gm-tubes-supported
|
||||
|
||||
float usvh = (cpm / 153.8f);
|
||||
|
||||
if (usvh < 99.0f) {
|
||||
*out_decimals = 3;
|
||||
return (uint16_t) roundf(usvh * 1000.0f);
|
||||
}
|
||||
|
||||
if (usvh < 999.0f) {
|
||||
*out_decimals = 2;
|
||||
return (uint16_t) roundf(usvh * 100.0f);
|
||||
}
|
||||
|
||||
if (usvh < 9999.0f) {
|
||||
*out_decimals = 1;
|
||||
return (uint16_t) roundf(usvh * 10.0f);
|
||||
}
|
||||
|
||||
*out_decimals = 0;
|
||||
return (uint16_t) roundf(usvh);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,17 @@
|
||||
#ifndef CPROJ_RADIATION_H
|
||||
#define CPROJ_RADIATION_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void init_radiation();
|
||||
|
||||
/// get progress 0-100, 100 = normal radiation resumed
|
||||
uint8_t rad_get_progress();
|
||||
|
||||
|
||||
uint16_t rad_get_cpm();
|
||||
/// Get current radiation dose rate u uSv/h, x10 (one decimal place)
|
||||
uint16_t rad_get_usvh(uint8_t *out_decimals);
|
||||
|
||||
#endif //CPROJ_RADIATION_H
|
||||
|
||||
@@ -3,8 +3,10 @@
|
||||
*/
|
||||
|
||||
#include "time_base.h"
|
||||
#include "global_state.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
/// timestamp counted in units of 100ms
|
||||
@@ -17,6 +19,9 @@ ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
timestamp_100ms++;
|
||||
|
||||
|
||||
req_update_display = true;
|
||||
|
||||
subsec_counter++;
|
||||
if (subsec_counter == 10) {
|
||||
subsec_counter = 0;
|
||||
|
||||
+42
-14
@@ -7,6 +7,9 @@
|
||||
#include "ssd1306.h"
|
||||
#include "sevenseg.h"
|
||||
#include "global_state.h"
|
||||
#include "radiation.h"
|
||||
|
||||
static bool ended_loading = false;
|
||||
|
||||
static struct SevenSeg sseg = {
|
||||
.x0 = 0,
|
||||
@@ -18,31 +21,56 @@ static struct SevenSeg sseg = {
|
||||
.spacing = 4,
|
||||
};
|
||||
|
||||
void clear_screen()
|
||||
{
|
||||
ssd1306_clearScreen();
|
||||
}
|
||||
|
||||
void init_user_interface()
|
||||
{
|
||||
TWI_Init();
|
||||
ssd1306_128x32_i2c_init();
|
||||
ssd1306_clearScreen();
|
||||
|
||||
// can't show anything useful at least until the first tick arrives, but more than 1 tick is needed
|
||||
show_loading_icon();
|
||||
}
|
||||
|
||||
void turn_off_display() {
|
||||
ssd1306_displayOff();
|
||||
}
|
||||
|
||||
static volatile uint16_t last_value = 0;
|
||||
static volatile uint16_t last_value_d = 0;
|
||||
void show_current_radiation()
|
||||
{
|
||||
// TODO
|
||||
sseg_number(&sseg, timestamp_100ms, 5, 0);
|
||||
// this is called from main, so we can sleep
|
||||
|
||||
if (!ended_loading) {
|
||||
int progress = rad_get_progress();
|
||||
if (progress == 100) {
|
||||
show_loading_screen(100, false);
|
||||
ended_loading = true;
|
||||
|
||||
// so user sees it
|
||||
_delay_ms(250);
|
||||
|
||||
clear_screen();
|
||||
// start showing values
|
||||
} else {
|
||||
if (progress < 10) progress = 10;
|
||||
show_loading_screen(progress, false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void show_empty_battery_icon()
|
||||
{
|
||||
// TODO
|
||||
sseg_number(&sseg, 9999, 5, 0);
|
||||
// uint16_t cpm = rad_get_cpm();
|
||||
// if (cpm != last_value) {
|
||||
// last_value = cpm;
|
||||
// sseg_number(&sseg, cpm, 5, 1);
|
||||
// }
|
||||
uint8_t decimals = 0;
|
||||
uint16_t usvh = rad_get_usvh(&decimals);
|
||||
if (usvh != last_value || decimals != last_value_d) {
|
||||
last_value = usvh;
|
||||
last_value_d = decimals;
|
||||
sseg_number(&sseg, usvh, 5, decimals);
|
||||
}
|
||||
|
||||
void show_loading_icon()
|
||||
{
|
||||
// TODO
|
||||
sseg_number(&sseg, 0, 5, 0);
|
||||
}
|
||||
|
||||
+12
-2
@@ -5,12 +5,22 @@
|
||||
#ifndef CPROJ_USER_INTERFACE_H
|
||||
#define CPROJ_USER_INTERFACE_H
|
||||
|
||||
#define DISPLAY_W 128
|
||||
#define DISPLAY_H 32
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void clear_screen();
|
||||
|
||||
void init_user_interface();
|
||||
|
||||
void show_current_radiation();
|
||||
|
||||
void show_empty_battery_icon();
|
||||
void show_empty_battery();
|
||||
|
||||
void show_loading_icon();
|
||||
void show_loading_screen(uint8_t progress_percent, bool clear);
|
||||
|
||||
void turn_off_display();
|
||||
|
||||
#endif //CPROJ_USER_INTERFACE_H
|
||||
|
||||
Reference in New Issue
Block a user