Compare commits

..

No commits in common. "fb7c5498faba32b4d818c9f87f0a751d62b0274f" and "b57552a3e7302fe06e5a1eba3dc610ed49596390" have entirely different histories.

View file

@ -60,8 +60,8 @@ const char revision[] = Id;
#define VERSION 1 #define VERSION 1
struct conf { struct conf {
uint16_t magic; // 0 unsigned int magic; // 0
uint8_t version; // 2 unsigned char version; // 2
uint8_t flags; // 3 uint8_t flags; // 3
uint16_t period; // 4 uint16_t period; // 4
uint16_t slen; // 6 uint16_t slen; // 6
@ -72,26 +72,20 @@ struct conf {
uint8_t reset; // 12 uint8_t reset; // 12
uint8_t dir; // 13 uint8_t dir; // 13
uint16_t n_steps; // 14 uint16_t n_steps; // 14
uint16_t dac; // 16
uint16_t dac_ramp; // 18 uint16_t dac_ramp; // 18
uint16_t dac_step; // 20 uint16_t dac_step; // 20
uint8_t adc_idx; // 22
uint8_t adc_incr; // 23 uint8_t adc_incr; // 23
uint8_t adc_period; // 24 uint8_t adc_period; // 24
uint8_t pad[7]; // 25 uint8_t pad[7]; // 25
uint8_t adc_ch[16]; // 32 uint8_t adc_ch[16]; // 32
}; } conf; // 64
struct stat { enum {
uint16_t adc[16]; // 48 FLAG_WDT = 1,
uint16_t dac; // 80
uint8_t adc_idx; // 82
uint8_t pad[45]; //128
}; };
struct vars {
struct conf conf;
struct stat stat;
} v;
#define STEP_RESOLUTION 23148L // ns #define STEP_RESOLUTION 23148L // ns
#define STEP_NS(ns) (((ns)+STEP_RESOLUTION/2)/STEP_RESOLUTION) #define STEP_NS(ns) (((ns)+STEP_RESOLUTION/2)/STEP_RESOLUTION)
#define TICK_RESOLUTION 92593L // ns #define TICK_RESOLUTION 92593L // ns
@ -138,12 +132,12 @@ void stepper_init()
// 16-bit Timer 1 PWM by OCR1A, prescaled by 256 // 16-bit Timer 1 PWM by OCR1A, prescaled by 256
TCCR1A = 1<<WGM10 | 1<<WGM11 ; TCCR1A = 1<<WGM10 | 1<<WGM11 ;
TCCR1B = 1<<WGM12 | 1<<WGM13 | 4<<CS10; TCCR1B = 1<<WGM12 | 1<<WGM13 | 4<<CS10;
OCR1AH = v.conf.period >> 8; OCR1AH = conf.period >> 8;
OCR1AL = v.conf.period; OCR1AL = conf.period;
OCR1BH = v.conf.slen >> 8; OCR1BH = conf.slen >> 8;
OCR1BL = v.conf.slen; OCR1BL = conf.slen;
RESET_PORT = v.conf.enable & ~v.conf.reset; RESET_PORT = conf.enable & ~conf.reset;
DIR_PORT = v.conf.dir; DIR_PORT = conf.dir;
STEP_PORT = 0; STEP_PORT = 0;
DDRB = MISO | RESET | ENABLE | SLEEP | LEDON; DDRB = MISO | RESET | ENABLE | SLEEP | LEDON;
DDRD = STEP1 | STEP2; DDRD = STEP1 | STEP2;
@ -153,8 +147,8 @@ void stepper_init()
static inline static inline
void stepper_start(uint8_t reset) void stepper_start(uint8_t reset)
{ {
RESET_PORT = v.conf.enable & ~reset; RESET_PORT = conf.enable & ~reset;
DIR_PORT = v.conf.dir; DIR_PORT = conf.dir;
TCNT1H = 0; TCNT1H = 0;
TCNT1L = 0; TCNT1L = 0;
TIMSK1 = (1<<OCIE1B); TIMSK1 = (1<<OCIE1B);
@ -175,13 +169,13 @@ char stepper_status()
#if 1 #if 1
ISR(TIMER1_COMPA_vect) ISR(TIMER1_COMPA_vect)
{ {
if (!v.conf.n_steps || (LIMIT_PORT & v.conf.lmask) != v.conf.lval) { if (!conf.n_steps || (LIMIT_PORT & conf.lmask) != conf.lval) {
STEP_PORT = 0; STEP_PORT = 0;
TIMSK1 = 0; TIMSK1 = 0;
return; return;
} }
v.conf.n_steps--; conf.n_steps--;
STEP_PORT = v.conf.step; STEP_PORT = conf.step;
} }
#else #else
ISR(TIMER1_COMPA_vect, ISR_NAKED) ISR(TIMER1_COMPA_vect, ISR_NAKED)
@ -221,10 +215,10 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED)
"out __SREG__, r24" "\n\t" "out __SREG__, r24" "\n\t"
"pop r24" "\n\t" "pop r24" "\n\t"
"reti" "\n" "reti" "\n"
:[N] "+m" (v.conf.n_steps) :[N] "+m" (conf.n_steps)
:[M] "m" (v.conf.lmask), :[M] "m" (conf.lmask),
[V] "m" (v.conf.lval), [V] "m" (conf.lval),
[S] "m" (v.conf.step), [S] "m" (conf.step),
[MSK] "n" (_SFR_MEM_ADDR(TIMSK1)), [MSK] "n" (_SFR_MEM_ADDR(TIMSK1)),
[P] "n" (_SFR_IO_ADDR(STEP_PORT)), [P] "n" (_SFR_IO_ADDR(STEP_PORT)),
[L] "n" (_SFR_IO_ADDR(LIMIT_PORT)) [L] "n" (_SFR_IO_ADDR(LIMIT_PORT))
@ -236,7 +230,7 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED)
ISR(TIMER1_COMPB_vect) ISR(TIMER1_COMPB_vect)
{ {
STEP_PORT = 0; STEP_PORT = 0;
RESET_PORT = v.conf.enable; RESET_PORT = conf.enable;
TIMSK1 = TIFR1 = 1<<OCIE1B | 1<<OCIE1A; TIMSK1 = TIFR1 = 1<<OCIE1B | 1<<OCIE1A;
} }
#else #else
@ -258,7 +252,7 @@ ISR(TIMER1_COMPB_vect, ISR_NAKED)
[IFR] "n" (_SFR_IO_ADDR(TIFR1)), [IFR] "n" (_SFR_IO_ADDR(TIFR1)),
[RES] "n" (_SFR_IO_ADDR(RESET_PORT)), [RES] "n" (_SFR_IO_ADDR(RESET_PORT)),
[STP] "n" (_SFR_IO_ADDR(STEP_PORT)), [STP] "n" (_SFR_IO_ADDR(STEP_PORT)),
[ENA] "m" (v.conf.enable), [ENA] "m" (conf.enable),
[IE] "n" (1<<OCIE1B | 1<<OCIE1A) [IE] "n" (1<<OCIE1B | 1<<OCIE1A)
); );
} }
@ -267,19 +261,19 @@ ISR(TIMER1_COMPB_vect, ISR_NAKED)
#if 1 #if 1
ISR(TIMER0_COMPA_vect) ISR(TIMER0_COMPA_vect)
{ {
uint16_t d = v.stat.dac; uint16_t d = conf.dac;
if (d == v.conf.dac_ramp) { if (d == conf.dac_ramp) {
TIMSK0 = 0; TIMSK0 = 0;
return; return;
} }
uint16_t s = v.conf.dac_step; uint16_t s = conf.dac_step;
if (d > v.conf.dac_ramp) if (d > conf.dac_ramp)
d -= s; d -= s;
else else
d += s; d += s;
DACL = d; DACL = d;
DACH = d>>8; DACH = d>>8;
v.stat.dac = d; conf.dac = d;
} }
#else #else
// Avoid some push, pop, cp, and jumps // Avoid some push, pop, cp, and jumps
@ -336,9 +330,9 @@ ISR(TIMER0_COMPA_vect, ISR_NAKED)
"out __SREG__, r24" "\n\t" "out __SREG__, r24" "\n\t"
"pop r24" "\n\t" "pop r24" "\n\t"
"reti" "\n" "reti" "\n"
:[D] "+m" (v.stat.dac) :[D] "+m" (conf.dac)
:[R] "m" (v.conf.dac_ramp), :[R] "m" (conf.dac_ramp),
[S] "m" (v.conf.dac_step), [S] "m" (conf.dac_step),
[MSK] "n" (_SFR_MEM_ADDR(TIMSK0)), [MSK] "n" (_SFR_MEM_ADDR(TIMSK0)),
[DH] "n" (_SFR_MEM_ADDR(DACH)), [DH] "n" (_SFR_MEM_ADDR(DACH)),
[DL] "n" (_SFR_MEM_ADDR(DACL)) [DL] "n" (_SFR_MEM_ADDR(DACL))
@ -353,13 +347,13 @@ void dac_set(uint16_t d)
DACL = d; DACL = d;
DACH = d>>8; DACH = d>>8;
DACON = 1<<DALA | 1<<DAEN | 1<<DAOE; DACON = 1<<DALA | 1<<DAEN | 1<<DAOE;
v.stat.dac = v.conf.dac_ramp = d; conf.dac = conf.dac_ramp = d;
} }
static static
void dac_ramp(uint16_t d) void dac_ramp(uint16_t d)
{ {
uint16_t s = v.conf.dac_step; uint16_t s = conf.dac_step;
if (!s) { if (!s) {
dac_set(d); dac_set(d);
return; return;
@ -368,9 +362,9 @@ void dac_ramp(uint16_t d)
d &= s; d &= s;
TIMSK0 = 0; TIMSK0 = 0;
DACON = 1<<DALA | 1<<DAEN | 1<<DAOE; DACON = 1<<DALA | 1<<DAEN | 1<<DAOE;
v.stat.dac = DAC & s; conf.dac = DAC & s;
v.conf.dac_ramp = d; conf.dac_ramp = d;
if (d != v.stat.dac) if (d != conf.dac)
TIMSK0 = 1<<OCIE0A; TIMSK0 = 1<<OCIE0A;
} }
@ -389,9 +383,9 @@ static
void adc_start(uint8_t i) void adc_start(uint8_t i)
{ {
i &= 15; i &= 15;
v.stat.adc_idx = i<<4; conf.adc_idx = i<<4;
OCR0A = OCR0B = v.conf.adc_period; OCR0A = OCR0B = conf.adc_period;
uint8_t ch = v.conf.adc_ch[i]; uint8_t ch = conf.adc_ch[i];
if (!(ch & 1<<REFS0)) if (!(ch & 1<<REFS0))
return; return;
ADMUX = ch; ADMUX = ch;
@ -405,6 +399,8 @@ void adc_stop()
ADCSRA = 1<<ADEN | 1<<ADIF | 6<<ADPS0; ADCSRA = 1<<ADEN | 1<<ADIF | 6<<ADPS0;
} }
uint16_t adc[16];
#if 1 #if 1
ISR(ADC_vect) ISR(ADC_vect)
{ {
@ -414,17 +410,17 @@ ISR(ADC_vect)
a |= ADCH<<8; a |= ADCH<<8;
} }
else { else {
a = v.stat.adc[v.stat.adc_idx >> 4]; a = adc[conf.adc_idx >> 4];
a -= a>>6; a -= a>>6;
a += ADCL; a += ADCL;
a += ADCH<<8; a += ADCH<<8;
} }
v.stat.adc[v.stat.adc_idx >> 4] = a; adc[conf.adc_idx >> 4] = a;
v.stat.adc_idx += v.conf.adc_incr; conf.adc_idx += conf.adc_incr;
uint8_t ch = v.conf.adc_ch[v.stat.adc_idx >> 4]; uint8_t ch = conf.adc_ch[conf.adc_idx >> 4];
if (!(ch & 1<<REFS0)) { if (!(ch & 1<<REFS0)) {
v.stat.adc_idx = 0; conf.adc_idx = 0;
ch = v.conf.adc_ch[0]; ch = conf.adc_ch[0];
} }
if (!(ch & 1<<REFS0)) if (!(ch & 1<<REFS0))
adc_stop(); adc_stop();
@ -526,10 +522,10 @@ ISR(ADC_vect, ISR_NAKED)
"out __SREG__, r24" "\n\t" "out __SREG__, r24" "\n\t"
"pop r24" "\n\t" "pop r24" "\n\t"
"reti" "\n" "reti" "\n"
:[I] "+m" (v.stat.adc_idx), :[I] "+m" (conf.adc_idx),
[D] "+m" (v.stat.adc) [D] "+m" (adc)
:[C] "m" (v.conf.adc_ch), :[C] "m" (conf.adc_ch),
[II] "m" (v.conf.adc_incr), [II] "m" (conf.adc_incr),
[AL] "n" (_SFR_MEM_ADDR(ADCL)), [AL] "n" (_SFR_MEM_ADDR(ADCL)),
[AH] "n" (_SFR_MEM_ADDR(ADCH)), [AH] "n" (_SFR_MEM_ADDR(ADCH)),
[X] "n" (_SFR_MEM_ADDR(ADMUX)), [X] "n" (_SFR_MEM_ADDR(ADMUX)),
@ -547,8 +543,8 @@ static void conf_init()
{ {
cli(); cli();
adc_init(); adc_init();
adc_start(v.stat.adc_idx>>4); adc_start(conf.adc_idx>>4);
dac_set(v.conf.dac_ramp); dac_set(conf.dac_ramp);
stepper_init(); stepper_init();
} }
@ -567,7 +563,7 @@ ISR(EE_READY_vect)
eewr_n = --n; eewr_n = --n;
EEAR = eewr_a + n; EEAR = eewr_a + n;
EECR |= 1<<EERE; EECR |= 1<<EERE;
uint8_t d = ((uint8_t*)&v.conf)[n]; uint8_t d = ((uint8_t*)&conf)[n];
if (EEDR == d) if (EEDR == d)
continue; continue;
EEDR = d; EEDR = d;
@ -602,8 +598,8 @@ ISR(EE_READY_vect, ISR_NAKED)
"adc r30, r31" "\n\t" "adc r30, r31" "\n\t"
"out %[AH], r30" "\n\t" "out %[AH], r30" "\n\t"
"sbi %[C], %[RE]" "\n\t" "sbi %[C], %[RE]" "\n\t"
"ldi r30, lo8(%[V])" "\n\t" "ldi r30, lo8(conf)" "\n\t"
"ldi r31, hi8($[V])" "\n\t" "ldi r31, hi8(conf)" "\n\t"
"add r30, r24" "\n\t" "add r30, r24" "\n\t"
"brcc 3f" "\n\t" "brcc 3f" "\n\t"
"subi r31, -1" "\n" "subi r31, -1" "\n"
@ -628,8 +624,7 @@ ISR(EE_READY_vect, ISR_NAKED)
"pop r24" "\n\t" "pop r24" "\n\t"
"reti" "\n" "reti" "\n"
: :
:[V] "m" (v.conf), :[C] "n" (_SFR_IO_ADDR(EECR)),
[C] "n" (_SFR_IO_ADDR(EECR)),
[AL] "n" (_SFR_IO_ADDR(EEARL)), [AL] "n" (_SFR_IO_ADDR(EEARL)),
[AH] "n" (_SFR_IO_ADDR(EEARH)), [AH] "n" (_SFR_IO_ADDR(EEARH)),
[D] "n" (_SFR_IO_ADDR(EEDR)), [D] "n" (_SFR_IO_ADDR(EEDR)),
@ -645,10 +640,12 @@ ISR(EE_READY_vect, ISR_NAKED)
static inline static inline
uint8_t eeprom_save(uint16_t a) uint8_t eeprom_save(uint16_t a)
{ {
// eeprom_update_block(&conf, (void*)a, sizeof(conf));
if (EECR & 1<<EERIE) if (EECR & 1<<EERIE)
return 1; return 1;
eewr_a = a; eewr_a = a;
eewr_n = sizeof(struct conf); eewr_n = sizeof(conf);
GPIOR2 = 0; GPIOR2 = 0;
EECR = 1<<EERIE; EECR = 1<<EERIE;
return 0; return 0;
@ -657,13 +654,14 @@ uint8_t eeprom_save(uint16_t a)
static inline static inline
uint8_t eeprom_load(uint16_t a) uint8_t eeprom_load(uint16_t a)
{ {
// eeprom_read_block(&conf, (void*)a, sizeof(conf));
cli(); cli();
if (EECR & 1<<EEWE) { if (EECR & 1<<EEWE) {
sei(); sei();
return 1; return 1;
} }
uint8_t n = sizeof(struct conf); uint8_t n = sizeof(conf);
uint8_t *c = (uint8_t*)&v.conf; uint8_t *c = (uint8_t*)&conf;
while (n--) { while (n--) {
EEAR = a++; EEAR = a++;
EECR |= 1<<EERE; EECR |= 1<<EERE;
@ -791,7 +789,7 @@ void reg88(uint8_t *v1, uint8_t *v2, unsigned char *r, const unsigned char *c)
// 'Z': eeprom what, a // 'Z': eeprom what, a
// what=='e' or 'E": read eeprom from address a*4 to conf // what=='e' or 'E": read eeprom from address a*4 to conf
// what=='F': ignore magic/version mismatch // what=='F': ignore magic/version mismatch
// what=='E' or 'F': reinitialize with v.conf. // what=='E' or 'F': reinitialize with conf.
// 'y': peek a // 'y': peek a
// 'Y': poke a, v // 'Y': poke a, v
@ -800,9 +798,7 @@ void reg88(uint8_t *v1, uint8_t *v2, unsigned char *r, const unsigned char *c)
// interrupts are disabled, so that the SPI reciever can respond to // interrupts are disabled, so that the SPI reciever can respond to
// all bytes in time. All commands execute fast, the master µC shall // all bytes in time. All commands execute fast, the master µC shall
// not time out while waiting for the reponse. The stepping timer is // not time out while waiting for the reponse. The stepping timer is
// restarted after command execution, when any steps are pending. // restarted after command execution, when any steps are commanded.
// The CPU sleeps while waiting for a command from the SPI, until SSEL
// goes low.
// //
// Interrupts // Interrupts
// PCINT2: disable global interrupts // PCINT2: disable global interrupts
@ -821,13 +817,13 @@ int main()
DDRB = MISO; DDRB = MISO;
eeprom_load(0); eeprom_load(0);
adc_init(); adc_init();
if (v.conf.magic == MAGIC && v.conf.version == VERSION) if (conf.magic == MAGIC && conf.version == VERSION)
conf_init(); conf_init();
while (1) { while (1) {
unsigned char cmd[3]; unsigned char cmd[3];
unsigned char resp[3]; unsigned char resp[3];
if (!stepper_status() && v.conf.step && v.conf.n_steps) if (!stepper_status() && conf.step && conf.n_steps)
stepper_start(0); stepper_start(0);
if (spi_slave_Rx(cmd, 3)) { if (spi_slave_Rx(cmd, 3)) {
spi_slave_Tx((const unsigned char*)"\xff\xff\xff" "EEY", 6); spi_slave_Tx((const unsigned char*)"\xff\xff\xff" "EEY", 6);
@ -836,7 +832,7 @@ int main()
stepper_stop(); stepper_stop();
char up = upcase(cmd[0]); char up = upcase(cmd[0]);
if (up) if (up)
v.conf.step = 0; conf.step = 0;
resp[0] = cmd[0]; resp[0] = cmd[0];
uint8_t i; uint8_t i;
switch (cmd[0] | 0x20) { switch (cmd[0] | 0x20) {
@ -845,49 +841,49 @@ int main()
resp[1] = 'E'; resp[1] = 'E';
resp[2] = cmd[0]; resp[2] = cmd[0];
break; break;
case 'm': reg88(&v.conf.lmask, &v.conf.lval, resp, cmd); break; case 'm': reg88(&conf.lmask, &conf.lval, resp, cmd); break;
case 'q': reg16(&v.conf.period, resp, cmd); case 'q': reg16(&conf.period, resp, cmd);
if (0) case 'l': reg16(&v.conf.slen, resp, cmd); if (0) case 'l': reg16(&conf.slen, resp, cmd);
if (up) if (up)
stepper_init(); stepper_init();
break; break;
case 'o': reg8f(&v.conf.enable, resp, cmd); case 'o': reg8f(&conf.enable, resp, cmd);
if (up) if (up)
RESET_PORT = v.conf.enable; RESET_PORT = conf.enable;
break; break;
case '0': v.conf.step = 0; case '0': conf.step = 0;
if (0) case '1': v.conf.step = STEP1; if (0) case '1': conf.step = STEP1;
if (0) case '2': v.conf.step = STEP2; if (0) case '2': conf.step = STEP2;
v.conf.dir = cmd[1] & 0xf; conf.dir = cmd[1] & 0xf;
if (cmd[2]) if (cmd[2])
v.conf.n_steps = cmd[2] << ((cmd[1]>>4) & 7); conf.n_steps = cmd[2] << ((cmd[1]>>4) & 7);
// fall through, return n_steps // fall through, return n_steps
case 's': reg16(&v.conf.n_steps, resp, cmd); break; case 's': reg16(&conf.n_steps, resp, cmd); break;
case 'r': reg8(&v.conf.reset, resp, cmd); case 'r': reg8(&conf.reset, resp, cmd);
resp[2] = cmd[2]; resp[2] = cmd[2];
if (cmd[2]) { if (cmd[2]) {
v.conf.step = 0; conf.step = 0;
if (cmd[2] & 0x80) if (cmd[2] & 0x80)
stepper_init(); stepper_init();
if (cmd[2] & 1) if (cmd[2] & 1)
stepper_start(v.conf.reset); stepper_start(conf.reset);
} }
break; break;
case 'd': reg16(&v.stat.dac, resp, cmd); case 'd': reg16(&conf.dac, resp, cmd);
dac_ramp(v.stat.dac); dac_ramp(conf.dac);
break; break;
case 'p': reg16(&v.conf.dac_step, resp, cmd); break; case 'p': reg16(&conf.dac_step, resp, cmd); break;
case 'a': case 'a':
resp[2] = cmd[2]; resp[2] = cmd[2];
i = cmd[2] & 15; i = cmd[2] & 15;
switch ((cmd[2]>>4) & 7) { switch ((cmd[2]>>4) & 7) {
case 0: int2frame(v.stat.adc[i], resp+1); case 0: int2frame(adc[i], resp+1);
if (up) v.stat.adc[i] = 0; if (up) adc[i] = 0;
break; break;
case 1: reg8(v.conf.adc_ch+i, resp, cmd); break; case 1: reg8(conf.adc_ch+i, resp, cmd); break;
case 2: reg8(&v.stat.adc_idx, resp, cmd); break; case 2: reg8(&conf.adc_idx, resp, cmd); break;
case 3: reg8(&v.conf.adc_incr, resp, cmd); break; case 3: reg8(&conf.adc_incr, resp, cmd); break;
case 4: reg8(&v.conf.adc_period, resp, cmd); break; case 4: reg8(&conf.adc_period, resp, cmd); break;
case 5: reg8(&ADMUX, resp, cmd); break; case 5: reg8(&ADMUX, resp, cmd); break;
case 6: reg8(&ADCSRA, resp, cmd); break; case 6: reg8(&ADCSRA, resp, cmd); break;
case 7: reg8(&ADCH, resp, cmd); break; case 7: reg8(&ADCH, resp, cmd); break;
@ -909,7 +905,7 @@ int main()
break; break;
case 'z': // Load/Save conf case 'z': // Load/Save conf
resp[1] = cmd[1]; resp[1] = cmd[1];
resp[2] = sizeof(struct conf); resp[2] = sizeof(conf);
if (!up) { if (!up) {
if (cmd[1]!='W' || eeprom_save(cmd[2]*4)) { if (cmd[1]!='W' || eeprom_save(cmd[2]*4)) {
resp[0] = 'E'; resp[0] = 'E';
@ -926,9 +922,9 @@ int main()
break; break;
} }
} }
if (v.conf.magic != MAGIC || v.conf.version != VERSION) { if (conf.magic != MAGIC || conf.version != VERSION) {
resp[0] = 'E'; resp[0] = 'E';
resp[2] = v.conf.version; resp[2] = conf.version;
if (cmd[1] != 'F') if (cmd[1] != 'F')
break; break;
} }
@ -937,14 +933,14 @@ int main()
break; break;
case 'x': // conf Byte case 'x': // conf Byte
resp[2] = cmd[1]; resp[2] = cmd[1];
if (cmd[1] >= sizeof(struct vars)) { if (cmd[1] >= sizeof(conf)) {
resp[0] = 'E'; resp[0] = 'E';
resp[1] = sizeof(struct vars); resp[1] = sizeof(conf);
break; break;
} }
resp[1] = ((unsigned char *)(&v))[cmd[1]]; resp[1] = ((unsigned char *)(&conf))[cmd[1]];
if (up) if (up)
((unsigned char *)(&v))[cmd[1]] = cmd[2]; ((unsigned char *)(&conf))[cmd[1]] = cmd[2];
break; break;
case 'y': // peek, poke case 'y': // peek, poke
resp[2] = cmd[1]; resp[2] = cmd[1];