-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdisplay.c
160 lines (137 loc) · 4.95 KB
/
display.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
/*
* display.c
*
* Author: Tuomas Vaherkoski <[email protected]>
*
* This file is part of variable-power-supply project.
*/
#include <avr/interrupt.h>
#include <avr/io.h>
#include <inttypes.h>
#include "display.h"
#include "peripherals.h"
#include "eventqueue.h"
volatile uint8_t seq_nbr;
volatile uint16_t* readout_p_;
volatile uint16_t static_readout_;
volatile char show_dots;
uint16_t get_readout_segments(uint8_t);
void display_handler(uint16_t);
#define TENS_OFFSET 10
#define HUNDRED_OFFSET 20
#define THOUSAND_OFFSET 30
#define OL 33
#define DOTS 34
#define CUR 35
uint16_t display_data[36][2] = {
{ 0b0000000000111001, 0b0000000001011010 }, // xxx0
{ 0b0000000000110001, 0b0000000000000000 }, // xxx1
{ 0b0000000000101001, 0b0000000001110010 }, // xxx2
{ 0b0000000000111001, 0b0000000000110010 }, // xxx3
{ 0b0000000000110001, 0b0000000000101010 }, // xxx4
{ 0b0000000000011001, 0b0000000000111010 }, // xxx5
{ 0b0000000000011001, 0b0000000001111010 }, // xxx6
{ 0b0000000000111001, 0b0000000000000000 }, // xxx7
{ 0b0000000000111001, 0b0000000001111010 }, // xxx8
{ 0b0000000000111001, 0b0000000000111010 }, // xxx9
{ 0b0000001011000001, 0b0000001110000010 }, // xx0x
{ 0b0000000000000000, 0b0000000110000010 }, // xx1x
{ 0b0000000111000001, 0b0000001100000010 }, // xx2x
{ 0b0000000110000001, 0b0000001110000010 }, // xx3x
{ 0b0000001100000001, 0b0000000110000010 }, // xx4x
{ 0b0000001110000001, 0b0000001010000010 }, // xx5x
{ 0b0000001111000001, 0b0000001010000010 }, // xx6x
{ 0b0000000000000000, 0b0000001110000010 }, // xx7x
{ 0b0000001111000001, 0b0000001110000010 }, // xx8x
{ 0b0000001110000001, 0b0000001110000010 }, // xx9x
{ 0b0001110000000001, 0b0010110000000010 }, // x0xx
{ 0b0001100000000001, 0b0000000000000000 }, // x1xx
{ 0b0001010000000001, 0b0011100000000010 }, // x2xx
{ 0b0001110000000001, 0b0001100000000010 }, // x3xx
{ 0b0001100000000001, 0b0001010000000010 }, // x4xx
{ 0b0000110000000001, 0b0001110000000010 }, // x5xx
{ 0b0000110000000001, 0b0011110000000010 }, // x6xx
{ 0b0001110000000001, 0b0000000000000000 }, // x7xx
{ 0b0001110000000001, 0b0011110000000010 }, // x8xx
{ 0b0001110000000001, 0b0001110000000010 }, // x9xx
{ 0b0000000000000000, 0b0000000000000000 }, // xxxx
{ 0b0110000000000001, 0b0000000000000000 }, // 1xxx
{ 0b1100000000000001, 0b1000000000000010 }, // 2xxx
{ 0b0000001011000001, 0b0000001111011010 }, // OL
{ 0b0000000000000000, 0b0000000000000110 }, // DOTS
{ 0b0000000011000001, 0b0011100011100010 }, // cur
};
void init_display(void) {
init_spi();
DDRD |= _BV(PD0) + _BV(PD1); // LED_VOLTAGE, LED_CURRENT outputs
seq_nbr = 0;
show_dots = 0;
set_static_readout(0);
evq_push(display_handler, 0); // start display
}
void set_dynamic_readout(uint16_t* readout) {
readout_p_ = readout;
}
void set_static_readout(uint16_t readout) {
static_readout_ = readout;
readout_p_ = &static_readout_;
}
void display_dots(void) {
show_dots ^= 1;
}
uint16_t get_readout_segments(uint8_t seq) {
/* Display can show numerical values between 0 - 2999 */
if (*readout_p_ < 3000 && *readout_p_ >= 0) {
uint16_t segments = 0;
int thousands = THOUSAND_OFFSET + (*readout_p_ / 1000);
int hundreds = HUNDRED_OFFSET + (*readout_p_ % 1000) / 100;
int tens = TENS_OFFSET + (*readout_p_ % 100) / 10;
int ones = (*readout_p_ % 10);
segments = display_data[thousands][seq] |
display_data[hundreds][seq] |
display_data[tens][seq] |
display_data[ones][seq];
if(show_dots) {
segments |= display_data[DOTS][seq];
}
return segments;
} else {
/* Other values mapped to special text strings */
switch(*readout_p_) {
case DISPLAY_CUR:
return display_data[CUR][seq];
default:
return 0;
}
}
}
void display_handler(uint16_t null) {
spi_send_word(get_readout_segments(seq_nbr % 2));
seq_nbr++;
// 100Hz refresh-rate
evq_timed_push(display_handler, 0, 10);
}
/* LEDs --------------------------------------------------------------------- */
#define LEDPORT (PORTD)
uint8_t status_led_status(uint8_t led);
void status_led_on(uint16_t led) {
LEDPORT |= led;
}
void status_led_off(uint16_t led) {
LEDPORT &= ~(led);
}
void status_led_toggle(uint16_t led) {
LEDPORT ^= (led);
}
void blink_led(uint16_t led, uint16_t time) {
if(status_led_status(led)) {
status_led_off(led);
evq_timed_push(status_led_on, led, time);
} else {
status_led_on(led);
evq_timed_push(status_led_off, led, time);
}
}
uint8_t status_led_status(uint8_t led) {
return LEDPORT & (uint8_t)(led);
}