Compare commits

...

8 commits

Author SHA1 Message Date
Stephan I. Böttcher
e62e03f550 print E adc_conf on boot 2024-04-10 18:20:41 +02:00
Stephan I. Böttcher
59fe3a7949 greeting improvement 2024-04-10 18:15:24 +02:00
Stephan I. Böttcher
a341b2c454 baye.config: add BC_SPI 2024-04-10 18:13:57 +02:00
Stephan I. Böttcher
affd866a7c spi: replace bit banging with SPI0 2024-04-10 18:10:57 +02:00
Stephan I. Böttcher
2287dbc7b9 calib: fix turbo test case[0] 2024-04-10 18:09:09 +02:00
Stephan I. Böttcher
9af59b100f bate: use 16-bit frames 2024-04-10 01:24:24 +02:00
Stephan I. Böttcher
423016de10 bate_wait: sleep() waiting for pin interrupt 2024-04-09 23:55:10 +02:00
Stephan I. Böttcher
fc180c1881 uart: pin sense bothedges 2024-04-09 23:50:43 +02:00
8 changed files with 234 additions and 102 deletions

View file

@ -8,7 +8,7 @@ all: $(PROJ).hex
SN_bate = 1
MCU_bate = attiny424
C_FILES_bate = uart.c rtc.c calib.c mul.c adc.c
C_FILES_bate = uart.c rtc.c calib.c mul.c adc.c spi.c
BATE_PERIOD=76
bate_CFLAGS = -DPERIOD=$(BATE_PERIOD)
@ -133,10 +133,13 @@ BC_PIT = 0xff
BC_BAUD = 0 0
BC_TEST = 0
BC_PERIOD= 9
BC_SPI = 0xff
BATE_CONFIG = $(BC_MAGIC) $(BC_VERS) $(BC_CLK) \
$(BC_PWR) $(BC_SEND) $(BC_TRIG) \
$(BC_MCLK) $(BC_MDEL) $(BC_PIT) $(BC_BAUD) $(BC_TEST) $(BC_PERIOD)
$(BC_MCLK) $(BC_MDEL) $(BC_PIT) $(BC_BAUD) \
$(BC_TEST) $(BC_PERIOD) $(BC_SPI)
bate.config:
$(AD) -U userrow:v:"$(BATE_CONFIG)":m \
|| $(AD) -U userrow:w:"$(BATE_CONFIG)":m

View file

