main.c File Reference

Satashnik. 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"
#include "modes.h"
#include "cal.h"
Include dependency graph for main.c:

Defines

#define TIMERCOUNT   25

Functions

void savingmode_keep (uint16_t hhmm)
void initdisplay ()
 Init display-related DDRs.
uint8_t swapbits (uint8_t x)
 Rehash bits to match the schematic.
uint16_t getrawdigits (uint8_t h1, uint8_t h2, uint8_t m1, uint8_t m2)
 get raw digits from hh:mm
uint16_t getrawdigits_bcd (uint16_t time)
 get raw digits from a BCD value
uint8_t display_currentdigit (uint8_t n)
 Output the current digit code to ID1.
void display_selectdigit (uint8_t n)
void fadeto (uint16_t t)
uint16_t get_display_value ()
 Return current BCD display value.
void timer0_init ()
 ISR (TIMER0_OVF_vect)
void calibrate_blinking ()
 Calibrate blink counters to quarters of second.
int main ()
 Program main.

Variables

volatile uint16_t time = 0
 current display value
volatile uint16_t timef = 0
 fadeto display value
volatile uint8_t digitmux = 0
 displayed digit, 0..3
volatile uint16_t digitsraw = 0
 raw port values
volatile uint16_t rawfadefrom = 0177777
 digitsraw fade from
volatile uint16_t rawfadeto = 0177777
 digitsraw fade to
volatile uint8_t blinktick = 0
 1 when a pressed button is autorepeated
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
volatile uint8_t halfbright
 keep low duty
uint16_t bcq1
 Values for blinking, calibrated to quarters of a second at startup.
uint16_t bcq2
uint16_t bcq3

Detailed Description

Satashnik.

Author:
Viacheslav Slavinsky

Define Documentation

#define TIMERCOUNT   25

Function Documentation

void calibrate_blinking (  ) 

Calibrate blink counters to quarters of second.

00289                           {
00290     bcq1 = bcq2 = bcq3 = 65535;
00291     for(bcq1 = rtc_gettime(1); bcq1 == rtc_gettime(1););
00292     blinkctr = 0; 
00293     for(bcq1 = rtc_gettime(1); bcq1 == rtc_gettime(1););
00294     cli();
00295     bcq1 = blinkctr/4;
00296     bcq2 = 2*blinkctr/4;
00297     bcq3 = 3*blinkctr/4;
00298     sei();
00299 }

Here is the call graph for this function:

uint8_t display_currentdigit ( uint8_t  n  ) 

Output the current digit code to ID1.

00108                                         {
00109     uint8_t dispbit = 0x0f;
00110     
00111     if (n < 4) {
00112         dispbit = 0x0f & (digitsraw >> (n<<2));
00113         PORTDIGIT = (PORTDIGIT & ~BV4(0,1,2,3)) | dispbit;
00114     } else {
00115         PORTDIGIT |= 0x0f;
00116     }
00117     
00118     return dispbit != 0x0f;
00119 }

void display_selectdigit ( uint8_t  n  ) 

Shut off previous anode, wait to prevent ghosting, output new digit code to ID1 and enable new anode

00123                                     {
00124     switch (n) {
00125         case SA1: 
00126                 PORTSA234 &= ~BV3(5,6,7);
00127                 _delay_ms(0.01); //ghosting prevention
00128                 if (display_currentdigit(n)) {
00129                     PORTSA1 |= _BV(0);
00130                 }
00131                 break;
00132         case SA2:
00133         case SA3:
00134         case SA4:
00135                 PORTSA1 &= ~_BV(0);
00136                 PORTSA234 &= ~BV3(5,6,7);
00137                 _delay_ms(0.01); //ghosting prevention
00138                 if (display_currentdigit(n)) {
00139                     PORTSA234 |= 0200 >> (n-1);
00140                 }
00141                 break;
00142         default:
00143                 PORTSA234 &= ~BV3(5,6,7);
00144                 PORTSA1 &= ~_BV(0);
00145                 break;
00146     }
00147 }

Here is the call graph for this function:

void fadeto ( uint16_t  t  ) 

