diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..2dc174a --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,2 @@ +logtable.c +exptable.c diff --git a/src/Makefile b/src/Makefile index ac5ab0c..50ef56e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,5 @@ -PROJ=blink +PROJ=ntc default: all all: $(PROJ).hex @@ -7,6 +7,13 @@ all: $(PROJ).hex SN_blink = 1 MCU_blink = attiny13a +SN_ntc = 1 +MCU_ntc = attiny13a +logtable.c: ./logtable.py +exptable.c: ./exptable.py + ./$< >$@ +C_FILES_ntc = exptable.c + SN_kennung = 1 MCU_kennung = attiny13a @@ -27,8 +34,7 @@ CC=avr-gcc -Wall -Wno-parentheses -MMD -std=c99 -O3 \ -fpack-struct \ -fshort-enums \ -mtiny-stack \ - -mint8 \ - -fverbose-asm + -mint8 SN = $(SN_$(PROJ)) CFLAGS = $($*_CFLAGS) $(DEBUG) -I. -DSN="$(SN)" @@ -70,6 +76,7 @@ OBJCOPY = avr-objcopy # [1:0] CKSEL = 10 (9.6MHz internal oscillator) lfuse_blink = 0x7a +lfuse_ntc = 0x7a # [6]: EESAVE = 0 ! (EEPROM not preserved @ chip erase) # [5]: WDTON = 0 ! (watchdog disabled) diff --git a/src/blink.c b/src/blink.c index 4e25198..5970d8c 100644 --- a/src/blink.c +++ b/src/blink.c @@ -9,126 +9,77 @@ #include #include -#define Bit(x) (1<<(x)) -#define SetPORT(x) PORTB |= Bit(x) -#define ClrPORT(x) PORTB &=~ Bit(x) -#define GetPORT(x) (PINB & Bit(x)) - #define RES_PORT 0 #define TRIG_PORT 1 #define OUT_PORT 2 #define LED2_PORT 3 #define LED1_PORT 4 -#define START_PORT OUT_PORT - -// 9.6MHz/8/240 = 5kHz -#define MAX_DC 240 -#define DC_EXP 12 - -static uint32_t led1_dc; - -static inline -uint8_t get_dc(uint32_t dc) { - return dc >> 24; -} -static inline -uint32_t set_dc(uint8_t dc) { - return ((uint32_t)dc << 24) - 1; -} -static inline -uint32_t fade(uint32_t dc) -{ - uint32_t diff = dc >> (8*((DC_EXP+4)>>3)); - if (DC_EXP & 4) - diff <<= 8 - (DC_EXP&7); - else - diff >>= DC_EXP & 3; - return dc - diff; -} +uint8_t tick; ISR(TIM0_COMPB_vect) { - SetPORT(LED1_PORT); + PORTB |= 1 << LED2_PORT; } ISR(TIM0_COMPA_vect) { - TIFR0 = Bit(OCF0B); - ClrPORT(LED1_PORT); - OCR0B = MAX_DC + 1 - (uint8_t)(led1_dc >> 24); + PORTB &=~ (1 << LED2_PORT); + TIFR0 = (1<>= 1; - } sei(); sleep_mode(); - led1_dc = fade(led1_dc); + + if (PINB & (1 << TRIG_PORT)) + PORTB &=~ (1 << LED1_PORT); + else + PORTB |= (1 << LED1_PORT); + + uint8_t dc = get_dc(); + + if (dc == 0 && !(PINB & (1 << OUT_PORT))) + set_dc(255); + + if (tick) { + tick = 0; + n = n - 1; + if (n == 0) { + n = nticks; + if (dc) + set_dc(dc-1); + } + } + } } diff --git a/src/exptable.py b/src/exptable.py new file mode 100755 index 0000000..e65b97e --- /dev/null +++ b/src/exptable.py @@ -0,0 +1,14 @@ +#! /usr/bin/python3 + +print(""" +/* generated by exptable.py */ +#include +const uint8_t exp_table[] __attribute__((section(".text"))) = { +""") + +for a in range(256): + aa = 2 ** ((a+36) / (256+35) * 8) + dc = int(aa)-1 + print(f" {dc}, // {a=} {aa=:.1f} {dc=}") + +print("};") diff --git a/src/logtable.py b/src/logtable.py new file mode 100755 index 0000000..64b8228 --- /dev/null +++ b/src/logtable.py @@ -0,0 +1,17 @@ +#! /usr/bin/python3 + +from math import log + +print(""" +/* generated by logtable.py */ +#include +const uint8_t log_table[] = { +""") + +for a in range(32): + log2 = log(a+1)/log(2) + dc = int(255/5 * log2) + print(f" {dc}, // {a+1=} {log2=:.3f} {dc=}") + + +print("};") diff --git a/src/ntc.c b/src/ntc.c new file mode 100644 index 0000000..95d0ad6 --- /dev/null +++ b/src/ntc.c @@ -0,0 +1,132 @@ +// +// blink.c +// + +// !!! int = int8_t + +#include +#include +#include +#include + +/* y = exp(x) = exp_table[x] + * exp_table[] is stored in flash (section .text) + * To read from flash we need the opcode LPM "Load Program Memory" + * exp8() is a C wrapper for that asm opcode. + * + * avr-gcc copies .rodata to RAM, to allow direct variable access. + * ATtiny13a has only 64 Bytes of RAM. A table of size 256 Bytes + * needs to go into flash. + * + * The linker script may provide for a data section in flash, but here + * we just drop the table into the .text section. + */ + +extern const uint8_t exp_table[256] __attribute__((section(".text"))); + +static inline +uint8_t exp8(uint8_t x) +{ + uint8_t r; + __asm__(" lpm %[R], Z" + : [R] "=d" (r) + : [Z] "z" (exp_table+x) + ); + return r; +} + +#define RES_PORT 0 +#define TRIG_PORT 1 +#define OUT_PORT 2 +#define LED2_PORT 3 +#define LED1_PORT 4 + +#define NTC_PORT LED2_PORT +#define NTC_ADC 3 + +static inline +void init_adc() +{ + ADMUX = 0x23; + DIDR0 |= 1 << NTC_PORT; + // ADCSRB = 0x00; + ADCSRA = 0xff; +} + +uint16_t ntc; + +uint16_t t_min = 0x8618; + +void set_dc(uint8_t dc); + +ISR(ADC_vect) +{ + uint16_t a = ADCL; + a |= (uint16_t)ADCH << 8; +#if 0 + ntc = ((uint32_t)ntc * 255 + a) / 256; +#else + uint32_t a1 = (uint32_t)ntc << 8; + a1 -= ntc; + a1 += a; + ntc = a1 >> 8; +#endif + uint16_t dc; + if (t_min < ntc) + dc = 0; + else { + dc = (t_min - ntc) >> 6; + if (dc > 0xff) + dc = 0xff; + else + dc = exp8(dc); + } + set_dc(dc); + ADCSRA = 0xff; +} + +uint8_t tick; + +ISR(TIM0_COMPB_vect) +{ + PORTB |= 1 << LED1_PORT; +} + +ISR(TIM0_COMPA_vect) +{ + PORTB &=~ (1 << LED1_PORT); + TIFR0 = (1<