mirror of
https://codeberg.org/SiB64/blinkenlights.git
synced 2026-06-28 16:19:49 +02:00
Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ce09f610ce | ||
|
|
0299fd4cc9 | ||
|
|
33c646b677 | ||
|
|
1465947402 | ||
|
|
c4e5eb8186 |
6 changed files with 213 additions and 90 deletions
2
src/.gitignore
vendored
Normal file
2
src/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
logtable.c
|
||||||
|
exptable.c
|
||||||
13
src/Makefile
13
src/Makefile
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
PROJ=blink
|
PROJ=ntc
|
||||||
|
|
||||||
default: all
|
default: all
|
||||||
all: $(PROJ).hex
|
all: $(PROJ).hex
|
||||||
|
|
@ -7,6 +7,13 @@ all: $(PROJ).hex
|
||||||
SN_blink = 1
|
SN_blink = 1
|
||||||
MCU_blink = attiny13a
|
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
|
SN_kennung = 1
|
||||||
MCU_kennung = attiny13a
|
MCU_kennung = attiny13a
|
||||||
|
|
||||||
|
|
@ -27,8 +34,7 @@ CC=avr-gcc -Wall -Wno-parentheses -MMD -std=c99 -O3 \
|
||||||
-fpack-struct \
|
-fpack-struct \
|
||||||
-fshort-enums \
|
-fshort-enums \
|
||||||
-mtiny-stack \
|
-mtiny-stack \
|
||||||
-mint8 \
|
-mint8
|
||||||
-fverbose-asm
|
|
||||||
|
|
||||||
SN = $(SN_$(PROJ))
|
SN = $(SN_$(PROJ))
|
||||||
CFLAGS = $($*_CFLAGS) $(DEBUG) -I. -DSN="$(SN)"
|
CFLAGS = $($*_CFLAGS) $(DEBUG) -I. -DSN="$(SN)"
|
||||||
|
|
@ -70,6 +76,7 @@ OBJCOPY = avr-objcopy
|
||||||
# [1:0] CKSEL = 10 (9.6MHz internal oscillator)
|
# [1:0] CKSEL = 10 (9.6MHz internal oscillator)
|
||||||
|
|
||||||
lfuse_blink = 0x7a
|
lfuse_blink = 0x7a
|
||||||
|
lfuse_ntc = 0x7a
|
||||||
|
|
||||||
# [6]: EESAVE = 0 ! (EEPROM not preserved @ chip erase)
|
# [6]: EESAVE = 0 ! (EEPROM not preserved @ chip erase)
|
||||||
# [5]: WDTON = 0 ! (watchdog disabled)
|
# [5]: WDTON = 0 ! (watchdog disabled)
|
||||||
|
|
|
||||||
127
src/blink.c
127
src/blink.c
|
|
@ -9,126 +9,77 @@
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include <avr/sleep.h>
|
#include <avr/sleep.h>
|
||||||
|
|
||||||
#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 RES_PORT 0
|
||||||
#define TRIG_PORT 1
|
#define TRIG_PORT 1
|
||||||
#define OUT_PORT 2
|
#define OUT_PORT 2
|
||||||
#define LED2_PORT 3
|
#define LED2_PORT 3
|
||||||
#define LED1_PORT 4
|
#define LED1_PORT 4
|
||||||
|
|
||||||
#define START_PORT OUT_PORT
|
uint8_t tick;
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ISR(TIM0_COMPB_vect)
|
ISR(TIM0_COMPB_vect)
|
||||||
{
|
{
|
||||||
SetPORT(LED1_PORT);
|
PORTB |= 1 << LED2_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISR(TIM0_COMPA_vect)
|
ISR(TIM0_COMPA_vect)
|
||||||
{
|
{
|
||||||
TIFR0 = Bit(OCF0B);
|
PORTB &=~ (1 << LED2_PORT);
|
||||||
ClrPORT(LED1_PORT);
|
TIFR0 = (1<<OCF0B);
|
||||||
OCR0B = MAX_DC + 1 - (uint8_t)(led1_dc >> 24);
|
tick = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
void set_dc(uint8_t dc)
|
||||||
void pulse_led1(uint8_t dc)
|
|
||||||
{
|
{
|
||||||
led1_dc = set_dc(dc);
|
OCR0B = 255 - dc;
|
||||||
OCR0B = MAX_DC + 1 - dc;
|
}
|
||||||
|
|
||||||
|
uint8_t get_dc()
|
||||||
|
{
|
||||||
|
return 255 - OCR0B;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void init_timer()
|
void init_timer()
|
||||||
{
|
{
|
||||||
DDRB = Bit(LED1_PORT) | Bit(LED2_PORT);
|
DDRB = (1<<LED1_PORT) | (1<<LED2_PORT);
|
||||||
ClrPORT(LED1_PORT);
|
|
||||||
TCCR0A = 0x02; // CTC TOP=OCRA TOV=MAX
|
TCCR0A = 0x02; // CTC TOP=OCRA TOV=MAX
|
||||||
TCCR0B = 0x02; // clk_IO/8
|
TCCR0B = 0x02; // clk_IO/8
|
||||||
OCR0A = MAX_DC;
|
OCR0A = 254;
|
||||||
OCR0B = 255; // off
|
set_dc(10);
|
||||||
TIMSK0 = Bit(OCIE0A) | Bit(OCIE0B);
|
TIMSK0 = (1<<OCIE0A) | (1<<OCIE0B);
|
||||||
}
|
}
|
||||||
|
|
||||||
ISR(PCINT0_vect)
|
static const uint8_t nticks = 50;
|
||||||
{
|
|
||||||
SetPORT(LED2_PORT);
|
|
||||||
if (!GetPORT(START_PORT))
|
|
||||||
pulse_led1(MAX_DC);
|
|
||||||
ClrPORT(LED2_PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline
|
|
||||||
void init_trig()
|
|
||||||
{
|
|
||||||
PCMSK = Bit(START_PORT);
|
|
||||||
GIMSK = Bit(PCIE);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void init_wdt(uint8_t wdt_period)
|
|
||||||
{
|
|
||||||
#ifdef WDT_TRIGGERED
|
|
||||||
uint8_t cr = Bit(WDE) | (wdt_period&7) << WDP0 | (wdt_period&8) << (WDP3-3);
|
|
||||||
__asm__("STS %[CSR], %[CE]" "\n\t"
|
|
||||||
"STS %[CSR], %[WE]" "\n"
|
|
||||||
::[CSR] "n" (&WDTCR),
|
|
||||||
[CE] "r" ((Bit(WDCE) | Bit(WDE))),
|
|
||||||
[WE] "r" (cr)
|
|
||||||
);
|
|
||||||
#endif // WDT_TRIGGERED
|
|
||||||
}
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
init_timer();
|
init_timer();
|
||||||
init_trig();
|
|
||||||
pulse_led1(MAX_DC);
|
|
||||||
init_wdt(7);
|
|
||||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||||
uint16_t debug = 0;
|
uint8_t n = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
if (!debug) {
|
|
||||||
// debug = 0xff00L | OCR0B;
|
|
||||||
ClrPORT(LED2_PORT);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (debug&1)
|
|
||||||
SetPORT(LED2_PORT);
|
|
||||||
else
|
|
||||||
ClrPORT(LED2_PORT);
|
|
||||||
debug >>= 1;
|
|
||||||
}
|
|
||||||
sei();
|
sei();
|
||||||
sleep_mode();
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
14
src/exptable.py
Executable file
14
src/exptable.py
Executable file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
print("""
|
||||||
|
/* generated by exptable.py */
|
||||||
|
#include <stdint.h>
|
||||||
|
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("};")
|
||||||
17
src/logtable.py
Executable file
17
src/logtable.py
Executable file
|
|
@ -0,0 +1,17 @@
|
||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
from math import log
|
||||||
|
|
||||||
|
print("""
|
||||||
|
/* generated by logtable.py */
|
||||||
|
#include <stdint.h>
|
||||||
|
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("};")
|
||||||
132
src/ntc.c
Normal file
132
src/ntc.c
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
//
|
||||||
|
// blink.c
|
||||||
|
//
|
||||||
|
|
||||||
|
// !!! int = int8_t
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/sleep.h>
|
||||||
|
|
||||||
|
/* 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<<OCF0B);
|
||||||
|
tick = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_dc(uint8_t dc)
|
||||||
|
{
|
||||||
|
OCR0B = 255 - dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t get_dc()
|
||||||
|
{
|
||||||
|
return 255 - OCR0B;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
void init_timer()
|
||||||
|
{
|
||||||
|
DDRB = 1<<LED1_PORT;
|
||||||
|
TCCR0A = 0x02; // CTC TOP=OCRA TOV=MAX
|
||||||
|
TCCR0B = 0x02; // clk_IO/8
|
||||||
|
OCR0A = 254;
|
||||||
|
set_dc(10);
|
||||||
|
TIMSK0 = (1<<OCIE0A) | (1<<OCIE0B);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
init_timer();
|
||||||
|
init_adc();
|
||||||
|
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||||
|
while (1) {
|
||||||
|
sei();
|
||||||
|
sleep_mode();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue