Patashnik. More...
#include <inttypes.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/pgmspace.h>
#include <avr/wdt.h>
#include <stdio.h>
#include <stdlib.h>
#include <util/delay.h>
#include "usrat.h"
#include "rtc.h"
#include "util.h"
#include "voltage.h"
#include "buttonry.h"
Defines | |
#define | FADETIME 512 |
#define | BLINKTIME 2048 |
#define | BLINKBIT 10 |
Functions | |
void | set_blinkmode (uint8_t mode) |
Set blinkmode. | |
void | initdisplay () |
Init display-related DDRs. | |
void | showtime (uint8_t h1, uint8_t h2, uint8_t m1, uint8_t m2) |
Rehash bits to match the schematic. | |
void | showtime_bcd (uint16_t time) |
Immediately display BCD value on nixies. | |
void | duty_set (uint8_t d) |
Sets tubes duty cycle. Valid values are 1..4. | |
uint8_t | duty_get () |
void | fadeto (uint16_t t) |
uint16_t | get_display_value () |
void | timer0_init () |
Start timer 0. Timer0 runs at 1MHz and overflows at 3906 Hz. | |
ISR (TIMER0_OVF_vect) | |
void | update_daylight (uint16_t time) |
int | main () |
Program main. | |
Variables | |
volatile uint16_t | time = 0 |
current display value | |
volatile uint16_t | timef = 0 |
fadeto display value | |
volatile uint8_t | dispctr = 0 |
counts 0..15 | |
volatile uint8_t | on_duty = 1 |
values 1..4, gets multiplied by 4 | |
volatile uint8_t | blinktick = 0 |
volatile uint8_t | blinkmode |
current blinking mode | |
volatile uint16_t | blinkctr |
blinkmode counter | |
volatile uint8_t | blinkduty |
blinkmode duty | |
volatile uint8_t | fadeduty |
volatile uint8_t | fadectr |
crossfade counters | |
volatile int16_t | fadetime |
crossfade time and trigger, write "-1" to start fade to timef |
Patashnik.
#define BLINKBIT 10 |
#define BLINKTIME 2048 |
#define FADETIME 512 |
uint8_t duty_get | ( | ) | [inline] |
00083 { return on_duty; }
void duty_set | ( | uint8_t | d | ) |
Sets tubes duty cycle. Valid values are 1..4.
00078 { 00079 on_duty = d; 00080 voltage_adjust(0); 00081 }
void fadeto | ( | uint16_t | t | ) |
Start fading time to given value. Transition is performed in TIMER0_OVF_vect and takes FADETIME cycles.
00087 { 00088 timef = t; fadetime = -1; 00089 voltage_adjust(0); 00090 }
uint16_t get_display_value | ( | ) | [inline] |
00092 { 00093 return timef; 00094 }
void initdisplay | ( | ) |
ISR | ( | TIMER0_OVF_vect | ) |
00103 { 00104 uint16_t toDisplay = time; 00105 static uint8_t effDuty; 00106 00107 voltage_adjust_tick(); 00108 00109 if (blinkmode != BLINK_NONE) { 00110 blinkctr = (blinkctr + 1) % BLINKTIME; 00111 if (blinkctr & _BV(BLINKBIT)) { 00112 if (effDuty != blinkduty) { 00113 blinktick = 1; 00114 } 00115 effDuty = blinkduty; 00116 } else { 00117 effDuty = on_duty; 00118 } 00119 } 00120 00121 if (fadetime == -1) { 00122 // start teh fade 00123 fadetime = FADETIME; 00124 fadeduty = 4; 00125 fadectr = 0; 00126 } 00127 00128 if (fadetime != 0) { 00129 fadetime--; 00130 00131 if (fadetime % (FADETIME/4) == 0) { 00132 fadeduty--; 00133 } 00134 00135 if (fadetime == 0) { 00136 fadectr = 0; 00137 time = timef; // end fade 00138 } 00139 } 00140 00141 00142 if (fadectr < fadeduty) { 00143 toDisplay = time; 00144 } 00145 else { 00146 toDisplay = timef; 00147 } 00148 fadectr = (fadectr + 1) & 3; 00149 00150 00151 if (dispctr < on_duty<<2) { 00152 switch (blinkmode) { 00153 case BLINK_HH: 00154 if (dispctr >= (effDuty<<2)) toDisplay |= 0xff00; 00155 break; 00156 case BLINK_MM: 00157 if (dispctr >= (effDuty<<2)) toDisplay |= 0x00ff; 00158 break; 00159 case BLINK_ALL: 00160 if (dispctr >= (effDuty<<2)) toDisplay |= 0xffff; 00161 break; 00162 default: 00163 break; 00164 } 00165 00166 if (on_duty > 2 && dispctr < 4) { 00167 // compensation: burn 2nd, 3rd digits 1/4th shorter in bright modes 00168 toDisplay |= 0x0ff0; 00169 } 00170 } else { 00171 if (on_duty < 3 && (dispctr < (on_duty+1)<<2) && ((toDisplay & 0x00f0) == 0x20) && blinkmode == BLINK_NONE) { 00172 // compensation: burn xx2x 1/4th longer 00173 toDisplay |= 0xff0f; 00174 } else { 00175 toDisplay |= 0xffff; 00176 } 00177 } 00178 00179 showtime_bcd(toDisplay); 00180 00181 dispctr = (dispctr + 1) & 017; 00182 }
int main | ( | ) |
Program main.
00231 { 00232 uint8_t i; 00233 uint16_t rtime; 00234 uint8_t byte; 00235 volatile uint16_t skip = 0; 00236 uint8_t uart_enabled = 0; 00237 00238 pump_nomoar(); 00239 00240 usart_init(F_CPU/16/19200-1); 00241 00242 printf_P(PSTR("\033[2J\033[HB%s WILL I DREAM? %02x\n"), BUILDNUM, MCUCSR); 00243 00244 sei(); 00245 00246 pump_init(); 00247 00248 adc_init(); 00249 00250 00251 initdisplay(); 00252 00253 duty_set(1); 00254 00255 rtc_init(); 00256 00257 buttons_init(); 00258 00259 time = 0xffff; 00260 timef = 0x1838; 00261 fadetime = -1; 00262 00263 timer0_init(); 00264 00265 _delay_ms(1000); 00266 00267 timef = 0xffff; 00268 fadetime = -1; 00269 _delay_ms(750); 00270 00271 wdt_enable(WDTO_250MS); 00272 00273 for(i = 0;;) { 00274 wdt_reset(); 00275 00276 // handle keyboard commands 00277 if (uart_available()) { 00278 byte = uart_getchar(); 00279 switch (uart_enabled) { 00280 case 0: if (byte == 'z') 00281 uart_enabled = 1; 00282 else 00283 uart_enabled = 0; 00284 break; 00285 case 1: if (byte == 'c') 00286 uart_enabled = 2; 00287 else 00288 uart_enabled = 0; 00289 break; 00290 case 2: 00291 switch (byte) { 00292 case '`': pump_nomoar(); 00293 break; 00294 case 'r': rtc_dump(); 00295 break; 00296 case 't': printf_P(PSTR("time=%04x\n"), time); 00297 break; 00298 case 'd': duty_set(on_duty % 4 + 1); 00299 break; 00300 case 'b': blinkmode = (blinkmode + 1) % 4; 00301 blinkduty = 0; 00302 blinkctr = BLINKTIME; 00303 break; 00304 case '.': break; 00305 case '=': // die 00306 for(;;); 00307 break; 00308 default: 00309 break; 00310 } 00311 00312 if (byte >= '0' && byte <= '9') { 00313 byte = byte - '0'; 00314 fadeto((byte<<12)+(byte<<8)+(byte<<4)+byte); 00315 skip = 255; 00316 } 00317 00318 printf_P(PSTR("OCR1A=%d ICR1=%d S=%d V=%d\n"), OCR1A, ICR1, voltage_setpoint, voltage); 00319 break; 00320 } 00321 00322 } 00323 00324 if (skip != 0) { 00325 skip--; 00326 } else { 00327 rtime = rtc_gettime();//voltage; 00328 update_daylight(rtime); 00329 if (!is_setting() && rtime != time && rtime != timef) { 00330 fadeto(rtime); 00331 } 00332 } 00333 00334 buttonry_tick(PIND & _BV(3), PIND & _BV(4)); 00335 00336 if (blinktick) { 00337 blinktick = 0; 00338 if (blinkhandler != NULL) { 00339 blinkhandler(1); 00340 } 00341 } 00342 00343 _delay_ms(50); 00344 } 00345 }
void set_blinkmode | ( | uint8_t | mode | ) | [inline] |
Set blinkmode.
00051 { 00052 blinkmode = mode; 00053 }
void showtime | ( | uint8_t | h1, | |
uint8_t | h2, | |||
uint8_t | m1, | |||
uint8_t | m2 | |||
) | [inline] |
Rehash bits to match the schematic.
00063 { 00064 PORTA = (PORTA & ~017) | ((m2&4)<<1) | ((m2&8)>>2) | (m2&1) | ((m2&2)<<1); 00065 00066 PORTB = (PORTB & ~017) | ((m1&1)<<3) | (m1&2) | ((m1&4)>>2) | ((m1&8)>>1); 00067 00068 PORTC = ((h2&1)<<3) | (h2&2) | ((h2&4)>>2) | ((h2&8)>>1) | 00069 ((((h1&1)<<3)| (h1&2) | ((h1&4)>>2) | ((h1&8)>>1)) << 4); 00070 }
void showtime_bcd | ( | uint16_t | time | ) |
void timer0_init | ( | ) |
void update_daylight | ( | uint16_t | time | ) |
Update DST: 02:00->03:00 on the last sunday of March 03:00->02:00 on the last sunday of October
And try to do this only once.
00190 { 00191 static uint8_t daylight_adjusted = 0; 00192 00193 if (time == 0x0000) daylight_adjusted = 0; 00194 00195 if (daylight_adjusted) return; 00196 00197 if (time == 0x0200 || time == 0x0300) { 00198 if (rtc_xdow(-1) == 0) { 00199 switch (rtc_xmonth(-1)) { 00200 case 3: 00201 if (rtc_xday(-1) > 0x24) { 00202 // last sunday of march 00203 if (time == 0x0200) { 00204 rtc_xhour(3); 00205 daylight_adjusted = 1; 00206 } 00207 } else { 00208 daylight_adjusted = 1; 00209 } 00210 break; 00211 case 10: 00212 if (rtc_xday(-1) > 0x24) { 00213 // last sunday of october 00214 if (time == 0x0300) { 00215 rtc_xhour(2); 00216 daylight_adjusted = 1; 00217 } 00218 } else { 00219 daylight_adjusted = 1; 00220 } 00221 break; 00222 default: 00223 daylight_adjusted = 1; 00224 break; 00225 } 00226 } 00227 } 00228 }
volatile uint16_t blinkctr |
blinkmode counter
volatile uint8_t blinkduty |
blinkmode duty
volatile uint8_t blinkmode |
current blinking mode
volatile uint8_t blinktick = 0 |
volatile uint8_t dispctr = 0 |
counts 0..15
volatile uint8_t fadectr |
crossfade counters
volatile uint8_t fadeduty |
volatile int16_t fadetime |
crossfade time and trigger, write "-1" to start fade to timef
volatile uint8_t on_duty = 1 |
values 1..4, gets multiplied by 4
volatile uint16_t time = 0 |
current display value
volatile uint16_t timef = 0 |
fadeto display value