mirror of
https://codeberg.org/SiB64/turbo_weather.git
synced 2026-05-01 15:14:22 +02:00
Compare commits
5 commits
977af7648b
...
899798defa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
899798defa | ||
|
|
26e39e219e | ||
|
|
0248c1dab2 | ||
|
|
60abd1ab89 | ||
|
|
0e878a6fa4 |
14 changed files with 272 additions and 53 deletions
|
|
@ -4,7 +4,9 @@ PROJ=dose
|
|||
PATH:=/usr/local/bin:$(PATH)
|
||||
|
||||
default: all
|
||||
all: $(PROJ).hex
|
||||
all: $(PROJ).hex $(PROJ)_all
|
||||
|
||||
dose_all: dose.eeprom dose.userrow
|
||||
|
||||
SN_dose = 1
|
||||
MCU_dose = $(MCU_$(VAR))
|
||||
|
|
|
|||
|
|
@ -209,6 +209,8 @@ uint8_t adc_poll(uint8_t flags)
|
|||
if (r)
|
||||
return r;
|
||||
if (flags) {
|
||||
if (flags & ADC_RTC && !rtc_cnt_tick())
|
||||
return 1;
|
||||
#ifdef HAVE_nFETs
|
||||
if (flags & ADC_PWM)
|
||||
pwm_step(config.pwm_max);
|
||||
|
|
|
|||
|
|
@ -41,4 +41,5 @@ enum adc_flags {
|
|||
ADC_16 = 0x10,
|
||||
ADC_32 = 0x20,
|
||||
ADC_64 = 0x40,
|
||||
ADC_RTC = 0x80,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ const struct config config = {
|
|||
[0] = 0xd1 | FM_READ>>8, // Buffer 1 Read (Low-Frequency)
|
||||
[1] = 0xd3 | FM_READ>>8, // Buffer 2 Read (Low-Frequency)
|
||||
},
|
||||
.page_start = 0x0800,
|
||||
.page_end = 0x1000,
|
||||
#ifdef HAVE_nFETs
|
||||
.pwm_min = 0x0000,
|
||||
.pwm_max = 0xffff,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ struct config {
|
|||
uint16_t write_buffer;
|
||||
uint16_t read_array;
|
||||
uint16_t read_buffer[2];
|
||||
uint16_t page_start;
|
||||
uint16_t page_end;
|
||||
#ifdef HAVE_nFETs
|
||||
uint16_t pwm_min;
|
||||
uint16_t pwm_max;
|
||||
|
|
|
|||
19
src/dose.c
19
src/dose.c
|
|
@ -26,10 +26,15 @@
|
|||
|
||||
section_status(main) struct magic magic;
|
||||
|
||||
const struct pipe_config cron_job[1] =
|
||||
struct pipe_config cron_job[1] =
|
||||
{
|
||||
[0] = {
|
||||
.pipe = {
|
||||
.source = pipe_adc,
|
||||
.dest = pipe_cmd,
|
||||
.status = PS_OUT | PS_BCH,
|
||||
.valid = 0,
|
||||
.adc = ADC_64 | ADC_PWM | ADC_RTC,
|
||||
},
|
||||
|
||||
},
|
||||
|
|
@ -51,18 +56,20 @@ int main()
|
|||
|
||||
magic.reset_source = RSTCTRL.RSTFR;
|
||||
RSTCTRL.RSTFR = magic.reset_source;
|
||||
send_str("\nV Turbo Dose V0.9");
|
||||
send_str("\nV Turbo Dose V0.0");
|
||||
send_hex_byte_eol(magic.reset_source);
|
||||
|
||||
cron_job[0].page = flash_find_free();
|
||||
cron_job[0].npages = config.page_end - cron_job[0].page;
|
||||
if (config.cron & 1)
|
||||
pipe_config(cron_job);
|
||||
|
||||
while (1) {
|
||||
sei();
|
||||
sleep_cpu();
|
||||
command();
|
||||
pipe_poll();
|
||||
if (rtc_tick) {
|
||||
rtc_tick = 0;
|
||||
if (config.cron)
|
||||
if (config.cron & 2 && rtc_cnt_tick())
|
||||
pipe_config(cron_job);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
53
src/flash.c
53
src/flash.c
|
|
@ -124,6 +124,12 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte)
|
|||
case FM_PAD2: pads += 1;
|
||||
case FM_PAD1: pads += 1;
|
||||
}
|
||||
if (!(mode & FM_START)) {
|
||||
spi.zsize = pads + size;
|
||||
spi.zero = what;
|
||||
spi_start_cmd(csize, flash_cmd_buffer);
|
||||
return 0;
|
||||
}
|
||||
if (size >= 128) {
|
||||
// for read of the security register
|
||||
pads += size-64;
|
||||
|
|
@ -136,8 +142,6 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte)
|
|||
b = cmd_buffer + (what-96);
|
||||
else if (size <= 2)
|
||||
b = flash_status_bytes;
|
||||
else
|
||||
return what;
|
||||
switch (mode & FM_START) {
|
||||
case FM_WRITE:
|
||||
spi_start_write(csize, flash_cmd_buffer, size, b);
|
||||
|
|
@ -155,7 +159,6 @@ uint8_t flash_cmd(uint16_t mode, uint16_t what, uint16_t page, uint16_t byte)
|
|||
|
||||
struct flash_cmd {
|
||||
uint16_t mode, what, page, byte;
|
||||
uint8_t buffer[8];
|
||||
};
|
||||
|
||||
uint8_t flash_submit_command(uint8_t *cmd)
|
||||
|
|
@ -275,7 +278,7 @@ uint8_t flash_poll(uint8_t rr)
|
|||
// request status bytes for pending Write or Error
|
||||
r |= FS_StBsy;
|
||||
fs.status = r;
|
||||
flash_cmd_na(0xd7, 0xff02);
|
||||
flash_cmd_na(0xd7 | FM_READ, 0xf002);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
|
@ -316,3 +319,45 @@ uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags)
|
|||
flash_status_bytes[0] = 0xff;
|
||||
return flash_poll(0);
|
||||
}
|
||||
|
||||
static inline
|
||||
uint8_t flash_memset_buffer2()
|
||||
{
|
||||
for (uint16_t i=0; i<528; i += 176) {
|
||||
uint8_t r = flash_cmd((uint16_t)config.flash_page_size << 8 | 0xff87, 176, 0, i);
|
||||
if (r)
|
||||
return r;
|
||||
while (spi_busy_p()) ;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline
|
||||
uint8_t flash_compare_buffer2(uint16_t p)
|
||||
{
|
||||
uint8_t r;
|
||||
r = flash_cmd((uint16_t)config.flash_page_size << 8 | 0x61, 0, p, 0);
|
||||
if (r)
|
||||
return r;
|
||||
while (spi_busy_p()) ;
|
||||
r = flash_cmd_na(0xd7 | FM_WAIT, 0xf002);
|
||||
if (r)
|
||||
return r;
|
||||
while (spi_busy_p()) ;
|
||||
return (flash_status_bytes[0] | flash_status_bytes[1]) & 0x40;
|
||||
}
|
||||
|
||||
uint16_t flash_find_free()
|
||||
{
|
||||
flash_memset_buffer2();
|
||||
uint16_t a = config.page_start;
|
||||
uint16_t e = config.page_end;
|
||||
while (e > a) {
|
||||
uint16_t p = (a+e)>>1;
|
||||
if (flash_compare_buffer2(p))
|
||||
a = p;
|
||||
else
|
||||
e = p;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ extern uint8_t flash_buffer[FB_SIZE];
|
|||
uint8_t flash_submit_command(uint8_t *cmd);
|
||||
uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags);
|
||||
uint8_t flash_poll(uint8_t rr);
|
||||
uint16_t flash_find_free();
|
||||
|
||||
extern
|
||||
struct flash_stream {
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ void fpga_cmd(struct fpga_cmd *c)
|
|||
spi_select(0);
|
||||
spi.zero = c->n & 0x80; // send nop: 0x8080 (please), or zeros
|
||||
spi.csize = n;
|
||||
spi.wdata = c->d;
|
||||
spi.cmd = c->d;
|
||||
spi.rdata = c->d;
|
||||
if (c->z & 0x80) {
|
||||
spi.isize = n + z>>3 & 0x0e; // ignore cmd ± (z[6:4])
|
||||
|
|
|
|||
|
|
@ -28,19 +28,19 @@ uint8_t pipe_poll()
|
|||
if (pipe.dest & pipe_flash && !(fl & FS_Ready))
|
||||
// flash did not finish successfully
|
||||
goto done;
|
||||
if (pipe.source & pipe_adc && !adc_poll(pipe.adc))
|
||||
goto done;
|
||||
|
||||
// fpga is OUT when the spi is ready.
|
||||
// We are done with this buffer
|
||||
pipe.valid = 0;
|
||||
if (pipe.source & pipe_flash)
|
||||
flash_poll(1);
|
||||
else if (pipe.source & pipe_adc)
|
||||
adc_poll(pipe.adc);
|
||||
#ifdef HAVE_FPGA
|
||||
else if (pipe.source & pipe_fpga)
|
||||
fpga_start(0);
|
||||
#endif
|
||||
r |=~ PS_OUT;
|
||||
r &= ~4;
|
||||
r &=~ (PS_OUT|4);
|
||||
r++;
|
||||
goto done;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,15 @@ volatile uint16_t clockh;
|
|||
volatile uint8_t pit_tick;
|
||||
volatile uint8_t rtc_tick;
|
||||
|
||||
uint8_t rtc_cnt_tick()
|
||||
{
|
||||
cli();
|
||||
uint8_t r = rtc_tick;
|
||||
rtc_tick = 0;
|
||||
sei();
|
||||
return r;
|
||||
}
|
||||
|
||||
struct_ioconf(rtc_config) = {
|
||||
conf_prefix(RTC),
|
||||
conf_iow(RTC.CMP, 3600),
|
||||
|
|
|
|||
|
|
@ -10,3 +10,5 @@ volatile extern uint16_t clockh;
|
|||
volatile extern uint8_t pit_tick;
|
||||
volatile extern uint8_t rtc_tick;
|
||||
uint32_t time();
|
||||
|
||||
uint8_t rtc_cnt_tick();
|
||||
|
|
|
|||
206
src/spi.c
206
src/spi.c
|
|
@ -15,62 +15,213 @@ struct_ioconf(spi_config) = {
|
|||
conf_io(SPI.CTRLA, SPI_MASTER_bm | SPI_ENABLE_bm | SPI_SPEED),
|
||||
};
|
||||
|
||||
#if 0
|
||||
ISR(SPI0_INT_vect)
|
||||
{
|
||||
uint8_t d;
|
||||
uint8_t ifg = SPI.INTFLAGS;
|
||||
while (ifg & SPI_DREIF_bm) {
|
||||
if (ifg & SPI_DREIF_bm) {
|
||||
repeat:
|
||||
if (spi.csize) {
|
||||
SPI.DATA = *spi.cmd++;
|
||||
spi.csize--;
|
||||
d = *spi.cmd++;
|
||||
}
|
||||
else if (spi.zsize) {
|
||||
SPI.DATA = spi.zero;
|
||||
spi.zsize--;
|
||||
d = spi.zero;
|
||||
}
|
||||
else if (spi.wsize) {
|
||||
if (spi.wdata)
|
||||
SPI.DATA = *spi.wdata++;
|
||||
else
|
||||
SPI.DATA = spi.zero;
|
||||
}
|
||||
else {
|
||||
if (ifg & SPI_TXCIF_bm) {
|
||||
if (!(spi.mode & SPI_CONT))
|
||||
SSEL_PORT.OUT |= 1 << SSEL_PIN;
|
||||
spi.status |= SPI_IDLE;
|
||||
SPI.INTCTRL = SPI_RXCIF_bm;
|
||||
spi.wsize--;
|
||||
d = *spi.wdata++;
|
||||
}
|
||||
else {
|
||||
SPI.INTCTRL = SPI_TXCIF_bm | SPI_RXCIF_bm;
|
||||
goto done_write;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SPI.DATA = d;
|
||||
// clear a stray TXCIF, at high SCK rate
|
||||
SPI.INTFLAGS = SPI_TXCIF_bm;
|
||||
SPI.INTCTRL = SPI_TXCIF_bm | SPI_DREIF_bm | SPI_RXCIF_bm;
|
||||
done_write:
|
||||
ifg = SPI.INTFLAGS;
|
||||
}
|
||||
while (ifg & SPI_RXCIF_bm) {
|
||||
uint8_t d = SPI.DATA; // clears the IF flag
|
||||
if (ifg & SPI_RXCIF_bm) {
|
||||
d = SPI.DATA; // clears the IF flag
|
||||
if (spi.isize)
|
||||
spi.isize --;
|
||||
else {
|
||||
if (spi.mask) {
|
||||
if ((d & spi.mask) == spi.wait) {
|
||||
spi.zsize++;
|
||||
SPI.INTCTRL = SPI_DREIF_bm | SPI_RXCIF_bm;
|
||||
continue;
|
||||
goto cont;
|
||||
}
|
||||
spi.mask = 0;
|
||||
}
|
||||
if (spi.rsize) {
|
||||
*spi.rdata++ = d;
|
||||
spi.rsize--;
|
||||
}
|
||||
else if (!spi.mask) {
|
||||
SPI.INTCTRL = SPI_DREIF_bm;
|
||||
*spi.rdata++ = d;
|
||||
}
|
||||
}
|
||||
cont:
|
||||
ifg = SPI.INTFLAGS;
|
||||
if (ifg & SPI_DREIF_bm)
|
||||
// This may prevent this ISR to terminate
|
||||
// before the job is done at high clock rate.
|
||||
// DRE is kept set when all bytes were sent.
|
||||
// With just the right clock rate, we may send
|
||||
// two bytes per interrupt.
|
||||
goto repeat;
|
||||
}
|
||||
if (ifg & SPI_TXCIF_bm) {
|
||||
if (!(spi.mode & SPI_CONT))
|
||||
SSEL_VPORT.OUT |= 1 << SSEL_PIN;
|
||||
SPI.INTCTRL = SPI_RXCIF_bm;
|
||||
}
|
||||
}
|
||||
#else
|
||||
ISR(SPI0_INT_vect, ISR_NAKED)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"push r24" "\n\t"
|
||||
"in r24, __SREG__" "\n\t"
|
||||
"push r24" "\n\t"
|
||||
"push r25" "\n\t"
|
||||
"push r26" "\n\t"
|
||||
"push r30" "\n\t"
|
||||
"push r31" "\n\t"
|
||||
"lds r24, %[IFLGS]" "\n\t"
|
||||
|
||||
"3:" "\n\t"
|
||||
"sbrs r24, %[DRE]" "\n\t"
|
||||
"rjmp 3f" "\n"
|
||||
|
||||
"5:" "\n"
|
||||
"lds r25, %[CSZ]" "\n\t"
|
||||
"subi r25, 1" "\n\t"
|
||||
"brcs 1f" "\n\t"
|
||||
"sts %[CSZ], r25" "\n\t"
|
||||
"lds r30, %[CMD]" "\n\t"
|
||||
"lds r31, %[CMD]+1" "\n\t"
|
||||
"ld r25, Z+" "\n\t"
|
||||
"sts %[CMD], r30" "\n\t"
|
||||
"sts %[CMD]+1, r31" "\n\t"
|
||||
"rjmp 2f" "\n"
|
||||
|
||||
"1:" "\n\t"
|
||||
"lds r25, %[ZSZ]" "\n\t"
|
||||
"subi r25, 1" "\n\t"
|
||||
"brcs 1f" "\n\t"
|
||||
"sts %[ZSZ], r25" "\n\t"
|
||||
"lds r25, %[ZERO]" "\n\t"
|
||||
"rjmp 2f" "\n"
|
||||
|
||||
"1:" "\n\t"
|
||||
"lds r25, %[WSZ]" "\n\t"
|
||||
"subi r25, 1" "\n\t"
|
||||
"ldi r26, %[RIFLGS]" "\n\t"
|
||||
"brcs 1f" "\n\t"
|
||||
"sts %[WSZ], r25" "\n\t"
|
||||
"lds r30, %[WD]" "\n\t"
|
||||
"lds r31, %[WD]+1" "\n\t"
|
||||
"ld r25, Z+" "\n\t"
|
||||
"sts %[WD], r30" "\n\t"
|
||||
"sts %[WD]+1, r31" "\n"
|
||||
|
||||
"2:" "\n\t"
|
||||
"sts %[DATA], r25" "\n\t"
|
||||
"ldi r25, 1<<%[TXC]" "\n\t"
|
||||
"sts %[IFLGS], r25" "\n\t"
|
||||
"ldi r26, %[AIFLGS]" "\n"
|
||||
|
||||
"1:" "\n\t"
|
||||
"sts %[ICTRL], r26" "\n\t"
|
||||
"lds r24, %[IFLGS]" "\n"
|
||||
"sbrs r24, %[RXC]" "\n\t"
|
||||
"rjmp 3f" "\n\t"
|
||||
"lds r25, %[DATA]" "\n\t"
|
||||
"lds r26, %[ISZ]" "\n\t"
|
||||
"subi r26, 1" "\n\t"
|
||||
"brcs 1f " "\n\t"
|
||||
"sts %[ISZ], r26" "\n\t"
|
||||
"rjmp 4f" "\n"
|
||||
|
||||
"1:" "\n\t"
|
||||
"lds r26, %[MASK]" "\n\t"
|
||||
"cpi r26, 0" "\n\t"
|
||||
"breq 1f" "\n\t"
|
||||
"and r26, r25" "\n\t"
|
||||
"lds r24, %[WAIT]" "\n\t"
|
||||
"cp r24, r26" "\n\t"
|
||||
"brne 2f" "\n\t"
|
||||
"lds r25, %[ZSZ]" "\n\t"
|
||||
"subi r25, -1" "\n\t"
|
||||
"sts %[ZSZ], r25" "\n\t"
|
||||
"rjmp 4f" "\n"
|
||||
|
||||
"2:" "\n\t"
|
||||
"clr r26" "\n\t"
|
||||
"sts %[MASK], r26" "\n"
|
||||
|
||||
"1:" "\n\t"
|
||||
"lds r26, %[RSZ]" "\n\t"
|
||||
"subi r26, 1" "\n\t"
|
||||
"brcs 4f" "\n\t"
|
||||
"sts %[RSZ], r26" "\n\t"
|
||||
"lds r30, %[RD]" "\n\t"
|
||||
"lds r31, %[RD]+1" "\n\t"
|
||||
"st Z+, r25" "\n\t"
|
||||
"sts %[RD], r30" "\n\t"
|
||||
"sts %[RD]+1, r31" "\n"
|
||||
|
||||
"4:" "\n\t"
|
||||
"lds r24, %[IFLGS]" "\n\t"
|
||||
"sbrc r24, %[DRE]" "\n\t"
|
||||
"rjmp 5b" "\n\t"
|
||||
|
||||
"3:" "\n\t"
|
||||
"sbrs r24, %[TXC]" "\n\t"
|
||||
"rjmp 3f" "\n\t"
|
||||
"lds r25, %[MODE]" "\n\t"
|
||||
"sbrs r25, 7" "\n\t"
|
||||
"sbi %[SPORT], %[SSEL]" "\n\t"
|
||||
"ldi r25, 1<<%[RXC]" "\n\t"
|
||||
"sts %[ICTRL], r25" "\n"
|
||||
|
||||
"3:" "\n\t"
|
||||
"pop r31" "\n\t"
|
||||
"pop r30" "\n\t"
|
||||
"pop r26" "\n\t"
|
||||
"pop r25" "\n\t"
|
||||
"pop r24" "\n\t"
|
||||
"out __SREG__, r24" "\n\t"
|
||||
"pop r24" "\n\t"
|
||||
"reti" "\n"
|
||||
::
|
||||
[CSZ] "m" (spi.csize),
|
||||
[ZSZ] "m" (spi.zsize),
|
||||
[WSZ] "m" (spi.wsize),
|
||||
[ISZ] "m" (spi.isize),
|
||||
[RSZ] "m" (spi.rsize),
|
||||
[CMD] "m" (spi.cmd),
|
||||
[ZERO] "m" (spi.zero),
|
||||
[WD] "m" (spi.wdata),
|
||||
[RD] "m" (spi.rdata),
|
||||
[MODE] "m" (spi.mode),
|
||||
[MASK] "m" (spi.mask),
|
||||
[WAIT] "m" (spi.wait),
|
||||
[IFLGS] "n" (&SPI.INTFLAGS),
|
||||
[TXC] "n" (SPI_TXCIF_bp),
|
||||
[DRE] "n" (SPI_DREIF_bp),
|
||||
[RXC] "n" (SPI_RXCIF_bp),
|
||||
[RIFLGS] "n" (SPI_TXCIF_bm | SPI_RXCIF_bm),
|
||||
[AIFLGS] "n" (SPI_TXCIF_bm | SPI_RXCIF_bm | SPI_DREIF_bm),
|
||||
[ICTRL] "n" (&SPI.INTCTRL),
|
||||
[DATA] "n" (&SPI.DATA),
|
||||
[SPORT] "n" (_SFR_IO_ADDR(SSEL_VPORT)),
|
||||
[SSEL] "n" (SSEL_PIN)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t spi_select(uint8_t mode)
|
||||
{
|
||||
|
|
@ -80,9 +231,9 @@ uint8_t spi_select(uint8_t mode)
|
|||
memset(&spi, 0, sizeof(spi));
|
||||
spi.mode = mode;
|
||||
if (mode & SPI_FLASH)
|
||||
SSEL_PORT.OUT &=~ (1 << SSEL_PIN);
|
||||
SSEL_VPORT.OUT &=~ (1 << SSEL_PIN);
|
||||
else
|
||||
SSEL_PORT.OUT |= 1 << SSEL_PIN;
|
||||
SSEL_VPORT.OUT |= 1 << SSEL_PIN;
|
||||
if (mode & SPI_CONFIG)
|
||||
SPI.CTRLA |= SPI_DORD_bm;
|
||||
else
|
||||
|
|
@ -90,7 +241,6 @@ uint8_t spi_select(uint8_t mode)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void spi_start_cmd(uint8_t csize, uint8_t *cmd)
|
||||
{
|
||||
spi.cmd = cmd;
|
||||
|
|
@ -112,7 +262,7 @@ void spi_start_read(uint8_t csize, uint8_t *cmd, uint8_t rsize, uint8_t *rdata)
|
|||
spi.rdata = rdata;
|
||||
spi.isize = csize + spi.zsize;
|
||||
barrier();
|
||||
spi.wsize = rsize; // more zeros
|
||||
spi.zsize += rsize;
|
||||
spi.rsize = rsize;
|
||||
spi_start_cmd(csize, cmd);
|
||||
}
|
||||
|
|
|
|||
10
src/spi.h
10
src/spi.h
|
|
@ -14,7 +14,6 @@
|
|||
extern
|
||||
struct spi_job {
|
||||
uint8_t mode;
|
||||
uint8_t status;
|
||||
uint8_t csize; // pipe.fpga.…
|
||||
uint8_t zsize; //
|
||||
uint8_t isize; //
|
||||
|
|
@ -34,10 +33,6 @@ enum spi_mode_bits {
|
|||
SPI_CONT = 0x80,
|
||||
};
|
||||
|
||||
enum spi_status_bits {
|
||||
SPI_IDLE = 0x01,
|
||||
};
|
||||
|
||||
static inline
|
||||
uint8_t spi_abort()
|
||||
{
|
||||
|
|
@ -51,13 +46,14 @@ uint8_t spi_abort()
|
|||
static inline
|
||||
uint8_t spi_busy_p()
|
||||
{
|
||||
return SPI.INTFLAGS;
|
||||
return SPI.INTFLAGS & SPI_TXCIF_bm;
|
||||
}
|
||||
|
||||
static inline
|
||||
void spi_start()
|
||||
{
|
||||
SPI.INTCTRL = SPI_DREIF_bm | SPI_RXCIF_bm;
|
||||
SPI.INTCTRL = SPI_DREIF_bm;
|
||||
// the ISR will immediately set SPI_TXCIF_bm.
|
||||
}
|
||||
|
||||
static inline void barrier() { __asm__("":::"memory"); }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue