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/sevenseg.c

146 lines
3.5 KiB

/**
* TODO file description
*/
#include <avr/pgmspace.h>
#include "sevenseg.h"
#include "ssd1306.h"
void sseg_home(struct SevenSeg *disp) {
disp->x = 0;
}
enum SevenSegBars {
T=1, RT=2, RB=4, B=8, LB=16, LT=32, M=64
};
static const uint8_t PROGMEM seven[] = {
[0] = T|RT|RB|B|LB|LT,
[1] = RT|RB,
[2] = T|RT|M|LB|B,
[3] = T|RT|M|RB|B,
[4] = RT|RB|M|LT,
[5] = T|LT|M|RB|B,
[6] = T|LT|LB|B|RB|M,
[7] = T|RT|RB,
[8] = T|LT|RT|LB|RB|B|M,
[9] = T|LT|RT|RB|B|M,
};
static void draw_7seg_dig(uint8_t x, uint8_t y, uint8_t w, uint8_t th, uint8_t digit) {
uint8_t mask = digit == 255 ? 0 : pgm_read_byte(&seven[digit]);
const uint8_t v = w - th * 2;
const uint8_t subs = 1;
ssd1306_setColor((mask & T) ? 0xFFFF : 0);
ssd1306_fillRect(
x + th,
y + 0,
x + th + v - subs,
y + th - subs);
ssd1306_setColor((mask & M) ? 0xFFFF : 0);
ssd1306_fillRect(
x + th,
y + th + v,
x + th + v - subs,
y + th * 2 + v - subs);
ssd1306_setColor((mask & B) ? 0xFFFF : 0);
ssd1306_fillRect(
x + th,
y + th * 2 + v * 2,
x + th + v - subs,
y + th * 3 + v * 2 - subs);
ssd1306_setColor((mask & LT) ? 0xFFFF : 0);
ssd1306_fillRect(
x + 0,
y + th,
x + th - subs,
y + th + v - subs);
ssd1306_setColor((mask & RT) ? 0xFFFF : 0);
ssd1306_fillRect(
x + th + v,
y + th,
x + th * 2 + v - subs,
y + th + v - subs);
ssd1306_setColor((mask & LB) ? 0xFFFF : 0);
ssd1306_fillRect(
x + 0,
y + th * 2 + v,
x + th - subs,
y + th * 2 + v * 2 - subs);
ssd1306_setColor((mask & RB) ? 0xFFFF : 0);
ssd1306_fillRect(
x + th + v,
y + th * 2 + v,
x + th * 2 + v - subs,
y + th * 2 + v * 2 - subs);
}
static void draw_7seg_period(uint8_t x, uint8_t y, uint8_t w, uint8_t th) {
const uint8_t v = w - th * 2;
const uint8_t subs = 1;
ssd1306_setColor(0xFFFF);
ssd1306_fillRect(
x,
y + th * 2 + v * 2,
x + th - subs,
y + th * 3 + v * 2 - subs);
}
void sseg_digit(struct SevenSeg *disp, uint8_t digit) {
draw_7seg_dig(disp->x, disp->y0, disp->charwidth, disp->thick, digit);
disp->x += disp->charwidth + disp->spacing;
}
void sseg_blank(struct SevenSeg *disp) {
draw_7seg_dig(disp->x, disp->y0, disp->charwidth, disp->thick, 255);
disp->x += disp->charwidth + disp->spacing;
}
void sseg_period(struct SevenSeg *disp) {
draw_7seg_period(disp->x, disp->y0, disp->charwidth, disp->thick);
disp->x += disp->thick + disp->spacing;
}
void sseg_number(struct SevenSeg *disp, uint32_t num, uint8_t places, uint8_t decimals) {
uint8_t digits[5] = {};
uint8_t pos = 4;
while (num > 0) {
uint8_t res = num % 10;
num /= 10;
digits[pos] = res;
pos--;
}
sseg_home(disp);
bool drawing = false;
for (uint8_t i = 5 - places; i < 5; i++) {
uint8_t d = digits[i];
if (i == 5 - decimals) {
sseg_period(disp);
}
if (!drawing && d == 0) {
if (i == 5 - decimals - 1) {
sseg_digit(disp, d);
drawing = true;
} else {
sseg_blank(disp);
}
} else {
sseg_digit(disp, d);
drawing = true;
}
}
}