@ -17,6 +17,7 @@
#include "calib.h"
#include "mul.h"
#include "adc.h"
#include "spi.h"
#define Bit(x) (1<<(x))
@ -100,21 +101,18 @@ void init_mclk(uint8_t p)
MCLK.CTRLB = TCA_SINGLE_CMP0EN_bm | TCA_SINGLE_WGMODE_FRQ_gc;
BATE_PORT.DIR |= Bit(DIN_PORT);
BATE_PORT.DIR |= Bit(SCK_PORT);
PORTA.PIN2CTRL = PORT_PULLUPEN_bm;
}
static inline
void mclk(uint8_t on)
ISR(PORTA_PORT_vect, ISR_NAKED)
{
if (on)
MCLK.CTRLA |= TCA_SINGLE_ENABLE_bm;
else
MCLK.CTRLA &=~ TCA_SINGLE_ENABLE_bm;
}
static inline
uint8_t mclk_status()
{
return MCLK.CTRLA & TCA_SINGLE_ENABLE_bm;
__asm__ ("push r24" "\n\t"
"lds r24,%[stat]" "\n\t"
"sts %[stat], r24" "\n\t"
"pop r24" "\n\t"
"reti" "\n"
: : [stat] "n" (&VPORTA.INTFLAGS)
);
}
volatile uint8_t tick;
@ -132,9 +130,45 @@ ISR(TCA0_CMP0_vect, ISR_NAKED)
);
}
__attribute__ ((noinline, noclone))
static
void bate_wait()
{
uint16_t timeout = 3277; // 50ms
tick = 0;
while (BATE_PORT.IN & Bit(DOUT_PORT)) {
PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc;
sleep_cpu();
if (tick) {
tick = 0;
if (!--timeout) {
DEBUG_COUNTER(bate_timeout);
break;
}
}
}
PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_INTDISABLE_gc;
}
static inline
void mclk(uint8_t on)
{
if (on)
MCLK.CTRLA |= TCA_SINGLE_ENABLE_bm;
else
MCLK.CTRLA &=~ TCA_SINGLE_ENABLE_bm;
}
static inline
uint8_t mclk_status()
{
return MCLK.CTRLA & TCA_SINGLE_ENABLE_bm;
}
union bate bate;
struct pressure pressure;
#ifdef BIT_BANG_BATE
// Spec:
// _____ _____ _____
@ -224,8 +258,6 @@ uint8_t bate_bit(uint8_t r, uint8_t c, uint8_t ii)
return r;
}
__attribute__ ((noinline, noclone))
static
uint16_t bate_frame(uint16_t d, uint8_t n)
@ -263,101 +295,67 @@ uint16_t bate_frame(uint16_t d, uint8_t n)
return (uint16_t)r1<<8 | r0;
}
__attribute__ ((noinline, noclone))
static
void bate_wait()
{
uint16_t timeout = 3277; // 50ms
sei();
while (BATE_PORT.IN & Bit(DOUT_PORT)) {
if (tick) {
tick = 0;
if (!timeout)
break;
timeout--;
}
}
cli();
}
static inline
void read_bate()
{
cli();
bate.H1 = 0x0001;
bate_frame(0xaaaa, 16);
bate_frame(0, 5);
bate_frame(0x3aa0, 14);
bate_frame(0, 8);
bate_frame(0x3aa0, 16);
bate.W1 = bate_frame(0, 16);
bate_frame(0x3ac0, 14);
bate_frame(0x3ac0, 16);
bate.W2 = bate_frame(0, 16);
bate_frame(0x3b20, 14);
bate_frame(0x3b20, 16);
bate.W3 = bate_frame(0, 16);
bate_frame(0x3b40, 14);
bate_frame(0x3b40, 16);
bate.W4 = bate_frame(0, 16);
bate_frame(0x0f40, 12);
bate.H1 = 0x0002;
bate_frame(0x0f40, 16);
sei();
bate_wait();
cli();
bate_frame(0,1);
bate.D1 = bate_frame(0, 16);
bate_frame(0x0f20, 12);
bate.H1 = 0x0003;
bate_frame(0x0f20, 16);
sei();
bate_wait();
cli();
bate_frame(0,1);
bate.D2 = bate_frame(0, 16);
bate.H1 = 0xba7e;
bate.H2 += 1;
sei();
}
#else // !BIT_BANG_BATE
static inline
void read_bate()
{
init_spi(config.spi_div);
spi_frame(0b0000000010101010);
spi_frame(0b1010101000000000);
spi_frame(0b0001110101010000);
bate.W1 = spi_frame(0);
spi_frame(0b0001110101100000);
bate.W2 = spi_frame(0);
spi_frame(0b0001110110010000);
bate.W3 = spi_frame(0);
spi_frame(0b0001110110100000);
bate.W4 = spi_frame(0);
spi_frame(0b0000111101000000);
bate_wait();
bate.D1 = spi_frame(0);
spi_frame(0b0000111100100000);
bate_wait();
bate.D2 = spi_frame(0);
spi_off();
}
#endif // !BIT_BANG_BATE
////////////////////////////////////////////////////////////////////////////////
//
// Configuration in USERROW
struct config {
uint8_t magic;
uint8_t version;
uint8_t cpu_clk;
uint8_t power;
uint8_t send;
uint8_t triggers;
uint8_t mclk_period;
uint8_t mclk_delay;
uint8_t pit_period;
uint16_t baud_div;
uint8_t calib_test;
uint8_t period;
};
enum magic_flags {
USE_USERROW = 0xBA,
USE_VERSION = 0x03,
};
enum power_flags {
POWER_DOWN = 0x01,
POWER_DOWN_CLI = 0x02,
STOP_MCLK = 0x04,
};
enum send_flags {
SEND_BOOT_MESSAGE = 0x01,
SEND_CLOCK = 0x02,
SEND_HEX = 0x04,
SEND_CALIB = 0x08,
SEND_ADC = 0x10,
SEND_DEBUG = 0x80,
};
enum trigger_flags {
TRIGGER_ONCE = 0x01,
TRIGGER_CONT = 0x02,
TRIGGER_UART = 0x04,
TRIGGER_CLOCK = 0x08,
TRIGGER_BREAK = 0x10,
};
static struct config config = {
struct config config = {
.power = STOP_MCLK,
.send = SEND_BOOT_MESSAGE | SEND_CLOCK | SEND_HEX | SEND_ADC,
.cpu_clk = CLKCTRL_PDIV_2X_gc | 1,
@ -365,7 +363,9 @@ static struct config config = {
.mclk_delay = 2,
.pit_period = RTC_CLKSEL_INT1K_gc,
.period = 9,
.spi_div = SPI_PRESC_DIV64_gc,
};
static const struct config *userrow = (struct config *) & USERROW;
#ifdef DEBUG
@ -409,14 +409,13 @@ int main()
sleep_enable();
sei();
send_str("Hallo\n");
send_str("\nV Turbo Weather V0.03\n");
if (config.send & SEND_BOOT_MESSAGE) {
send_str("V Turbo Weather V0.01\n");
send_hex('S', (uint8_t *)&SIGROW, sizeof(SIGROW_t), 0);
send_hex('F', (uint8_t *)&FUSE, sizeof(FUSE_t), 1);
send_hex('U', (uint8_t *)&USERROW, sizeof(USERROW_t), 1);
send_hex('C', (uint8_t *)&config, sizeof(struct config), 1);
send_hex('E', (uint8_t *)adc_conf, sizeof(adc_conf), 1);
}
uint8_t test_calib = config.calib_test;

View file

@ -4,6 +4,55 @@
#include "uart.h"
////////////////////////////////////////////////////////////////////////////////
//
// Configuration
struct config {
uint8_t magic;
uint8_t version;
uint8_t cpu_clk;
uint8_t power;
uint8_t send;
uint8_t triggers;
uint8_t mclk_period;
uint8_t mclk_delay;
uint8_t pit_period;
uint16_t baud_div;
uint8_t calib_test;
uint8_t period;
uint8_t spi_div;
};
enum magic_flags {
USE_USERROW = 0xBA,
USE_VERSION = 0x03,
};
enum power_flags {
POWER_DOWN = 0x01,
POWER_DOWN_CLI = 0x02,
STOP_MCLK = 0x04,
};
enum send_flags {
SEND_BOOT_MESSAGE = 0x01,
SEND_CLOCK = 0x02,
SEND_HEX = 0x04,
SEND_CALIB = 0x08,
SEND_ADC = 0x10,
SEND_DEBUG = 0x80,
};
enum trigger_flags {
TRIGGER_ONCE = 0x01,
TRIGGER_CONT = 0x02,
TRIGGER_UART = 0x04,
TRIGGER_CLOCK = 0x08,
TRIGGER_BREAK = 0x10,
};
extern struct config config;
#ifndef NODEBUG
# define DEBUG
#endif
@ -15,10 +64,12 @@
struct debug {
uint8_t value;
uint8_t magic;
uint16_t adc_irqs;
uint16_t tx_irqs;
uint16_t rx_irqs;
uint16_t tx_sleep;
uint8_t tx_sleep;
uint8_t tx_irqs;
uint8_t rx_irqs;
uint8_t adc_irqs;
uint8_t bate_timeout;
uint8_t spi_timeout;
uint16_t mainloops;
};

View file

@ -75,7 +75,7 @@ void bate_calib(const union bate *bate, struct pressure *pt)
}
static const union bate testdata[] = {
{ .w = { 0x7EBA, 0xA41A, 0xA691, 0x0A93, 0x989F, 0x28AF, 0x4896, 0x71F4 }, },
{ .w = { 0xA691, 0x0A97, 0x989F, 0xAF28, 0x4896, 0x71F4 }, },
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x470c, 0x773f }, }, // 21.2 °C, 1021.7 mbar
{ .W = { 0xabaf, 0x3c99, 0xa31a, 0xb589}, .D = { 0x1a51, 0x6fed }, }, // 7.5 °C, 5.4 mbar
{ .W = { 0xaa3d, 0x35d9, 0xcbe5, 0xb736}, .D = { 0x4bb7, 0x7487 }, }, // 17.7 °C, 1023.0 mbar

View file

@ -3,16 +3,13 @@
// !!! int = int8_t
union bate {
uint8_t b[16];
uint16_t w[8];
uint8_t b[12];
uint16_t w[6];
struct {
uint16_t H[2];
uint16_t W[4];
uint16_t D[2];
};
struct {
uint16_t H1;
uint16_t H2;
uint16_t W1;
uint16_t W2;
uint16_t W3;

68
src/spi.c Normal file
View file

@ -0,0 +1,68 @@
//
// spi.c
//
// !!! int = int8_t
#include "spi.h"
#include "bate.h"
#include <avr/interrupt.h>
#include <avr/sleep.h>
volatile uint8_t spi_tick;
// The Pressure sensor samples on the rising edge, MODE = 0
static const uint8_t SPI_Mode_Write = SPI_SSD_bm | SPI_BUFEN_bm;
// The Pressure sensor delivers on the rising edge, MODE = 1
static const uint8_t SPI_Mode_Read = SPI_SSD_bm | SPI_BUFEN_bm | SPI_MODE_0_bm;
void init_spi(uint8_t div)
{
if (div & ~SPI_PRESC_gm)
div = SPI_PRESC_DIV64_gc;
SPI.CTRLB = SPI_Mode_Write;
SPI.CTRLA = SPI_MASTER_bm | SPI_ENABLE_bm | div;
SPI.DATA;
SPI.DATA;
SPI.INTFLAGS = 0xff;
SPI.INTCTRL = SPI_TXCIE_bm;
}
uint16_t spi_frame(uint16_t d)
{
if (d)
SPI.CTRLB = SPI_Mode_Write;
else
SPI.CTRLB = SPI_Mode_Read;
SPI.DATA;
SPI.DATA;
SPI.INTFLAGS = 0xff;
spi_tick = 0;
SPI.DATA = d >> 8;
SPI.DATA = d;
uint8_t timeout = 20; // 20×15µs = 300µs
sei();
while (!spi_tick) {
sleep_cpu();
if (!--timeout) {
DEBUG_COUNTER(spi_timeout);
break;
}
}
uint16_t b = SPI.DATA;
return (b<<8) | SPI.DATA;
}
ISR(SPI0_INT_vect, ISR_NAKED)
{
__asm__ ("push r24" "\n\t"
"lds r24, %[flag]" "\n\t"
"sts %[flag], r24" "\n\t"
"sts spi_tick, r24" "\n\t"
"pop r24" "\n\t"
"reti" "\n"
: : [flag] "n" (&SPI.INTFLAGS)
);
}

13
src/spi.h Normal file
View file

@ -0,0 +1,13 @@
//
// spi.h
//
#include <stdint.h>
#include <avr/io.h>
#define SPI SPI0
extern volatile uint8_t spi_tick;
uint16_t spi_frame(uint16_t d);
void init_spi(uint8_t div);
static inline void spi_off() { SPI.INTCTRL = SPI.CTRLA = 0; }

View file

@ -22,9 +22,10 @@ void init_uart(uint16_t div)
div = UART_DIV;
USART0.BAUD = div;
PORTB.DIRSET = Bit(2);
PORTB.PIN3CTRL = PORT_PULLUPEN_bm | PORT_ISC_LEVEL_gc;
USART0.CTRLB = USART_RXEN_bm | USART_TXEN_bm;
USART0.CTRLA = USART_RXCIE_bm;
// `BOTHEDGES` should wake from power down sleep()
PORTB.PIN3CTRL = PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc;
}
uint8_t rx_tick;