--- /dev/null
+# Hardware definitions
+PART=atmega88
+FREQ=1000000
+
+CFLAGS=-Os
+
+MLDFLAGS=$(LDFLAGS) -mmcu=$(PART)
+MCFLAGS=$(CFLAGS) -DF_CPU=$(FREQ)UL -mmcu=$(PART)
+
+default: kokare.hex # kokare.ehex
+
+program: kokare.hex
+ avrdude -q -p m88 -U flash:w:kokare.hex
+
+%.hex: %.elf
+ avr-objcopy -O ihex -R .eeprom $< $@
+
+%.ehex: %.elf
+ avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 $< $@
+
+kokare.elf: kokare.o
+ avr-gcc $< -o $@ $(MLDFLAGS)
+
+%.o: %.c
+ avr-gcc -c $(MCFLAGS) $< -o $@
+
+clean:
+ rm -f *.o *.elf *.hex *.ehex
--- /dev/null
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <inttypes.h>
+
+#define SEGA 128
+#define SEGB 64
+#define SEGC 4
+#define SEGD 16
+#define SEGE 32
+#define SEGF 2
+#define SEGG 1
+#define SEGP 8
+
+uint8_t font[16] = {
+ SEGA | SEGB | SEGC | SEGD | SEGE | SEGF,
+ SEGB | SEGC,
+ SEGA | SEGB | SEGD | SEGE | SEGG,
+ SEGA | SEGB | SEGC | SEGD | SEGG,
+ SEGB | SEGC | SEGF | SEGG,
+ SEGA | SEGC | SEGD | SEGF | SEGG,
+ SEGA | SEGC | SEGD | SEGE | SEGF | SEGG,
+ SEGA | SEGB | SEGC,
+ SEGA | SEGB | SEGC | SEGD | SEGE | SEGF | SEGG,
+ SEGA | SEGB | SEGC | SEGD | SEGF | SEGG,
+ SEGA | SEGB | SEGC | SEGE | SEGF | SEGG,
+ SEGC | SEGD | SEGE | SEGF | SEGG,
+ SEGA | SEGD | SEGE | SEGF,
+ SEGB | SEGC | SEGD | SEGE | SEGG,
+ SEGA | SEGD | SEGE | SEGF | SEGG,
+ SEGA | SEGE | SEGF | SEGG,
+};
+/* LED */
+uint8_t dsp[2] = {0, 0};
+char leda = 0;
+char ledc = 0;
+/* Timer */
+char of = 0;
+int oticks = 0;
+/* Pulse counter */
+char pstate = 0;
+char pval = 0;
+/* Switch */
+char sstate = 0;
+int stime = 0;
+/* Temp sensor */
+char tstate = 0;
+char tlock = 0;
+unsigned long tstart;
+unsigned long ttime;
+unsigned long ttimea = 10000;
+/* Zero-cross detector*/
+/* Triac */
+
+void init(void)
+{
+ /* Timer init */
+ TCCR1A = 0;
+ TCCR1B = 1;
+ TIMSK1 = 1;
+
+ /*
+ * B0..2 = Pulse sensor
+ * B3..5 = ISP
+ * B6..7 = CLK
+ */
+ DDRB = 0x00;
+ PORTB = 0x07;
+ PCMSK0 = 0x07;
+ PCICR = 0x01;
+ /*
+ * C0..5 = LEDA0..5
+ * C6 = /RESET
+ * C7 = NC
+ */
+ DDRC = 0x3f;
+ PORTC = 0x00;
+ /*
+ * D0 = Triac
+ * D1 = NTC FET
+ * D2 = ZCD (INT0)
+ * D3 = NTC Op-amp (INT1)
+ * D4..5 = LEDA6..7
+ * D6..7 = LEDC0..1
+ */
+ DDRD = 0xf3;
+ PORTD = 0x00;
+ EICRA = 0x0d;
+ EIMSK = 0x03;
+}
+
+unsigned char bindisp(unsigned char num)
+{
+ unsigned char ret;
+
+ ret = 0;
+ if(num & 1)
+ ret |= SEGA;
+ if(num & 2)
+ ret |= SEGB;
+ if(num & 4)
+ ret |= SEGC;
+ if(num & 8)
+ ret |= SEGD;
+ if(num & 16)
+ ret |= SEGE;
+ if(num & 32)
+ ret |= SEGF;
+ if(num & 64)
+ ret |= SEGG;
+ if(num & 128)
+ ret |= SEGP;
+ return(ret);
+}
+
+void display(char num)
+{
+ dsp[0] = font[(num / 10) % 10];
+ dsp[1] = font[num % 10];
+}
+
+void disphex(unsigned char num)
+{
+ dsp[0] = font[(num & 0xf0) >> 4];
+ dsp[1] = font[num & 0x0f];
+}
+
+unsigned long getticks(void)
+{
+ return(TCNT1 + (((unsigned long)oticks) << 16));
+}
+
+void ledcycle(void)
+{
+ static uint16_t last = 0;
+ uint8_t c, d, v;
+
+ if(TCNT1 - last > 500) {
+ last = TCNT1;
+ if(++leda >= 8) {
+ leda = 0;
+ if(++ledc >= 2)
+ ledc = 0;
+ }
+ if(dsp[ledc] & (1 << leda)) {
+ if(leda < 6) {
+ c = 1 << leda;
+ d = 0;
+ } else {
+ c = 0;
+ d = 0x10 << (leda - 6);
+ }
+ d |= ledc?0x40:0x80;
+ } else {
+ c = d = 0;
+ }
+ PORTC = c;
+ PORTD = (PORTD & 0x0f) | d;
+ }
+}
+
+void tempcycle(void)
+{
+ unsigned long now;
+
+ now = getticks();
+ if(tstate == 0) {
+ if((PIND & 8) && (tlock == 0)) {
+ PORTD |= 2;
+ tstart = now;
+ tstate = 1;
+ }
+ } else if(tstate == 1) {
+ if(now - tstart > 1000) {
+ PORTD &= ~2;
+ tstate = 0;
+ tstart = now;
+ }
+ }
+}
+
+void calcavg(void)
+{
+ if(tlock == 1) {
+ tlock = 2;
+ ttimea = ((ttimea * 15) + ttime) >> 4;
+ tlock = 0;
+ }
+}
+
+int main(void)
+{
+ int cur;
+
+ cur = 0;
+ init();
+ sei();
+ display(0);
+ while(1) {
+ ledcycle();
+ tempcycle();
+ calcavg();
+
+ /*
+ dsp[0] = bindisp((ttimea & 0xff00) >> 8);
+ dsp[1] = bindisp(ttimea & 0x00ff);
+ */
+ /*
+ disphex((ttimea & 0xff000) >> 12);
+ */
+ if(ttimea < 20000) {
+ display((ttimea / 100) % 100);
+ dsp[0] |= SEGP;
+ if(ttimea >= 10000)
+ dsp[1] |= SEGP;
+ } else {
+ display(ttimea / 1000);
+ }
+
+ /*
+ cur += pval;
+ pval = 0;
+ if(sstate == 2) {
+ cur = stime;
+ sstate = 0;
+ }
+ if(cur > 99)
+ cur = 99;
+ if(cur < -99)
+ cur = -99;
+ if(cur < 0) {
+ display(-cur);
+ dsp[0] |= SEGP;
+ } else {
+ display(cur);
+ }
+ */
+ }
+}
+
+ISR(SIG_INTERRUPT0)
+{
+}
+
+ISR(SIG_INTERRUPT1)
+{
+ unsigned long now;
+
+ now = getticks();
+ if(tstate == 0) {
+ tstate = 1;
+ if(tlock != 2)
+ ttime = now - tstart;
+ tstart = now;
+ PORTD |= 2;
+ tlock = 1;
+ }
+}
+
+ISR(SIG_OVERFLOW1)
+{
+ of = 1;
+ oticks++;
+}
+
+ISR(SIG_PIN_CHANGE0)
+{
+ if((sstate == 0) & ((PINB & 1) == 0)) {
+ stime = oticks;
+ sstate = 1;
+ }
+ if((sstate == 1) & ((PINB & 1) == 1)) {
+ stime = oticks - stime;
+ sstate = 2;
+ }
+ if(pstate == 0) {
+ if((PINB & 2) == 0) {
+ pstate = 1;
+ } else if((PINB & 4) == 0) {
+ pstate = 2;
+ }
+ } else if(pstate == 1) {
+ if((PINB & 4) == 0) {
+ pval++;
+ pstate = 3;
+ } else {
+ pstate = 0;
+ }
+ } else if(pstate == 2) {
+ if((PINB & 2) == 0) {
+ pval--;
+ pstate = 3;
+ } else {
+ pstate = 0;
+ }
+ } else {
+ if((PINB & 2) && (PINB & 4))
+ pstate = 0;
+ }
+}