Start fading time to given value. Transition is performed in TIMER0_OVF_vect and takes FADETIME cycles.

00151                         { 
00152     uint16_t raw = getrawdigits_bcd(t); // takes time
00153     cli();
00154     timef = t; 
00155     rawfadeto = raw;
00156     fadetime = -1;
00157     sei();
00158 }

Here is the call graph for this function:

uint16_t get_display_value (  )  [inline]

Return current BCD display value.

00161                                     {
00162     return timef;
00163 }

uint16_t getrawdigits ( uint8_t  h1,
uint8_t  h2,
uint8_t  m1,
uint8_t  m2 
)

get raw digits from hh:mm

00098                                                                       {
00099     return (swapbits(h1)<<12) | (swapbits(h2)<<8) | (swapbits(m1)<<4) | swapbits(m2);
00100 }

Here is the call graph for this function:

uint16_t getrawdigits_bcd ( uint16_t  time  ) 

get raw digits from a BCD value

00103                                          {
00104     return getrawdigits((time & 0xf000)>>12, (time & 0x0f00)>>8, (time & 0x00f0)>>4, time & 0x000f);
00105 }

Here is the call graph for this function:

void initdisplay (  ) 

Init display-related DDRs.

00085                    {
00086     DDRDIGIT |= BV4(0,1,2,3);
00087     DDRDOT |= _BV(DOT);
00088     DDRSA1 |= _BV(0);
00089     DDRSA234 |= BV3(5,6,7);
00090 }

ISR ( TIMER0_OVF_vect   ) 

00173                      {
00174     uint16_t toDisplay = time;
00175     static uint8_t odd = 0;
00176     
00177     TCNT0 = 256-TIMERCOUNT;
00178 
00179     odd += 1;
00180 
00181     // Handle the dot, which must be sustained at all times
00182     // High-frequency short-duty seems to be an acceptable way
00183     // of keeping the gas ionized, yet practically invisible
00184     if ((odd & 7) < (( (dotmode == DOT_OFF || blinkctr>bcq2) && !(dotmode == DOT_ON)) ? 0:1) 
00185         || ((dotmode == DOT_BLINK) && ((blinkctr <= 4) || ((odd & 0x7f) == 0)))) {
00186         PORTDOT |= _BV(DOT);
00187     } else {
00188         PORTDOT &= ~_BV(DOT);
00189     }
00190     
00191     // Signal the main loop to continue rolling
00192     if ((odd & 0x3f) == 0) {
00193         blinktick |= _BV(2);
00194     }
00195     
00196     // A "slow" cycle every 32 fast cycles, display business
00197     if ((odd & 0x1f) == 0) {
00198         // keep blinkctr for things that happen on 1/4ths of a second
00199         blinkctr++;
00200         if (blinkctr > (bcq2<<1)) {
00201             blinkctr = 0;
00202         }
00203         
00204         // signal the main loop to autorepeat buttons when needed
00205         if (blinkmode_get() != BLINK_NONE) {
00206             if (blinkctr == bcq1 || blinkctr == bcq2 || blinkctr == bcq3 || blinkctr == 1) {
00207                 blinktick |= _BV(1);
00208             }
00209         }
00210         
00211         // fadetime == -1 indicates start of fade
00212         if (fadetime == -1) {
00213             if (fade_get() == FADE_OFF) {
00214                 fadeduty = 1;
00215                 fadetime = 1;
00216             } else {
00217                 // start teh fade
00218                 fadetime = fadetime_full;
00219                 fadeduty = 4;
00220                 fadectr = 0;
00221             }
00222         }
00223         
00224         if (fadetime != 0) {
00225             fadetime--;
00226     
00227             if (fadetime % fadetime_quart == 0) {
00228                 fadeduty--;
00229             }
00230             
00231             if (fadetime == 0) {
00232                 fadectr = 0;
00233                 time = timef; // end fade
00234                 rawfadefrom = rawfadeto;
00235             }
00236         } 
00237         
00238         if ((fadectr>>3) < fadeduty) {
00239             toDisplay = rawfadefrom;
00240         } else {
00241             toDisplay = rawfadeto;
00242         }
00243         fadectr = (fadectr + 1) & 037;
00244     
00245         // blinking (blinkmode & 0200 temporarily disables blinking)
00246         if (blinkmode_get() != BLINK_NONE && (blinkmode_get() & 0200) == 0 && blinkctr > bcq2) {
00247             switch (blinkmode_get()) {
00248                 case BLINK_HH:
00249                     toDisplay |= 0xff00;
00250                     break;
00251                 case BLINK_MM:
00252                     toDisplay |= 0x00ff;
00253                     break;
00254                 case BLINK_ALL:
00255                     toDisplay |= 0xffff;
00256                     break;
00257                 default:
00258                     break;
00259             }
00260         }
00261     
00262         digitsraw = toDisplay;
00263     }
00264     
00265     // every other "slow" cycle, select the next digit...
00266     if ((odd & 0x1f) == 0) {
00267         display_selectdigit(digitmux);
00268         digitmux = (digitmux + 1) & 3;
00269     } else {
00270         // switch bright digits earlier
00271         if ((odd & 0x1f) == 0x18) {
00272             switch (PORTDIGIT & 017) {
00273                 case 0x0a: // "3"
00274                     display_selectdigit(0377);
00275                     break;
00276             }
00277         }
00278         // shorten duty cycle for cathode-preserving modes
00279         if (halfbright == 2 && (odd & 0x1f) == 0x8) {
00280             display_selectdigit(0377);
00281         }
00282         if (halfbright == 1 && (odd & 0x1f) == 0x10) {
00283             display_selectdigit(0377);
00284         }
00285     }
00286 }

