mirror of
https://codeberg.org/SiB64/turbo_weather.git
synced 2026-05-01 15:14:22 +02:00
Compare commits
No commits in common. "899798defa43163e9ff9ada8d4aa45541bcb03df" and "977af7648b6336345eb8749150b67a2d1ffb81b3" have entirely different histories.
899798defa
...
977af7648b
14 changed files with 53 additions and 272 deletions
|
|
@ -4,9 +4,7 @@ PROJ=dose
|
||||||
PATH:=/usr/local/bin:$(PATH)
|
PATH:=/usr/local/bin:$(PATH)
|
||||||
|
|
||||||
default: all
|
default: all
|
||||||
all: $(PROJ).hex $(PROJ)_all
|
all: $(PROJ).hex
|
||||||
|
|
||||||
dose_all: dose.eeprom dose.userrow
|
|
||||||
|
|
||||||
SN_dose = 1
|
SN_dose = 1
|
||||||
MCU_dose = $(MCU_$(VAR))
|
MCU_dose = $(MCU_$(VAR))
|
||||||
|
|
|
||||||
|
|
@ -209,8 +209,6 @@ 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,5 +41,4 @@ 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,8 +20,6 @@ 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,8 +17,6 @@ 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;
|
||||||
|
|
|
||||||
21
src/dose.c
21
src/dose.c
|
|
@ -26,15 +26,10 @@
|
||||||
|
|
||||||
section_status(main) struct magic magic;
|
section_status(main) struct magic magic;
|
||||||
|
|
||||||
struct pipe_config cron_job[1] =
|
const 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,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
@ -56,20 +51,18 @@ 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.0");
|
send_str("\nV Turbo Dose V0.9");
|
||||||
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 (config.cron & 2 && rtc_cnt_tick())
|
if (rtc_tick) {
|
||||||
pipe_config(cron_job);
|
rtc_tick = 0;
|
||||||
|
if (config.cron)
|
||||||
|
pipe_config(cron_job);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
53
src/flash.c
53
src/flash.c
|
|
@ -124,12 +124,6 @@ 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;
|
||||||
|
|
@ -142,6 +136,8 @@ 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);
|
||||||
|
|
@ -159,6 +155,7 @@ 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)
|
||||||
|
|
@ -278,7 +275,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 | FM_READ, 0xf002);
|
flash_cmd_na(0xd7, 0xff02);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -319,45 +316,3 @@ 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,7 +29,6 @@ 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.cmd = c->d;
|
spi.wdata = 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|4);
|
r |=~ PS_OUT;
|
||||||
|
r &= ~4;
|
||||||
r++;
|
r++;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,15 +14,6 @@ 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,5 +10,3 @@ 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();
|
|
||||||
|
|
|
||||||
208
src/spi.c
208
src/spi.c
|
|
@ -15,213 +15,62 @@ 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;
|
||||||
if (ifg & SPI_DREIF_bm) {
|
while (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) {
|
||||||
spi.wsize--;
|
if (spi.wdata)
|
||||||
d = *spi.wdata++;
|
SPI.DATA = *spi.wdata++;
|
||||||
|
else
|
||||||
|
SPI.DATA = spi.zero;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SPI.INTCTRL = SPI_TXCIF_bm | SPI_RXCIF_bm;
|
if (ifg & SPI_TXCIF_bm) {
|
||||||
goto done_write;
|
if (!(spi.mode & SPI_CONT))
|
||||||
|
SSEL_PORT.OUT |= 1 << SSEL_PIN;
|
||||||
|
spi.status |= SPI_IDLE;
|
||||||
|
SPI.INTCTRL = SPI_RXCIF_bm;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SPI.INTCTRL = SPI_TXCIF_bm | SPI_RXCIF_bm;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
if (ifg & SPI_RXCIF_bm) {
|
while (ifg & SPI_RXCIF_bm) {
|
||||||
d = SPI.DATA; // clears the IF flag
|
uint8_t 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++;
|
||||||
goto cont;
|
SPI.INTCTRL = SPI_DREIF_bm | SPI_RXCIF_bm;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
spi.mask = 0;
|
spi.mask = 0;
|
||||||
}
|
}
|
||||||
if (spi.rsize) {
|
if (spi.rsize) {
|
||||||
spi.rsize--;
|
|
||||||
*spi.rdata++ = d;
|
*spi.rdata++ = d;
|
||||||
|
spi.rsize--;
|
||||||
|
}
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
|
|
@ -231,9 +80,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_VPORT.OUT &=~ (1 << SSEL_PIN);
|
SSEL_PORT.OUT &=~ (1 << SSEL_PIN);
|
||||||
else
|
else
|
||||||
SSEL_VPORT.OUT |= 1 << SSEL_PIN;
|
SSEL_PORT.OUT |= 1 << SSEL_PIN;
|
||||||
if (mode & SPI_CONFIG)
|
if (mode & SPI_CONFIG)
|
||||||
SPI.CTRLA |= SPI_DORD_bm;
|
SPI.CTRLA |= SPI_DORD_bm;
|
||||||
else
|
else
|
||||||
|
|
@ -241,6 +90,7 @@ 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;
|
||||||
|
|
@ -262,7 +112,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.zsize += rsize;
|
spi.wsize = rsize; // more zeros
|
||||||
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,6 +14,7 @@
|
||||||
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; //
|
||||||
|
|
@ -33,6 +34,10 @@ 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()
|
||||||
{
|
{
|
||||||
|
|
@ -46,14 +51,13 @@ uint8_t spi_abort()
|
||||||
static inline
|
static inline
|
||||||
uint8_t spi_busy_p()
|
uint8_t spi_busy_p()
|
||||||
{
|
{
|
||||||
return SPI.INTFLAGS & SPI_TXCIF_bm;
|
return SPI.INTFLAGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
void spi_start()
|
void spi_start()
|
||||||
{
|
{
|
||||||
SPI.INTCTRL = SPI_DREIF_bm;
|
SPI.INTCTRL = SPI_DREIF_bm | SPI_RXCIF_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