Compare commits

...

4 commits

Author SHA1 Message Date
Stephan I. Böttcher
0579532711 leia: RESET_PORT config 2025-10-28 08:55:44 +01:00
Stephan I. Böttcher
d3a29cc6c9 leia: ramp dac only when 'D' 2025-10-27 19:58:35 +01:00
Stephan I. Böttcher
e06a147c6e leia: stepper isr enable only one OCR 2025-10-27 19:56:51 +01:00
Stephan I. Böttcher
fc2affa04e spi_slave: harden _sleep mode 2025-10-27 19:44:39 +01:00
2 changed files with 85 additions and 31 deletions

View file

@ -137,7 +137,7 @@ const struct conf runcon = {
.adc_incr = 16, // one conversions per channel
.adc_period = TICK_NS(1000000),
.dac_step = 0x20,
.pad = "\xff\xff\xff\xff\xff\xff\xff"
.pad = "\xff\xff\xff\xff\xff\xff\xff",
};
void stepper_init()
@ -158,14 +158,19 @@ void stepper_init()
DDRC = DIR | MS1 | MS2 | MS3;
}
static inline
void stepper_run()
{
TCNT1H = 0;
TCNT1L = 0;
TIMSK1 = TIFR1 = (1<<OCIE1B);
}
static inline
void stepper_start(uint8_t reset)
{
RESET_PORT = v.conf.enable & ~reset;
DIR_PORT = v.conf.dir;
TCNT1H = 0;
TCNT1L = 0;
TIMSK1 = (1<<OCIE1B);
}
static inline
@ -175,12 +180,12 @@ void stepper_stop()
}
static inline
char stepper_status()
uint8_t stepper_status()
{
return TIMSK1;
}
#if 1
#if 0
ISR(TIMER1_COMPA_vect)
{
if (!v.conf.n_steps || (LIMIT_PORT & v.conf.lmask) != v.conf.lval) {
@ -190,6 +195,7 @@ ISR(TIMER1_COMPA_vect)
}
v.conf.n_steps--;
STEP_PORT = v.conf.step;
TIMSK1 = TIFR1 = 1<<OCIE1B;
}
#else
ISR(TIMER1_COMPA_vect, ISR_NAKED)
@ -214,6 +220,9 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED)
"sts %[N]+1, r25" "\n\t"
"lds r24, %[S]" "\n\t"
"out %[P], r24" "\n\t"
"ldi r24, %[IE]" "\n\t"
"out %[IFR], r24" "\n\t"
"sts %[MSK], r24" "\n\t"
"pop r25" "\n\t"
"pop r24" "\n\t"
"out __SREG__, r24" "\n\t"
@ -234,18 +243,20 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED)
[V] "m" (v.conf.lval),
[S] "m" (v.conf.step),
[MSK] "n" (_SFR_MEM_ADDR(TIMSK1)),
[IFR] "n" (_SFR_IO_ADDR(TIFR1)),
[IE] "n" (1<<OCIE1B),
[P] "n" (_SFR_IO_ADDR(STEP_PORT)),
[L] "n" (_SFR_IO_ADDR(LIMIT_PORT))
);
}
#endif
#if 1
#if 0
ISR(TIMER1_COMPB_vect)
{
STEP_PORT = 0;
RESET_PORT = v.conf.enable;
TIMSK1 = TIFR1 = 1<<OCIE1B | 1<<OCIE1A;
TIMSK1 = TIFR1 = 1<<OCIE1A;
}
#else
ISR(TIMER1_COMPB_vect, ISR_NAKED)
@ -267,12 +278,12 @@ ISR(TIMER1_COMPB_vect, ISR_NAKED)
[RES] "n" (_SFR_IO_ADDR(RESET_PORT)),
[STP] "n" (_SFR_IO_ADDR(STEP_PORT)),
[ENA] "m" (v.conf.enable),
[IE] "n" (1<<OCIE1B | 1<<OCIE1A)
[IE] "n" (1<<OCIE1A)
);
}
#endif
#if 1
#if 0
ISR(TIMER0_COMPA_vect)
{
uint16_t d = v.stat.dac;
@ -376,6 +387,7 @@ void dac_ramp(uint16_t d)
d &= s;
TIMSK0 = 0;
DACON = 1<<DALA | 1<<DAEN | 1<<DAOE;
OCR0A = OCR0B = v.conf.adc_period;
v.stat.dac = DAC & s;
v.conf.dac_ramp = d;
if (d != v.stat.dac)
@ -715,7 +727,7 @@ static inline
void reg8f(uint8_t *v, unsigned char *r, const unsigned char *c)
{
r[1] = *v;
*v = r[1] & ~c[2] | c[1];
*v = r[1] & ~c[2] | c[1] & ~(r[1] & c[2]);
}
static inline
@ -850,16 +862,13 @@ int main()
while (1) {
unsigned char cmd[3];
unsigned char resp[3];
if (!stepper_status() && v.conf.step && v.conf.n_steps)
stepper_start(0);
stepper_run();
if (spi_slave_Rx(cmd, 3)) {
spi_slave_Tx((const unsigned char*)"\xff\xff\xff" "EEY", 6);
continue;
}
stepper_stop();
char up = upcase(cmd[0]);
if (up)
v.conf.step = 0;
resp[0] = cmd[0];
uint8_t i;
switch (cmd[0] | 0x20) {
@ -878,32 +887,74 @@ int main()
if (up)
RESET_PORT = v.conf.enable;
break;
case 'i': reg8f(&v.conf.dir, resp, cmd);
if (up) {
DIR_PORT = v.conf.dir;
uint8_t s = 0;
if (v.conf.dir & 0x10) s |= STEP1;
if (v.conf.dir & 0x20) s |= STEP2;
STEP_PORT = s;
}
break;
case '0': v.conf.step = 0;
if (0) case '1': v.conf.step = STEP1;
if (0) case '2': v.conf.step = STEP2;
v.conf.dir = cmd[1] & 0xf;
if (cmd[1] & 0x0e)
v.conf.dir = cmd[1] & 0x0f;
else {
v.conf.dir &= 0x0e;
v.conf.dir |= cmd[1] & 1;
}
if (cmd[2])
v.conf.n_steps = cmd[2] << ((cmd[1]>>4) & 7);
v.conf.n_steps = cmd[2] << (cmd[1]>>4);
stepper_start(0);
// fall through, return n_steps
case 's': reg16(&v.conf.n_steps, resp, cmd); break;
case 'r': resp[2] = cmd[2];
switch (cmd[2] & 0x3) {
case 0: reg8(&v.conf.reset, resp, cmd);
case 1: reg8(&v.conf.disable, resp, cmd);
case 2: reg8(&v.conf.awake, resp, cmd);
case 3: reg8(&v.conf.ledoff, resp, cmd);
switch (cmd[2] & 0x3) { // define RESET_PORT bits
case 0: reg8(&v.conf.reset, resp, cmd); break;
case 1: reg8(&v.conf.disable, resp, cmd); break;
case 2: reg8(&v.conf.ledoff, resp, cmd); break;
case 3: reg8(&v.conf.awake, resp, cmd); break;
}
if (up && cmd[2] & 0x3)
v.conf.enable = v.conf.awake | v.conf.ledoff | v.conf.disable;
if (cmd[2] & 0x40)
switch (cmd[2] & 0x0c) {
case 0x04: // set RESET_PORT bits
switch (cmd[2] & 0x3) {
case 0: v.conf.enable |= v.conf.reset; break;
case 1: v.conf.enable |= v.conf.disable; break;
case 2: v.conf.enable |= v.conf.ledoff; break;
case 3: v.conf.enable |= v.conf.awake; break;
}
break;
case 0x08: // clear RESET_PORT bits
switch (cmd[2] & 0x3) {
case 0: v.conf.enable &=~ v.conf.reset; break;
case 1: v.conf.enable &=~ v.conf.disable; break;
case 2: v.conf.enable &=~ v.conf.ledoff; break;
case 3: v.conf.enable &=~ v.conf.awake; break;
}
break;
case 0x0c: // assign enable/disable/ledoff/sleep
v.conf.enable = v.conf.awake | v.conf.reset;
switch (cmd[2] & 0x3) { // no breaks
case 3: v.conf.enable &=~ v.conf.awake;
case 2: v.conf.enable |= v.conf.ledoff;
case 1: v.conf.enable |= v.conf.disable;
}
break;
}
if (cmd[2] & 0x10) // drive PORT
RESET_PORT = v.conf.enable;
if (cmd[2] & 0x80)
if (cmd[2] & 0x20) // assert RESET
RESET_PORT &=~ v.conf.reset;
if (cmd[2] & 0x40) // reinitialize
stepper_init();
if (cmd[2] & 0x10)
if (cmd[2] & 0x80) // pulse the reset pin(s)
stepper_start(v.conf.reset);
break;
case 'd': reg16(&v.stat.dac, resp, cmd);
dac_ramp(v.stat.dac);
if (up)
dac_ramp(v.stat.dac);
break;
case 'p': reg16(&v.conf.dac_step, resp, cmd); break;
case 'a':

View file

@ -186,9 +186,12 @@ static inline
unsigned char spi_slave_Tx_sei(const unsigned char d[], unsigned char n)
{
n = spi_slave_Tx_n(d, n);
while (!PIN_SSEL);
while (!PIN_SSEL)
if (SPSR & SPSR_IF) {
SPSR;
SPDR = 0;
}
PCIFR |= PCIF_SSEL;
sei();
return n;
}
@ -216,7 +219,7 @@ unsigned char spi_slave_Rx_sleep(unsigned char d[], unsigned char n)
while (!PIN_SSEL) {
if (SPSR & SPSR_IF) {
SPSR;
SPDR;
SPDR = 0;
}
sei();
sleep_cpu();