Here is the call graph for this function:

int main (  ) 

Program main.

00302            {
00303     uint8_t i;
00304     uint16_t rtime;
00305     uint8_t byte;
00306     volatile uint16_t skip = 0;
00307     uint8_t uart_enabled = 0;
00308     volatile uint16_t mmss, mmss1;
00309     
00310     pump_nomoar();
00311     
00312     usart_init(F_CPU/16/19200-1);
00313     
00314     printf_P(PSTR("\033[2J\033[HB%s WHAT DO YOU MEAN? %02x\n"), BUILDNUM, MCUCSR);
00315 
00316     sei();
00317 
00318     voltage_start();        // start HV generation    
00319     initdisplay();
00320     dotmode_set(DOT_OFF);
00321     rtc_init();
00322     buttons_init();
00323 
00324     // display greeting
00325     fade_set(FADE_SLOW);
00326     rtime = time = timef = 0xffff;   
00327     timer0_init();
00328     fadeto(0x1838);
00329 
00330     // calibrate blink quarters and fadeout
00331     calibrate_blinking();
00332     fade_set(FADE_SLOW);    
00333     fadeto(0xffff);
00334     _delay_ms(500);
00335     
00336     dotmode_set(DOT_BLINK);
00337     
00338     wdt_enable(WDTO_250MS);
00339     
00340     set_sleep_mode(SLEEP_MODE_IDLE);
00341     
00342     for(i = 0;;i++) {
00343         wdt_reset();
00344         
00345         // handle keyboard commands
00346         if (uart_available()) {
00347             byte = uart_getchar();
00348             switch (uart_enabled) {
00349                 case 0: if (byte == 'z') 
00350                             uart_enabled = 1;
00351                         else
00352                             uart_enabled = 0;
00353                         break;
00354                 case 1: if (byte == 'c') 
00355                             uart_enabled = 2;
00356                         else
00357                             uart_enabled = 0;
00358                         break;
00359                 case 2:
00360                         switch (byte) { 
00361                         case '`':   pump_nomoar();
00362                                     break;
00363                         case '.':   break;
00364                         case '=':   // die
00365                                     for(;;);
00366                                     break;
00367                         default:
00368                                     break;
00369                         }
00370             
00371                         if (byte >= '0' && byte <= '9') {
00372                             byte = byte - '0';
00373                             fadeto((byte<<12)+(byte<<8)+(byte<<4)+byte);
00374                             skip = 255;
00375                         }
00376                         
00377                         printf_P(PSTR("OCR1A=%d ICR1=%d S=%d V=%d, Time=%04x\n"), OCR1A, ICR1, voltage_setpoint_get(), voltage_get(), time);
00378                         break;
00379             }
00380         }
00381         
00382         buttonry_tick();
00383     
00384         if ((blinktick & _BV(1)) != 0) {        
00385             blinktick &= ~_BV(1);
00386             if (blinkhandler != NULL) {
00387                 blinkhandler(1);
00388             }
00389         }
00390         
00391         if (skip != 0) {
00392             skip--;
00393         } else {
00394             mmss = rtc_gettime(1);
00395             if (!is_setting() && mmss != mmss1) {
00396                 mmss1 = mmss;
00397                 cli(); blinkctr = 0; sei();
00398             }
00399             
00400             rtime = rtc_gettime(0);
00401             
00402             update_daylight(rtime);
00403             
00404             savingmode_keep(rtime);
00405             
00406             switch (mode_get()) {
00407                 case HHMM:
00408                     rtime = rtc_gettime(0);
00409                     break;
00410                 case MMSS:
00411                     rtime = mmss;
00412                     break;
00413                 case VOLTAGE:
00414                     rtime = voltage_getbcd();
00415                     break;
00416             }
00417             
00418             if (!is_setting() && rtime != time && rtime != timef) {
00419                 fadeto(rtime);
00420             }     
00421         }
00422         
00423         // just waste time
00424         while((blinktick & _BV(2)) == 0) {
00425             sleep_enable();
00426             sleep_cpu();
00427         }
00428         blinktick &= ~_BV(2);
00429     }
00430 }

