Compare commits
18 commits
3b7a32b26e
...
df870da929
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df870da929 | ||
|
|
de6e5d2e1d | ||
|
|
a7504da2ff | ||
|
|
7f3cb0583a | ||
|
|
c20fe169b4 | ||
|
|
82d18d3e66 | ||
|
|
0f8632bb57 | ||
|
|
71a95be193 | ||
|
|
2d38e63320 | ||
|
|
7158c9f6b0 | ||
|
|
6f26cd9469 | ||
|
|
23194ceabb | ||
|
|
ff93d268e4 | ||
|
|
a758c33f6f | ||
|
|
feaa93e086 | ||
|
|
511bfc0cce | ||
|
|
84338f287c | ||
|
|
49643bd07e |
3 changed files with 297 additions and 159 deletions
413
chaos/chaos.c
413
chaos/chaos.c
|
|
@ -8,7 +8,6 @@ const char *revision =
|
|||
|
||||
"$Id$";
|
||||
|
||||
#define PIN_SSEL (PIND & (1<<PD3))
|
||||
#include "spi_slave.h"
|
||||
|
||||
#include "ads8688.h"
|
||||
|
|
@ -16,7 +15,6 @@ const char *revision =
|
|||
unsigned char read_adc(unsigned char c, unsigned char n);
|
||||
void adc_read(unsigned char chs, unsigned char n);
|
||||
unsigned int read_auxadc();
|
||||
unsigned int read_hvadc();
|
||||
void dac_ramp(unsigned int target);
|
||||
void ads8688_cmd(const unsigned char *c, unsigned char *r);
|
||||
void ltc1655_cmd(const unsigned char *c);
|
||||
|
|
@ -27,6 +25,17 @@ void ads8688_config();
|
|||
#include "hvosc.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/sleep.h>
|
||||
|
||||
void die()
|
||||
{
|
||||
while (1) {
|
||||
cli();
|
||||
set_sleep_mode(SLEEP_MODE_IDLE);
|
||||
sleep_enable();
|
||||
sleep_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned char disable_irq()
|
||||
{
|
||||
|
|
@ -66,7 +75,7 @@ static inline void avrdac_set(unsigned int d)
|
|||
#include <avr/wdt.h>
|
||||
void wdt_init(unsigned char mode);
|
||||
unsigned char wdt_count;
|
||||
unsigned char wdt_saved;
|
||||
volatile unsigned char wdt_tick;
|
||||
|
||||
enum {
|
||||
WDT_MODE_LIVE = 2, // = any command kick
|
||||
|
|
@ -82,52 +91,54 @@ static inline void wdt_kick()
|
|||
}
|
||||
|
||||
// ADS8688 gains Channels:
|
||||
// 0: ±2.5 Vref = ± 10.24V 0: Iprim, 0.5V/A, ± 0.64V
|
||||
// 1: ±1.25 Vref = ± 5.12V 1: HV Mon, ±5V
|
||||
// 2: ±0.625 Vref = ± 2.56V 2: Vdrv, 0…10V
|
||||
// 3: ±0.3125 Vref = ± 1.28V 3: NTC, 0…5V
|
||||
// b: ±0.15625 Vref = ± 0.64V 4: Vprim/11, 0…5V
|
||||
// 5: 0…2.5 Vref = 0…10.24V 5: 5V/2, 0…5V
|
||||
// 6: 0.1,25 Vref = 0… 5.12V 6: I_bias, ±2.56V
|
||||
// 7: 0.625 Vref = 0… 2.56V 7: Idrv, 0…10V
|
||||
// 0: ±2.5 Vref = ± 10.24V 0: b: Iprim, 0.5V/A, ± 0.64V
|
||||
// 1: ±1.25 Vref = ± 5.12V 1: 5: Vdrv, 0…10V
|
||||
// 2: ±0.625 Vref = ± 2.56V 2: 1: HV Mon, ±5V
|
||||
// 3: ±0.3125 Vref = ± 1.28V 3: 6: NTC, 0…5V
|
||||
// b: ±0.15625 Vref = ± 0.64V 4: 6: Vprim/11, 0…5V
|
||||
// 5: 0…2.5 Vref = 0…10.24V 5: 6: 5V/2, 0…5V
|
||||
// 6: 0.1,25 Vref = 0… 5.12V 6: 2: I_bias, ±2.56V
|
||||
// 7: 0.625 Vref = 0… 2.56V 7: 5: Idrv, 0…10V
|
||||
// f: 0.3125 Vref = 0… 1.28V A: dac
|
||||
|
||||
#ifndef ADC_GAIN
|
||||
# define ADC_GAINS 0x5266651bUL
|
||||
# define ADC_GAINS 0x5266615bUL
|
||||
#endif
|
||||
|
||||
#define MAGIC 0xc05c
|
||||
#define VERSION 2
|
||||
#define VERSION 4
|
||||
|
||||
struct conf {
|
||||
unsigned int magic;
|
||||
unsigned char version;
|
||||
unsigned char flags;
|
||||
unsigned char flags2;
|
||||
unsigned int dac;
|
||||
unsigned int dac_nominal;
|
||||
unsigned int dac_off;
|
||||
unsigned int tick_period;
|
||||
unsigned char wdt_timeout;
|
||||
unsigned char wdt_mode;
|
||||
unsigned char wdt_save_addr;
|
||||
unsigned char avradc;
|
||||
unsigned int avrdac;
|
||||
unsigned int adcconf;
|
||||
unsigned long adcgain;
|
||||
unsigned char auxadc_n;
|
||||
unsigned char hvadc_ch;
|
||||
unsigned char hvadc_n;
|
||||
unsigned char safe;
|
||||
unsigned int hvadc_safe;
|
||||
unsigned char ddrc;
|
||||
unsigned char portc;
|
||||
unsigned char portc_on;
|
||||
unsigned char portc_off;
|
||||
unsigned char hvosc_freq;
|
||||
unsigned char hvosc_dc;
|
||||
unsigned char padding[3];
|
||||
} conf;
|
||||
unsigned int magic; // 0
|
||||
unsigned char version; // 2
|
||||
unsigned char flags; // 3
|
||||
unsigned char flags2; // 4
|
||||
unsigned int dac; // 5
|
||||
unsigned int dac_nominal; // 7
|
||||
unsigned int dac_off; // 9
|
||||
unsigned int tick_period; // 11
|
||||
unsigned char wdt_timeout; // 13
|
||||
unsigned char wdt_mode; // 14
|
||||
unsigned char wdt_toggle; // 15
|
||||
unsigned char avradc; // 16
|
||||
unsigned int avrdac; // 17
|
||||
unsigned int adcconf; // 19
|
||||
unsigned long adcgain; // 21
|
||||
unsigned char auxadc_n; // 25
|
||||
unsigned char hvadc_ch; // 26
|
||||
unsigned char hvadc_n; // 27
|
||||
unsigned char safe; // 28
|
||||
unsigned int hvadc_safe; // 29
|
||||
unsigned char ddrc; // 31
|
||||
unsigned char portc; // 32
|
||||
unsigned char portc_on; // 33
|
||||
unsigned char portc_off; // 34
|
||||
unsigned char hvosc_freq; // 35
|
||||
unsigned char hvosc_dc; // 36
|
||||
unsigned char inpdis; // 37
|
||||
unsigned char wdt_load; // 38
|
||||
unsigned char padding; // 39
|
||||
} conf; // 40
|
||||
|
||||
enum {
|
||||
FLAG_WDT = 1,
|
||||
|
|
@ -141,6 +152,7 @@ enum {
|
|||
FLAG2_PC_HV = 2,
|
||||
FLAG2_HVOSC = 4,
|
||||
FLAG2_HVLED = 8,
|
||||
FLAG2_INPDIS = 16,
|
||||
};
|
||||
|
||||
__attribute__((section(".eeprom")))
|
||||
|
|
@ -148,55 +160,64 @@ const struct conf runconf[] = {
|
|||
[0] = { // Default
|
||||
.magic = MAGIC,
|
||||
.version = VERSION,
|
||||
.flags = FLAG_RAMP | FLAG_ADCCONF | FLAG_DACADC,
|
||||
.flags2 = FLAG2_HVOSC | FLAG2_HVLED | FLAG2_INPDIS,
|
||||
.wdt_mode = 1,
|
||||
.wdt_timeout = 120, // 2 min
|
||||
.tick_period = TICK_NS(10000000L), // 10ms ramp
|
||||
.wdt_toggle = 8, // sec
|
||||
.tick_period = TICK_NS(1000000L), // 1ms ramp
|
||||
.avradc = 0x7f, // off
|
||||
.adcconf = 0x8500,// RST
|
||||
.ddrc = 2, // OC1B HVOSC
|
||||
.adcgain = ADC_GAINS,
|
||||
.auxadc_n = 4,
|
||||
.hvadc_ch = 1,
|
||||
.hvadc_n = 4,
|
||||
.hvadc_safe = 0x8100,
|
||||
.hvadc_ch = 2,
|
||||
.hvadc_n = 2,
|
||||
.hvadc_safe = 0,
|
||||
.inpdis = 0x3f,
|
||||
.wdt_load = 20,
|
||||
},
|
||||
[1] = { // ON
|
||||
.magic = MAGIC,
|
||||
.version = VERSION,
|
||||
.flags = FLAG_WDT | FLAG_RAMP | FLAG_ADCCONF | FLAG_DACADC,
|
||||
.flags2 = FLAG2_HVOSC | FLAG2_HVLED,
|
||||
.flags = FLAG_WDT | FLAG_ADCCONF | FLAG_DACADC,
|
||||
.flags2 = FLAG2_HVOSC | FLAG2_HVLED | FLAG2_INPDIS,
|
||||
.wdt_mode = 4,
|
||||
.wdt_timeout = 120, // 2 min
|
||||
.tick_period = TICK_NS(10000000L), // 10ms ramp
|
||||
.wdt_toggle = 8, // sec
|
||||
.tick_period = TICK_NS(1000000L), // 1ms ramp
|
||||
.avradc = 0x7f, // off
|
||||
.adcconf = 0x8500,// RST
|
||||
.adcgain = ADC_GAINS,
|
||||
.auxadc_n = 4,
|
||||
.hvadc_ch = 1,
|
||||
.hvadc_n = 4,
|
||||
.hvadc_safe = 0x8100,
|
||||
.hvadc_ch = 2,
|
||||
.hvadc_n = 2,
|
||||
.hvadc_safe = 0,
|
||||
.ddrc = 2, // OC1B HVOSC
|
||||
.hvosc_freq = 64,
|
||||
.hvosc_dc = 19,
|
||||
.dac_nominal = 100,
|
||||
.hvosc_freq = 55,
|
||||
.hvosc_dc = 14,
|
||||
.dac_off = 1000,
|
||||
.dac_nominal = 34832, // 700 V
|
||||
.inpdis = 0x3f,
|
||||
},
|
||||
[2] = { // SAFE
|
||||
.magic = MAGIC,
|
||||
.version = VERSION,
|
||||
.safe = 1,
|
||||
.flags = FLAG_WDT | FLAG_RAMP | FLAG_ADCCONF | FLAG_DACADC,
|
||||
.flags2 = FLAG2_HVOSC | FLAG2_HVLED,
|
||||
.flags = FLAG_WDT | FLAG_RAMP | FLAG_ADCCONF,
|
||||
.flags2 = FLAG2_HVOSC | FLAG2_HVLED | FLAG2_INPDIS,
|
||||
.wdt_timeout = 120, // 2 min
|
||||
.tick_period = TICK_NS(10000000L), // 10ms ramp
|
||||
.wdt_toggle = 8, // sec
|
||||
.tick_period = TICK_NS(1000000L), // 1ms ramp
|
||||
.avradc = 0x7f, // off
|
||||
.adcconf = 0x8500,// RST
|
||||
.adcgain = ADC_GAINS,
|
||||
.auxadc_n = 4,
|
||||
.hvadc_ch = 1,
|
||||
.hvadc_n = 4,
|
||||
.hvadc_safe = 0x8100,
|
||||
.hvadc_ch = 2,
|
||||
.hvadc_n = 2,
|
||||
.hvadc_safe = 683 + 0x8000, // 30V
|
||||
.ddrc = 2, // OC1B HVOSC
|
||||
.hvosc_freq = 0,
|
||||
.hvosc_dc = 0,
|
||||
.dac_nominal = 0,
|
||||
.inpdis = 0x3f,
|
||||
},
|
||||
};
|
||||
|
||||
|
|
@ -213,20 +234,23 @@ void conf_init()
|
|||
ads8688_config();
|
||||
if (conf.flags & FLAG_DACADC)
|
||||
conf.dac = read_auxadc(conf.auxadc_n);
|
||||
if (conf.flags & FLAG_RAMP)
|
||||
dac_ramp(conf.dac_nominal);
|
||||
if (conf.flags & FLAG_ADC)
|
||||
avradc_enable(conf.avradc);
|
||||
if (conf.flags & FLAG_DAC)
|
||||
avrdac_set(conf.avrdac);
|
||||
if (conf.flags2 & FLAG2_HVLED) {
|
||||
conf.ddrc |= LED_MASK;
|
||||
led_init();
|
||||
}
|
||||
if (conf.flags2 & FLAG2_PORTC) {
|
||||
PORTC = conf.portc;
|
||||
DDRC = conf.ddrc;
|
||||
}
|
||||
if (conf.flags2 & FLAG2_INPDIS) {
|
||||
DIDR0 = conf.inpdis << 5;
|
||||
DIDR1 = conf.inpdis >> 3;
|
||||
}
|
||||
if (conf.flags & FLAG_RAMP)
|
||||
dac_ramp(conf.dac_nominal);
|
||||
}
|
||||
|
||||
#include <avr/eeprom.h>
|
||||
|
|
@ -253,7 +277,8 @@ int hv_is_safe()
|
|||
{
|
||||
return !hvosc_is_on()
|
||||
&& conf.dac <= conf.dac_off
|
||||
&& adc_hv <= conf.hvadc_safe
|
||||
&& (!conf.hvadc_safe
|
||||
|| adc_hv <= conf.hvadc_safe)
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -267,6 +292,45 @@ void toggle_hv_led()
|
|||
}
|
||||
}
|
||||
|
||||
void hv_led_on()
|
||||
{
|
||||
if (conf.flags2 & FLAG2_HVLED) {
|
||||
if (hv_is_safe())
|
||||
led_on(LED_GREEN);
|
||||
else
|
||||
led_on(LED_RED);
|
||||
}
|
||||
}
|
||||
|
||||
char spi_was_busy;
|
||||
|
||||
static inline
|
||||
void spi_busy_init()
|
||||
{
|
||||
PCMSK2 |= 8; // PIND3 PCINT19
|
||||
while (!(PIND & 8));
|
||||
PCIFR = 4;
|
||||
}
|
||||
|
||||
static inline
|
||||
unsigned char spi_busy()
|
||||
{
|
||||
// Return true if the SSEL pin became low
|
||||
unsigned char f = PCIFR & 4;
|
||||
PCIFR = 4;
|
||||
spi_was_busy = f && !(PIND & 8);
|
||||
return spi_was_busy;
|
||||
}
|
||||
|
||||
static inline
|
||||
void clear_spi_busy()
|
||||
{
|
||||
const unsigned char *busy_msg = (const unsigned char *) "\xff\xff\xff" "EEY";
|
||||
if (spi_was_busy && !(PIND & 8))
|
||||
spi_slave_Tx(busy_msg, 6);
|
||||
spi_was_busy = 0;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void hv_safe()
|
||||
{
|
||||
|
|
@ -278,17 +342,33 @@ void hv_safe()
|
|||
ltc1655_cmd(INT2FRAME(conf.dac_off));
|
||||
conf.dac = conf.dac_off;
|
||||
unsigned int adc_last = 0xffff;
|
||||
while (!read_hvadc()) {
|
||||
if (adc_hv < conf.hvadc_safe || adc_hv >= adc_last)
|
||||
break;
|
||||
adc_last = adc_hv;
|
||||
unsigned int toggle = 0;
|
||||
if (conf.hvadc_safe) {
|
||||
spi_busy_init();
|
||||
while (!read_adc(conf.hvadc_ch, conf.hvadc_n)) {
|
||||
if (spi_busy())
|
||||
break;
|
||||
wdt_reset();
|
||||
if (adc_hv < conf.hvadc_safe || adc_hv >= adc_last)
|
||||
break;
|
||||
adc_last = adc_hv;
|
||||
toggle++;
|
||||
if (!toggle)
|
||||
toggle_hv_led();
|
||||
}
|
||||
}
|
||||
enable_irq(sreg);
|
||||
toggle_hv_led();
|
||||
hv_led_on();
|
||||
}
|
||||
|
||||
unsigned char wdt_killed_us;
|
||||
|
||||
int main()
|
||||
{
|
||||
wdt_killed_us = MCUSR;
|
||||
MCUSR = 0;
|
||||
wdt_init(0);
|
||||
|
||||
// turn of unused IO modules
|
||||
PRR = (1<<PRPSC)|(1<<PRCAN)|(1<<PRTIM1)|(1<<PRLIN)|(1<<PRADC);
|
||||
|
||||
|
|
@ -296,20 +376,33 @@ int main()
|
|||
DDRB |= (1<<PB0); // make MISO an output
|
||||
ads8688_init();
|
||||
ltc1655_init();
|
||||
hv_safe();
|
||||
eeprom_load(0);
|
||||
if (conf.magic == MAGIC && conf.version == VERSION)
|
||||
|
||||
if (conf.wdt_load
|
||||
&& wdt_killed_us & (1<<WDRF)
|
||||
&& conf.magic == MAGIC
|
||||
&& conf.version == VERSION)
|
||||
eeprom_load(conf.wdt_load);
|
||||
if (conf.magic == MAGIC && conf.version == VERSION) {
|
||||
conf_init();
|
||||
if (conf.safe)
|
||||
hv_safe();
|
||||
}
|
||||
while (1) {
|
||||
sei();
|
||||
clear_spi_busy();
|
||||
unsigned char cmd[3];
|
||||
unsigned char resp[3];
|
||||
unsigned char c;
|
||||
unsigned char sreg;
|
||||
const char *p;
|
||||
spi_slave_Rx(cmd, 3);
|
||||
if (spi_slave_Rx_wdt(cmd, 3)) {
|
||||
const unsigned char *wdt_msg =
|
||||
(const unsigned char *) "\xff\xff\xff" "EEW";
|
||||
spi_slave_Tx(wdt_msg, 6);
|
||||
continue;
|
||||
}
|
||||
cli();
|
||||
resp[0] = cmd[0];
|
||||
toggle_hv_led();
|
||||
sreg = disable_irq();
|
||||
if (conf.wdt_mode == WDT_MODE_LIVE)
|
||||
wdt_kick();
|
||||
switch (cmd[0]) {
|
||||
|
|
@ -328,15 +421,11 @@ int main()
|
|||
int2frame(conf.dac_nominal, resp+1);
|
||||
conf.dac_nominal = frame2int(cmd+1);
|
||||
break;
|
||||
case 'w':
|
||||
int2frame(conf.dac_off, resp+1);
|
||||
conf.dac_off = frame2int(cmd+1);
|
||||
break;
|
||||
case 'H':
|
||||
int2frame(conf.dac, resp+1);
|
||||
if (conf.wdt_mode >= WDT_MODE_HV)
|
||||
wdt_kick();
|
||||
enable_irq(sreg);
|
||||
sei();
|
||||
spi_slave_Tx(resp, 3);
|
||||
dac_ramp(frame2int(cmd+1));
|
||||
continue;
|
||||
|
|
@ -348,7 +437,7 @@ int main()
|
|||
int2frame(conf.dac, resp+1);
|
||||
if (conf.wdt_mode >= WDT_MODE_HV)
|
||||
wdt_kick();
|
||||
enable_irq(sreg);
|
||||
sei();
|
||||
spi_slave_Tx(resp, 3);
|
||||
dac_ramp(conf.dac_nominal);
|
||||
continue;
|
||||
|
|
@ -361,6 +450,7 @@ int main()
|
|||
conf.hvosc_dc = cmd[2];
|
||||
}
|
||||
hvosc_init(conf.hvosc_freq, conf.hvosc_dc);
|
||||
hv_led_on();
|
||||
conf.safe = 0;
|
||||
break;
|
||||
case 'I':
|
||||
|
|
@ -378,7 +468,7 @@ int main()
|
|||
case 't':
|
||||
resp[1] = adc_status;
|
||||
resp[2] = adc_error;
|
||||
enable_irq(sreg);
|
||||
sei();
|
||||
spi_slave_Tx(resp, 3);
|
||||
if (cmd[1]) {
|
||||
if (upcase(cmd[0])) {
|
||||
|
|
@ -395,20 +485,17 @@ int main()
|
|||
if (c>8)
|
||||
c = 8;
|
||||
switch (cmd[2]) {
|
||||
case 1: int2frame(adc_sum[c], resp+1); break;
|
||||
case 2: resp[1] = adc_sum[c] >> 16; resp[2] = adc_n[c]; break;
|
||||
case 1: int2frame(adc_sum[c] >> 8, resp+1); break;
|
||||
case 2: resp[1] = adc_sum[c]; resp[2] = adc_n[c]; break;
|
||||
case 3: int2frame(adc_noise[c], resp+1); break;
|
||||
default: resp[1] = adc_status; resp[2] = adc_error; break;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
if (adc_error) {
|
||||
resp[0] = 'E';
|
||||
resp[1] = 'r';
|
||||
resp[2] = adc_error;
|
||||
break;
|
||||
}
|
||||
int2frame(adc_aux, resp+1);
|
||||
if (cmd[1])
|
||||
int2frame(adc_hv, resp+1);
|
||||
else
|
||||
int2frame(adc_aux, resp+1);
|
||||
break;
|
||||
case 'V':
|
||||
p = revision;
|
||||
|
|
@ -420,18 +507,26 @@ int main()
|
|||
resp[1] = *p;
|
||||
resp[2] = cmd[1]-c;
|
||||
break;
|
||||
case 'w':
|
||||
resp[1] = conf.wdt_mode;
|
||||
resp[2] = wdt_count;
|
||||
sei();
|
||||
spi_slave_Tx(resp, 3);
|
||||
hv_safe();
|
||||
break;
|
||||
case 'W':
|
||||
if (cmd[1]==0xff && cmd[2]==0xd1)
|
||||
die();
|
||||
resp[1] = conf.wdt_mode;
|
||||
resp[2] = conf.wdt_timeout;
|
||||
if (cmd[2])
|
||||
conf.wdt_timeout = cmd[2];
|
||||
if (cmd[1]) {
|
||||
if (cmd[1])
|
||||
wdt_init(cmd[1]);
|
||||
sreg = (1<<SREG_I);
|
||||
}
|
||||
else {
|
||||
resp[2] = wdt_count;
|
||||
wdt_kick();
|
||||
toggle_hv_led();
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
|
|
@ -449,7 +544,7 @@ int main()
|
|||
case 'S':
|
||||
resp[1] = cmd[1];
|
||||
resp[2] = sizeof(conf);
|
||||
enable_irq(sreg);
|
||||
sei();
|
||||
spi_slave_Tx(resp, 3);
|
||||
eeprom_save(cmd[1]);
|
||||
continue;
|
||||
|
|
@ -465,7 +560,7 @@ int main()
|
|||
break;
|
||||
}
|
||||
if (cmd[1] && upcase(cmd[1])) {
|
||||
enable_irq(sreg);
|
||||
sei();
|
||||
spi_slave_Tx(resp, 3);
|
||||
conf_init();
|
||||
continue;
|
||||
|
|
@ -533,8 +628,20 @@ int main()
|
|||
if (!upcase(cmd[0]))
|
||||
*(unsigned char *)(cmd[1]+0) = cmd[2];
|
||||
break;
|
||||
case 'Z':
|
||||
case 'z':
|
||||
resp[1] = cmd[1];
|
||||
switch (cmd[1]) {
|
||||
case 0: resp[2] = wdt_killed_us; break;
|
||||
}
|
||||
if (upcase(cmd[0]))
|
||||
break;
|
||||
switch (cmd[1]) {
|
||||
case 0: wdt_killed_us = cmd[2]; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
enable_irq(sreg);
|
||||
sei();
|
||||
spi_slave_Tx(resp, 3);
|
||||
}
|
||||
}
|
||||
|
|
@ -555,8 +662,13 @@ void ads8688_config()
|
|||
}, r);
|
||||
}
|
||||
|
||||
volatile unsigned char adc_lock;
|
||||
|
||||
unsigned char read_adc(unsigned char c, unsigned char n)
|
||||
{
|
||||
unsigned char e = 0;
|
||||
if (n>8)
|
||||
n=8;
|
||||
unsigned char nn = (1<<n) - 1;
|
||||
unsigned char cc;
|
||||
if (c >= 8) {
|
||||
|
|
@ -566,42 +678,58 @@ unsigned char read_adc(unsigned char c, unsigned char n)
|
|||
else
|
||||
cc = 1<<c;
|
||||
|
||||
spi_int_init();
|
||||
unsigned char cmd[2] = {0, 0xc0 | (c << 2)};
|
||||
unsigned char resp[2];
|
||||
unsigned char i;
|
||||
adc_lock = 1;
|
||||
unsigned char sreg = disable_irq();
|
||||
for (i=0; i<3; i++)
|
||||
ads8688_cmd(cmd, resp);
|
||||
enable_irq(sreg);
|
||||
unsigned int s0 = frame2int(resp);
|
||||
unsigned long s = s0;
|
||||
int r = 0;
|
||||
unsigned long q = 0;
|
||||
spi_busy_init();
|
||||
for (i=0; i<nn; i++) {
|
||||
if (spi_int())
|
||||
return adc_error |= cc;
|
||||
unsigned char sreg = disable_irq();
|
||||
if (spi_busy()) {
|
||||
e = adc_error |= cc;
|
||||
goto out;
|
||||
}
|
||||
sreg = disable_irq();
|
||||
ads8688_cmd(cmd, resp);
|
||||
enable_irq(sreg);
|
||||
unsigned int s1 = frame2int(resp);
|
||||
s += s1;
|
||||
char d = s1 - s0;
|
||||
int dd = s1 - s0;
|
||||
if (dd > 127)
|
||||
dd = 127;
|
||||
if (dd < -127)
|
||||
dd = -127;
|
||||
signed char d = dd;
|
||||
r += d;
|
||||
q += d * d;
|
||||
}
|
||||
unsigned long rr = (long)r*r;
|
||||
unsigned long qq = (nn+1)*q;
|
||||
unsigned long chi2 = qq-rr;
|
||||
adc_sum[c] = s;
|
||||
adc_noise[c] = chi2 >> n;
|
||||
unsigned long qq = q << n;
|
||||
unsigned long chi2 = qq - rr;
|
||||
adc_sum[c] = s << (8-n);
|
||||
chi2 >>= 2*n - 1;
|
||||
chi2 += 1;
|
||||
chi2 >>= 1;
|
||||
adc_noise[c] = chi2;
|
||||
adc_n[c] = n;
|
||||
adc_status |= cc;
|
||||
return 0;
|
||||
if (c == conf.hvadc_ch)
|
||||
adc_hv = adc_sum[c] >> 8;
|
||||
out:
|
||||
adc_lock = 0;
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
void adc_read(unsigned char chs, unsigned char n)
|
||||
{
|
||||
spi_int_init();
|
||||
adc_status = 0;
|
||||
adc_error = 0;
|
||||
unsigned char c;
|
||||
|
|
@ -610,34 +738,24 @@ void adc_read(unsigned char chs, unsigned char n)
|
|||
continue;
|
||||
if (read_adc(c, n))
|
||||
return;
|
||||
if (c==conf.hvadc_ch)
|
||||
adc_hv = adc_sum[c] >> n;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int read_hvadc()
|
||||
{
|
||||
unsigned char n = conf.hvadc_n;
|
||||
unsigned char c = conf.hvadc_ch;
|
||||
if (!read_adc(c, n))
|
||||
adc_hv = adc_sum[c] >> n;
|
||||
return adc_hv;
|
||||
}
|
||||
|
||||
unsigned int read_auxadc()
|
||||
{
|
||||
unsigned char n = conf.auxadc_n;
|
||||
if (!read_adc(8, n))
|
||||
adc_aux = adc_sum[8] >> n;
|
||||
adc_aux = adc_sum[8] >> 8;
|
||||
return adc_aux;
|
||||
}
|
||||
|
||||
void dac_ramp(unsigned int target)
|
||||
{
|
||||
conf.safe = 0;
|
||||
spi_int_init();
|
||||
unsigned char toggle = 0;
|
||||
spi_busy_init();
|
||||
while (conf.dac != target) {
|
||||
if (spi_int())
|
||||
if (spi_busy())
|
||||
return;
|
||||
if (!tick(TICKO))
|
||||
continue;
|
||||
|
|
@ -649,24 +767,36 @@ void dac_ramp(unsigned int target)
|
|||
conf.dac = target;
|
||||
ltc1655_cmd(INT2FRAME(conf.dac));
|
||||
enable_irq(sreg);
|
||||
toggle++;
|
||||
if (!toggle)
|
||||
toggle_hv_led();
|
||||
}
|
||||
hv_led_on();
|
||||
}
|
||||
|
||||
ISR(WDT_vect)
|
||||
{
|
||||
if (conf.safe && !hv_is_safe())
|
||||
read_hvadc();
|
||||
toggle_hv_led();
|
||||
if (wdt_count++ < conf.wdt_timeout)
|
||||
goto wdt_out;
|
||||
hv_safe();
|
||||
wdt_reset();
|
||||
if (conf.wdt_save_addr && !wdt_saved) {
|
||||
wdt_saved = 1;
|
||||
eeprom_save(conf.wdt_save_addr);
|
||||
wdt_count++;
|
||||
if (wdt_count >= conf.wdt_toggle) {
|
||||
if (conf.safe && conf.hvadc_safe && !adc_lock) {
|
||||
adc_hv = 0;
|
||||
read_adc(conf.hvadc_ch, conf.hvadc_n);
|
||||
}
|
||||
toggle_hv_led();
|
||||
}
|
||||
if (wdt_count < conf.wdt_timeout)
|
||||
goto wdt_out;
|
||||
wdt_count = 0;
|
||||
hv_safe();
|
||||
wdt_out:
|
||||
WDTCSR |= WDIE;
|
||||
__asm__("STS %[CSR], %[CE]" "\n\t"
|
||||
"STS %[CSR], %[IE]" "\n"
|
||||
::[CSR] "n" (&WDTCSR),
|
||||
[CE] "r" ((unsigned char)(1<<WDCE | 1<<WDE | 1<<WDP2 | 1<<WDP1)),
|
||||
[IE] "r" ((unsigned char)(1<<WDIE | 1<<WDE | 1<<WDP2 | 1<<WDP1))
|
||||
);
|
||||
wdt_tick = 1;
|
||||
}
|
||||
|
||||
void wdt_init(unsigned char mode)
|
||||
|
|
@ -674,7 +804,12 @@ void wdt_init(unsigned char mode)
|
|||
conf.wdt_mode = mode;
|
||||
wdt_reset();
|
||||
if (mode < WDT_MODE_LIVE) {
|
||||
WDTCSR = 0;
|
||||
__asm__("STS %[CSR], %[CE]" "\n\t"
|
||||
"STS %[CSR], %[IE]" "\n"
|
||||
::[CSR] "n" (&WDTCSR),
|
||||
[CE] "r" ((unsigned char)(1<<WDCE | 1<<WDIE | 1<<WDE | 1<<WDP2 | 1<<WDP1)),
|
||||
[IE] "r" ((unsigned char)(1<<WDP2 | 1<<WDP1))
|
||||
);
|
||||
return;
|
||||
}
|
||||
// 1s timeout, WDT interrupt enabled
|
||||
|
|
@ -713,10 +848,4 @@ void avradc_enable(unsigned char c)
|
|||
if (!(c&0x80))
|
||||
ADCSRA |= 1<<ADEN;
|
||||
ADCSRA |= 1<<ADSC;
|
||||
if (cc==4)
|
||||
; // SPI SCK
|
||||
else if (cc<8)
|
||||
DIDR0 = 1<<cc;
|
||||
else if (cc<11)
|
||||
DIDR1 = 1<<(cc&3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,15 @@
|
|||
|
||||
static inline void hvosc_init(unsigned char freq, unsigned char dc)
|
||||
{
|
||||
PORTC &=~ (1<<PC1);
|
||||
PORTD &=~ (1<<PD2);
|
||||
DDRC |= (1<<PC1);
|
||||
DDRD |= (1<<PD2);
|
||||
if (!dc || freq <= dc) {
|
||||
TCCR1A = 0;
|
||||
return;
|
||||
}
|
||||
PRR &=~ (1<<PRTIM1);
|
||||
DDRC |= (1<<PC1);
|
||||
DDRD |= (1<<PD2);
|
||||
TCCR1A = (2<<COM1A0) | (3<<COM1B0) | (2<<WGM10);
|
||||
TCCR1B = (1<<CS10) | (2<<WGM12);
|
||||
ICR1H = 0;
|
||||
|
|
|
|||
37
spi_slave.h
37
spi_slave.h
|
|
@ -32,7 +32,28 @@ static inline void spi_slave_Rx(unsigned char d[], unsigned char n)
|
|||
}
|
||||
}
|
||||
|
||||
static inline void spi_slave_Tx(unsigned char d[], unsigned char n)
|
||||
extern volatile unsigned char wdt_tick;
|
||||
static inline char spi_slave_Rx_wdt(unsigned char d[], unsigned char n)
|
||||
{
|
||||
SPSR;
|
||||
SPDR;
|
||||
register unsigned char b;
|
||||
do {
|
||||
while (!(SPSR & SPSR_IF));
|
||||
wdt_tick = 0;
|
||||
SPDR = 0xff;
|
||||
b = SPDR;
|
||||
} while (b&0x80);
|
||||
*d++ = b;
|
||||
while (--n) {
|
||||
while (!(SPSR & SPSR_IF));
|
||||
SPDR = 0xff;
|
||||
*d++ = SPDR;
|
||||
}
|
||||
return wdt_tick;
|
||||
}
|
||||
|
||||
static inline void spi_slave_Tx(const unsigned char d[], unsigned char n)
|
||||
{
|
||||
SPSR;
|
||||
SPDR;
|
||||
|
|
@ -55,17 +76,3 @@ static inline unsigned int frame2int(unsigned char *f)
|
|||
}
|
||||
#define INT2FRAME(i) ((unsigned char []){i, i>>8})
|
||||
|
||||
#ifdef PIN_SSEL
|
||||
|
||||
static inline unsigned int spi_int()
|
||||
{
|
||||
// Return true if the SSEL pin is low
|
||||
return !PIN_SSEL;
|
||||
}
|
||||
|
||||
static inline void spi_int_init()
|
||||
{
|
||||
while (spi_int());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue