Added ZVD and Triac control.
[kokare.git] / kokare.c
1 #include <avr/io.h>
2 #include <avr/interrupt.h>
3 #include <inttypes.h>
4
5 #define SEGA 128
6 #define SEGB 64
7 #define SEGC 4
8 #define SEGD 16
9 #define SEGE 32
10 #define SEGF 2
11 #define SEGG 1
12 #define SEGP 8
13
14 uint8_t font[16] = {
15     SEGA | SEGB | SEGC | SEGD | SEGE | SEGF,
16     SEGB | SEGC,
17     SEGA | SEGB | SEGD | SEGE | SEGG,
18     SEGA | SEGB | SEGC | SEGD | SEGG,
19     SEGB | SEGC | SEGF | SEGG,
20     SEGA | SEGC | SEGD | SEGF | SEGG,
21     SEGA | SEGC | SEGD | SEGE | SEGF | SEGG,
22     SEGA | SEGB | SEGC,
23     SEGA | SEGB | SEGC | SEGD | SEGE | SEGF | SEGG,
24     SEGA | SEGB | SEGC | SEGD | SEGF | SEGG,
25     SEGA | SEGB | SEGC | SEGE | SEGF | SEGG,
26     SEGC | SEGD | SEGE | SEGF | SEGG,
27     SEGA | SEGD | SEGE | SEGF,
28     SEGB | SEGC | SEGD | SEGE | SEGG,
29     SEGA | SEGD | SEGE | SEGF | SEGG,
30     SEGA | SEGE | SEGF | SEGG,
31 };
32 /* LED */
33 uint8_t dsp[2] = {0, 0};
34 char leda = 0;
35 char ledc = 0;
36 /* Timer */
37 char of = 0;
38 int oticks = 0;
39 unsigned long mnow;
40 /* Pulse counter */
41 char pstate = 0;
42 char pval = 0;
43 /* Switch */
44 char sstate = 0;
45 int stime = 0;
46 /* Temp sensor */
47 char tstate = 0;
48 char tlock = 0;
49 unsigned long tstart;
50 unsigned long ttime;
51 unsigned long ttimea = 10000;
52 /* Zero-cross detector*/
53 char zok = 0;
54 unsigned long ztime;
55 /* Triac */
56 char trstate = 0;
57 char tron = 0;
58 unsigned short trdelay = 0;
59
60 void init(void)
61 {
62     /* Timer init */
63     TCCR1A = 0;
64     TCCR1B = 1;
65     TIMSK1 = 1;
66     
67     /*
68      * B0..2 = Pulse sensor
69      * B3..5 = ISP
70      * B6..7 = CLK
71      */
72     DDRB = 0x30;
73     PORTB = 0x07;
74     PCMSK0 = 0x07;
75     PCICR = 0x01;
76     /*
77      * C0..5 = LEDA0..5
78      * C6 = /RESET
79      * C7 = NC
80      */
81     DDRC = 0x3f;
82     PORTC = 0x00;
83     /*
84      * D0 = Triac
85      * D1 = NTC FET
86      * D2 = ZCD (INT0)
87      * D3 = NTC Op-amp (INT1)
88      * D4..5 = LEDA6..7
89      * D6..7 = LEDC0..1
90      */
91     DDRD = 0xf3;
92     PORTD = 0x00;
93     EICRA = 0x0d;
94     EIMSK = 0x03;
95 }
96
97 unsigned char bindisp(unsigned char num)
98 {
99     unsigned char ret;
100     
101     ret = 0;
102     if(num & 1)
103         ret |= SEGA;
104     if(num & 2)
105         ret |= SEGB;
106     if(num & 4)
107         ret |= SEGC;
108     if(num & 8)
109         ret |= SEGD;
110     if(num & 16)
111         ret |= SEGE;
112     if(num & 32)
113         ret |= SEGF;
114     if(num & 64)
115         ret |= SEGG;
116     if(num & 128)
117         ret |= SEGP;
118     return(ret);
119 }
120
121 void display(char num)
122 {
123     dsp[0] = font[(num / 10) % 10];
124     dsp[1] = font[num % 10];
125 }
126
127 void disphex(unsigned char num)
128 {
129     dsp[0] = font[(num & 0xf0) >> 4];
130     dsp[1] = font[num & 0x0f];
131 }
132
133 unsigned long getticks(void)
134 {
135     return(TCNT1 + (((unsigned long)oticks) << 16));
136 }
137
138 void ledcycle(void)
139 {
140     static uint16_t last = 0;
141     uint8_t c, d, v;
142     
143     if(TCNT1 - last > 500) {
144         last = TCNT1;
145         if(++leda >= 8) {
146             leda = 0;
147             if(++ledc >= 2)
148                 ledc = 0;
149         }
150         if(dsp[ledc] & (1 << leda)) {
151             if(leda < 6) {
152                 c = 1 << leda;
153                 d = 0;
154             } else {
155                 c = 0;
156                 d = 0x10 << (leda - 6);
157             }
158             d |= ledc?0x40:0x80;
159         } else {
160             c = d = 0;
161         }
162         PORTC = c;
163         PORTD = (PORTD & 0x0f) | d;
164     }
165 }
166
167 void tempcycle(void)
168 {
169     if(tstate == 0) {
170         if((PIND & 8) && (tlock == 0)) {
171             PORTD |= 2;
172             tstart = mnow;
173             tstate = 1;
174         }
175     } else if(tstate == 1) {
176         if(mnow - tstart > 1000) {
177             PORTD &= ~2;
178             tstate = 0;
179             tstart = mnow;
180         }
181     }
182 }
183
184 void calcavg(void)
185 {
186     if(tlock == 1) {
187         tlock = 2;
188         ttimea = ((ttimea * 15) + ttime) >> 4;
189         tlock = 0;
190     }
191 }
192
193 void triaccycle(void)
194 {
195     if(trstate == 0) {
196         if(tron && zok && (mnow > ztime + trdelay)) {
197             PORTD |= 1;
198             zok = 0;
199             trstate = 1;
200         }
201     } else if(trstate == 1) {
202         PORTD &= ~1;
203         trstate = 0;
204     }
205 }
206
207 int main(void)
208 {
209     int cur;
210     
211     cur = 0;
212     init();
213     sei();
214     display(0);
215
216     tron = 1;
217     trdelay = 5000;
218
219     while(1) {
220         mnow = getticks();
221         ledcycle();
222         tempcycle();
223         calcavg();
224         triaccycle();
225
226         /*
227           dsp[0] = bindisp((ttimea & 0xff00) >> 8);
228           dsp[1] = bindisp(ttimea & 0x00ff);
229         */
230         /*
231           disphex((ttimea & 0xff000) >> 12);
232         */
233 #if 1
234         /*
235           Temp display
236         */
237         if(ttimea < 20000) {
238             display((ttimea / 100) % 100);
239             dsp[0] |= SEGP;
240             if(ttimea >= 10000)
241                 dsp[1] |= SEGP;
242         } else {
243             display(ttimea / 1000);
244         }
245 #endif
246 #if 0
247         /*
248           Pulse counter display
249         */
250         cur += pval;
251         pval = 0;
252         if(sstate == 2) {
253             cur = stime;
254             sstate = 0;
255         }
256         if(cur > 99)
257             cur = 99;
258         if(cur < -99)
259             cur = -99;
260         if(cur < 0) {
261             display(-cur);
262             dsp[0] |= SEGP;
263         } else {
264             display(cur);
265         }
266 #endif
267     }
268 }
269
270 ISR(SIG_INTERRUPT0)
271 {
272     ztime = getticks();
273     zok = 1;
274 }
275
276 ISR(SIG_INTERRUPT1)
277 {
278     unsigned long now;
279     
280     now = getticks();
281     if(tstate == 0) {
282         tstate = 1;
283         if(tlock != 2)
284             ttime = now - tstart;
285         tstart = now;
286         PORTD |= 2;
287         tlock = 1;
288     }
289 }
290
291 ISR(SIG_OVERFLOW1)
292 {
293     of = 1;
294     oticks++;
295 }
296
297 ISR(SIG_PIN_CHANGE0)
298 {
299     if((sstate == 0) & ((PINB & 1) == 0)) {
300         stime = oticks;
301         sstate = 1;
302     }
303     if((sstate == 1) & ((PINB & 1) == 1)) {
304         stime = oticks - stime;
305         sstate = 2;
306     }
307     if(pstate == 0) {
308         if((PINB & 2) == 0) {
309             pstate = 1;
310         } else if((PINB & 4) == 0) {
311             pstate = 2;
312         }
313     } else if(pstate == 1) {
314         if((PINB & 4) == 0) {
315             pval++;
316             pstate = 3;
317         } else {
318             pstate = 0;
319         }
320     } else if(pstate == 2) {
321         if((PINB & 2) == 0) {
322             pval--;
323             pstate = 3;
324         } else {
325             pstate = 0;
326         }
327     } else {
328         if((PINB & 2) && (PINB & 4))
329             pstate = 0;
330     }
331 }