Here is the call graph for this function:

void savingmode_keep ( uint16_t  hhmm  ) 

00059                                     {
00060     switch (savingmode_get()) {
00061         case SAVENIGHT:
00062             if (hhmm > 0x0100 && hhmm < 0x0700) {
00063                 voltage_set(VOLTAGE_SAVE);
00064                 halfbright = 2;                     // darkest
00065             } else if (hhmm < 0x0800) {
00066                 voltage_set(VOLTAGE_SAVE);
00067                 halfbright = 1;                     // dark
00068             } else {
00069                 voltage_set(VOLTAGE_WASTE);
00070                 halfbright = 0;                     // normal
00071             }
00072             break;
00073         case SAVE:
00074             voltage_set(VOLTAGE_SAVE);
00075             halfbright = 1;
00076             break;
00077         case WASTE:
00078             voltage_set(VOLTAGE_WASTE);
00079             halfbright = 0;
00080             break;
00081     }
00082 }

Here is the call graph for this function:

uint8_t swapbits ( uint8_t  x  ) 

Rehash bits to match the schematic.

00093                             {
00094     return ((x & 1) << 3) | (x & 2) | ((x & 4) >> 2) | ((x & 8) >> 1);
00095 }

void timer0_init (  ) 

Start timer 0. Timer0 runs at 1MHz The speed is dictated by the need to keep the neon dot ionized at all times

00167                    {
00168     TIMSK |= _BV(TOIE0);    // enable Timer0 overflow interrupt
00169     TCNT0 = 256-TIMERCOUNT;
00170     TCCR0 = _BV(CS01);
00171 }


Variable Documentation

uint16_t bcq1

Values for blinking, calibrated to quarters of a second at startup.

uint16_t bcq2
uint16_t bcq3
volatile uint16_t blinkctr

blinkmode counter

volatile uint8_t blinkduty

blinkmode duty

volatile uint8_t blinktick = 0

1 when a pressed button is autorepeated

volatile uint8_t digitmux = 0

displayed digit, 0..3

volatile uint16_t digitsraw = 0

raw port values

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 halfbright

keep low duty

volatile uint16_t rawfadefrom = 0177777

digitsraw fade from

volatile uint16_t rawfadeto = 0177777

digitsraw fade to

volatile uint16_t time = 0

current display value

volatile uint16_t timef = 0

fadeto display value


Generated on Wed Jan 27 00:29:57 2010 for Patashnik by  doxygen 1.6.1