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)
|
PATH:=/usr/local/bin:$(PATH)
|
||||||
|
|
||||||
default: all
|
default: all
|
||||||
all: $(PROJ).hex
|
all: $(PROJ).hex $(PROJ)_all
|
||||||
|
|
||||||
|
dose_all: dose.eeprom dose.userrow
|
||||||
|
|
||||||
SN_dose = 1
|
SN_dose = 1
|
||||||
MCU_dose = $(MCU_$(VAR))
|
MCU_dose = $(MCU_$(VAR))
|
||||||
|
|
|
||||||
|
|
@ -209,6 +209,8 @@ uint8_t adc_poll(uint8_t flags)
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
if (flags) {
|
if (flags) {
|
||||||
|
if (flags & ADC_RTC && !rtc_cnt_tick())
|
||||||
|
return 1;
|
||||||
#ifdef HAVE_nFETs
|
#ifdef HAVE_nFETs
|
||||||
if (flags & ADC_PWM)
|
if (flags & ADC_PWM)
|
||||||
pwm_step(config.pwm_max);
|
pwm_step(config.pwm_max);
|
||||||
|
|
|
||||||
|
|
@ -41,4 +41,5 @@ enum adc_flags {
|
||||||
ADC_16 = 0x10,
|
ADC_16 = 0x10,
|
||||||
ADC_32 = 0x20,
|
ADC_32 = 0x20,
|
||||||
ADC_64 = 0x40,
|
ADC_64 = 0x40,
|
||||||
|
ADC_RTC = 0x80,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ const struct config config = {
|
||||||
[0] = 0xd1 | FM_READ>>8, // Buffer 1 Read (Low-Frequency)
|
[0] = 0xd1 | FM_READ>>8, // Buffer 1 Read (Low-Frequency)
|
||||||
[1] = 0xd3 | FM_READ>>8, // Buffer 2 Read (Low-Frequency)
|
[1] = 0xd3 | FM_READ>>8, // Buffer 2 Read (Low-Frequency)
|
||||||
},
|
},
|
||||||
|
.page_start = 0x0800,
|
||||||
|
.page_end = 0x1000,
|
||||||
#ifdef HAVE_nFETs
|
#ifdef HAVE_nFETs
|
||||||
.pwm_min = 0x0000,
|
.pwm_min = 0x0000,
|
||||||
.pwm_max = 0xffff,
|
.pwm_max = 0xffff,
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@ struct config {
|
||||||
uint16_t write_buffer;
|
uint16_t write_buffer;
|
||||||
uint16_t read_array;
|
uint16_t read_array;
|
||||||
uint16_t read_buffer[2];
|
uint16_t read_buffer[2];
|
||||||
|
uint16_t page_start;
|
||||||
|
uint16_t page_end;
|
||||||
#ifdef HAVE_nFETs
|
#ifdef HAVE_nFETs
|
||||||
uint16_t pwm_min;
|
uint16_t pwm_min;
|
||||||
uint16_t pwm_max;
|
uint16_t pwm_max;
|
||||||
|
|
|
||||||
19
src/dose.c
19
src/dose.c
|
|
@ -26,10 +26,15 @@
|
||||||
|
|
||||||
section_status(main) struct magic magic;
|
section_status(main) struct magic magic;
|
||||||
|
|
||||||
const struct pipe_config cron_job[1] =
|
struct pipe_config cron_job[1] =
|
||||||
{
|
{
|
||||||
[0] = {
|
[0] = {
|
||||||
.pipe = {
|
.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;
|
magic.reset_source = RSTCTRL.RSTFR;
|
||||||
RSTCTRL.RSTFR = magic.reset_source;
|
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);
|
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) {
|
while (1) {
|
||||||
sei();
|
sei();
|
||||||
sleep_cpu();
|
sleep_cpu();
|
||||||
command();
|
command();
|
||||||
pipe_poll();
|
pipe_poll();
|
||||||
if (rtc_tick) {
|
if (config.cron & 2 && rtc_cnt_tick())
|
||||||
rtc_tick = 0;
|
|
||||||
if (config.cron)
|
|
||||||
pipe_config(cron_job);
|
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_PAD2: pads += 1;
|
||||||
case FM_PAD1: 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) {
|
if (size >= 128) {
|
||||||
// for read of the security register
|
// for read of the security register
|
||||||
pads += size-64;
|
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);
|
b = cmd_buffer + (what-96);
|
||||||
else if (size <= 2)
|
else if (size <= 2)
|
||||||
b = flash_status_bytes;
|
b = flash_status_bytes;
|
||||||
else
|
|
||||||
return what;
|
|
||||||
switch (mode & FM_START) {
|
switch (mode & FM_START) {
|
||||||
case FM_WRITE:
|
case FM_WRITE:
|
||||||
spi_start_write(csize, flash_cmd_buffer, size, b);
|
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 {
|
struct flash_cmd {
|
||||||
uint16_t mode, what, page, byte;
|
uint16_t mode, what, page, byte;
|
||||||
uint8_t buffer[8];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t flash_submit_command(uint8_t *cmd)
|
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
|
// request status bytes for pending Write or Error
|
||||||
r |= FS_StBsy;
|
r |= FS_StBsy;
|
||||||
fs.status = r;
|
fs.status = r;
|
||||||
flash_cmd_na(0xd7, 0xff02);
|
flash_cmd_na(0xd7 | FM_READ, 0xf002);
|
||||||
return r;
|
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;
|
flash_status_bytes[0] = 0xff;
|
||||||
return flash_poll(0);
|
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_submit_command(uint8_t *cmd);
|
||||||
uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags);
|
uint8_t flash_start_stream(uint16_t page, uint16_t npages, uint8_t flags);
|
||||||
uint8_t flash_poll(uint8_t rr);
|
uint8_t flash_poll(uint8_t rr);
|
||||||
|
uint16_t flash_find_free();
|
||||||
|
|
||||||
extern
|
extern
|
||||||
struct flash_stream {
|
struct flash_stream {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ void fpga_cmd(struct fpga_cmd *c)
|
||||||
spi_select(0);
|
spi_select(0);
|
||||||
spi.zero = c->n & 0x80; // send nop: 0x8080 (please), or zeros
|
spi.zero = c->n & 0x80; // send nop: 0x8080 (please), or zeros
|
||||||
spi.csize = n;
|
spi.csize = n;
|
||||||
spi.wdata = c->d;
|
spi.cmd = c->d;
|
||||||
spi.rdata = c->d;
|
spi.rdata = c->d;
|
||||||
if (c->z & 0x80) {
|
if (c->z & 0x80) {
|
||||||
spi.isize = n + z>>3 & 0x0e; // ignore cmd ± (z[6:4])
|
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))
|
if (pipe.dest & pipe_flash && !(fl & FS_Ready))
|
||||||
// flash did not finish successfully
|
// flash did not finish successfully
|
||||||
goto done;
|
goto done;
|
||||||
|
if (pipe.source & pipe_adc && !adc_poll(pipe.adc))
|
||||||
|
goto done;
|
||||||
|
|
||||||
// fpga is OUT when the spi is ready.
|
// fpga is OUT when the spi is ready.
|
||||||
// We are done with this buffer
|
// We are done with this buffer
|
||||||
pipe.valid = 0;
|
pipe.valid = 0;
|
||||||
if (pipe.source & pipe_flash)
|
if (pipe.source & pipe_flash)
|
||||||
flash_poll(1);
|
flash_poll(1);
|
||||||
else if (pipe.source & pipe_adc)
|
|
||||||
adc_poll(pipe.adc);
|
|
||||||
#ifdef HAVE_FPGA
|
#ifdef HAVE_FPGA
|
||||||
else if (pipe.source & pipe_fpga)
|
else if (pipe.source & pipe_fpga)
|
||||||
fpga_start(0);
|
fpga_start(0);
|
||||||
#endif
|
#endif
|
||||||
r |=~ PS_OUT;
|
r &=~ (PS_OUT|4);
|
||||||
r &= ~4;
|
|
||||||
r++;
|
r++;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,15 @@ volatile uint16_t clockh;
|
||||||
volatile uint8_t pit_tick;
|
volatile uint8_t pit_tick;
|
||||||
volatile uint8_t rtc_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) = {
|
struct_ioconf(rtc_config) = {
|
||||||
conf_prefix(RTC),
|
conf_prefix(RTC),
|
||||||
conf_iow(RTC.CMP, 3600),
|
conf_iow(RTC.CMP, 3600),
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,5 @@ volatile extern uint16_t clockh;
|
||||||
volatile extern uint8_t pit_tick;
|
volatile extern uint8_t pit_tick;
|
||||||
volatile extern uint8_t rtc_tick;
|
volatile extern uint8_t rtc_tick;
|
||||||
uint32_t time();
|
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),
|
conf_io(SPI.CTRLA, SPI_MASTER_bm | SPI_ENABLE_bm | SPI_SPEED),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 0
|
||||||
ISR(SPI0_INT_vect)
|
ISR(SPI0_INT_vect)
|
||||||
{
|
{
|
||||||
|
uint8_t d;
|
||||||
uint8_t ifg = SPI.INTFLAGS;
|
uint8_t ifg = SPI.INTFLAGS;
|
||||||
while (ifg & SPI_DREIF_bm) {
|
if (ifg & SPI_DREIF_bm) {
|
||||||
|
repeat:
|
||||||
if (spi.csize) {
|
if (spi.csize) {
|
||||||
SPI.DATA = *spi.cmd++;
|
|
||||||
spi.csize--;
|
spi.csize--;
|
||||||
|
d = *spi.cmd++;
|
||||||
}
|
}
|
||||||
else if (spi.zsize) {
|
else if (spi.zsize) {
|
||||||
SPI.DATA = spi.zero;
|
|
||||||
spi.zsize--;
|
spi.zsize--;
|
||||||
|
d = spi.zero;
|
||||||
}
|
}
|
||||||
else if (spi.wsize) {
|
else if (spi.wsize) {
|
||||||
if (spi.wdata)
|
spi.wsize--;
|
||||||
SPI.DATA = *spi.wdata++;
|
d = *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;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SPI.INTCTRL = SPI_TXCIF_bm | SPI_RXCIF_bm;
|
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;
|
ifg = SPI.INTFLAGS;
|
||||||
}
|
}
|
||||||
while (ifg & SPI_RXCIF_bm) {
|
if (ifg & SPI_RXCIF_bm) {
|
||||||
uint8_t d = SPI.DATA; // clears the IF flag
|
d = SPI.DATA; // clears the IF flag
|
||||||
if (spi.isize)
|
if (spi.isize)
|
||||||
spi.isize --;
|
spi.isize --;
|
||||||
else {
|
else {
|
||||||
if (spi.mask) {
|
if (spi.mask) {
|
||||||
if ((d & spi.mask) == spi.wait) {
|
if ((d & spi.mask) == spi.wait) {
|
||||||
spi.zsize++;
|
spi.zsize++;
|
||||||
SPI.INTCTRL = SPI_DREIF_bm | SPI_RXCIF_bm;
|
goto cont;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
spi.mask = 0;
|
spi.mask = 0;
|
||||||
}
|
}
|
||||||
if (spi.rsize) {
|
if (spi.rsize) {
|
||||||
*spi.rdata++ = d;
|
|
||||||
spi.rsize--;
|
spi.rsize--;
|
||||||
}
|
*spi.rdata++ = d;
|
||||||
else if (!spi.mask) {
|
|
||||||
SPI.INTCTRL = SPI_DREIF_bm;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
cont:
|
||||||
ifg = SPI.INTFLAGS;
|
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)
|
uint8_t spi_select(uint8_t mode)
|
||||||
{
|
{
|
||||||
|
|
@ -80,9 +231,9 @@ uint8_t spi_select(uint8_t mode)
|
||||||
memset(&spi, 0, sizeof(spi));
|
memset(&spi, 0, sizeof(spi));
|
||||||
spi.mode = mode;
|
spi.mode = mode;
|
||||||
if (mode & SPI_FLASH)
|
if (mode & SPI_FLASH)
|
||||||
SSEL_PORT.OUT &=~ (1 << SSEL_PIN);
|
SSEL_VPORT.OUT &=~ (1 << SSEL_PIN);
|
||||||
else
|
else
|
||||||
SSEL_PORT.OUT |= 1 << SSEL_PIN;
|
SSEL_VPORT.OUT |= 1 << SSEL_PIN;
|
||||||
if (mode & SPI_CONFIG)
|
if (mode & SPI_CONFIG)
|
||||||
SPI.CTRLA |= SPI_DORD_bm;
|
SPI.CTRLA |= SPI_DORD_bm;
|
||||||
else
|
else
|
||||||
|
|
@ -90,7 +241,6 @@ uint8_t spi_select(uint8_t mode)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void spi_start_cmd(uint8_t csize, uint8_t *cmd)
|
void spi_start_cmd(uint8_t csize, uint8_t *cmd)
|
||||||
{
|
{
|
||||||
spi.cmd = 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.rdata = rdata;
|
||||||
spi.isize = csize + spi.zsize;
|
spi.isize = csize + spi.zsize;
|
||||||
barrier();
|
barrier();
|
||||||
spi.wsize = rsize; // more zeros
|
spi.zsize += rsize;
|
||||||
spi.rsize = rsize;
|
spi.rsize = rsize;
|
||||||
spi_start_cmd(csize, cmd);
|
spi_start_cmd(csize, cmd);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
src/spi.h
10
src/spi.h
|
|
@ -14,7 +14,6 @@
|
||||||
extern
|
extern
|
||||||
struct spi_job {
|
struct spi_job {
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
uint8_t status;
|
|
||||||
uint8_t csize; // pipe.fpga.…
|
uint8_t csize; // pipe.fpga.…
|
||||||
uint8_t zsize; //
|
uint8_t zsize; //
|
||||||
uint8_t isize; //
|
uint8_t isize; //
|
||||||
|
|
@ -34,10 +33,6 @@ enum spi_mode_bits {
|
||||||
SPI_CONT = 0x80,
|
SPI_CONT = 0x80,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum spi_status_bits {
|
|
||||||
SPI_IDLE = 0x01,
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
uint8_t spi_abort()
|
uint8_t spi_abort()
|
||||||
{
|
{
|
||||||
|
|
@ -51,13 +46,14 @@ uint8_t spi_abort()
|
||||||
static inline
|
static inline
|
||||||
uint8_t spi_busy_p()
|
uint8_t spi_busy_p()
|
||||||
{
|
{
|
||||||
return SPI.INTFLAGS;
|
return SPI.INTFLAGS & SPI_TXCIF_bm;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void spi_start()
|
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"); }
|
static inline void barrier() { __asm__("":::"memory"); }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue