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$";
|
"$Id$";
|
||||||
|
|
||||||
#define PIN_SSEL (PIND & (1<<PD3))
|
|
||||||
#include "spi_slave.h"
|
#include "spi_slave.h"
|
||||||
|
|
||||||
#include "ads8688.h"
|
#include "ads8688.h"
|
||||||
|
|
@ -16,7 +15,6 @@ const char *revision =
|
||||||
unsigned char read_adc(unsigned char c, unsigned char n);
|
unsigned char read_adc(unsigned char c, unsigned char n);
|
||||||
void adc_read(unsigned char chs, unsigned char n);
|
void adc_read(unsigned char chs, unsigned char n);
|
||||||
unsigned int read_auxadc();
|
unsigned int read_auxadc();
|
||||||
unsigned int read_hvadc();
|
|
||||||
void dac_ramp(unsigned int target);
|
void dac_ramp(unsigned int target);
|
||||||
void ads8688_cmd(const unsigned char *c, unsigned char *r);
|
void ads8688_cmd(const unsigned char *c, unsigned char *r);
|
||||||
void ltc1655_cmd(const unsigned char *c);
|
void ltc1655_cmd(const unsigned char *c);
|
||||||
|
|
@ -27,6 +25,17 @@ void ads8688_config();
|
||||||
#include "hvosc.h"
|
#include "hvosc.h"
|
||||||
|
|
||||||
#include <avr/interrupt.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()
|
static inline unsigned char disable_irq()
|
||||||
{
|
{
|
||||||
|
|
@ -66,7 +75,7 @@ static inline void avrdac_set(unsigned int d)
|
||||||
#include <avr/wdt.h>
|
#include <avr/wdt.h>
|
||||||
void wdt_init(unsigned char mode);
|
void wdt_init(unsigned char mode);
|
||||||
unsigned char wdt_count;
|
unsigned char wdt_count;
|
||||||
unsigned char wdt_saved;
|
volatile unsigned char wdt_tick;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
WDT_MODE_LIVE = 2, // = any command kick
|
WDT_MODE_LIVE = 2, // = any command kick
|
||||||
|
|
@ -82,52 +91,54 @@ static inline void wdt_kick()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADS8688 gains Channels:
|
// ADS8688 gains Channels:
|
||||||
// 0: ±2.5 Vref = ± 10.24V 0: Iprim, 0.5V/A, ± 0.64V
|
// 0: ±2.5 Vref = ± 10.24V 0: b: Iprim, 0.5V/A, ± 0.64V
|
||||||
// 1: ±1.25 Vref = ± 5.12V 1: HV Mon, ±5V
|
// 1: ±1.25 Vref = ± 5.12V 1: 5: Vdrv, 0…10V
|
||||||
// 2: ±0.625 Vref = ± 2.56V 2: Vdrv, 0…10V
|
// 2: ±0.625 Vref = ± 2.56V 2: 1: HV Mon, ±5V
|
||||||
// 3: ±0.3125 Vref = ± 1.28V 3: NTC, 0…5V
|
// 3: ±0.3125 Vref = ± 1.28V 3: 6: NTC, 0…5V
|
||||||
// b: ±0.15625 Vref = ± 0.64V 4: Vprim/11, 0…5V
|
// b: ±0.15625 Vref = ± 0.64V 4: 6: Vprim/11, 0…5V
|
||||||
// 5: 0…2.5 Vref = 0…10.24V 5: 5V/2, 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: I_bias, ±2.56V
|
// 6: 0.1,25 Vref = 0… 5.12V 6: 2: I_bias, ±2.56V
|
||||||
// 7: 0.625 Vref = 0… 2.56V 7: Idrv, 0…10V
|
// 7: 0.625 Vref = 0… 2.56V 7: 5: Idrv, 0…10V
|
||||||
// f: 0.3125 Vref = 0… 1.28V A: dac
|
// f: 0.3125 Vref = 0… 1.28V A: dac
|
||||||
|
|
||||||
#ifndef ADC_GAIN
|
#ifndef ADC_GAIN
|
||||||
# define ADC_GAINS 0x5266651bUL
|
# define ADC_GAINS 0x5266615bUL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MAGIC 0xc05c
|
#define MAGIC 0xc05c
|
||||||
#define VERSION 2
|
#define VERSION 4
|
||||||
|
|
||||||
struct conf {
|
struct conf {
|
||||||
unsigned int magic;
|
unsigned int magic; // 0
|
||||||
unsigned char version;
|
unsigned char version; // 2
|
||||||
unsigned char flags;
|
unsigned char flags; // 3
|
||||||
unsigned char flags2;
|
unsigned char flags2; // 4
|
||||||
unsigned int dac;
|
unsigned int dac; // 5
|
||||||
unsigned int dac_nominal;
|
unsigned int dac_nominal; // 7
|
||||||
unsigned int dac_off;
|
unsigned int dac_off; // 9
|
||||||
unsigned int tick_period;
|
unsigned int tick_period; // 11
|
||||||
unsigned char wdt_timeout;
|
unsigned char wdt_timeout; // 13
|
||||||
unsigned char wdt_mode;
|
unsigned char wdt_mode; // 14
|
||||||
unsigned char wdt_save_addr;
|
unsigned char wdt_toggle; // 15
|
||||||
unsigned char avradc;
|
unsigned char avradc; // 16
|
||||||
unsigned int avrdac;
|
unsigned int avrdac; // 17
|
||||||
unsigned int adcconf;
|
unsigned int adcconf; // 19
|
||||||
unsigned long adcgain;
|
unsigned long adcgain; // 21
|
||||||
unsigned char auxadc_n;
|
unsigned char auxadc_n; // 25
|
||||||
unsigned char hvadc_ch;
|
unsigned char hvadc_ch; // 26
|
||||||
unsigned char hvadc_n;
|
unsigned char hvadc_n; // 27
|
||||||
unsigned char safe;
|
unsigned char safe; // 28
|
||||||
unsigned int hvadc_safe;
|
unsigned int hvadc_safe; // 29
|
||||||
unsigned char ddrc;
|
unsigned char ddrc; // 31
|
||||||
unsigned char portc;
|
unsigned char portc; // 32
|
||||||
unsigned char portc_on;
|
unsigned char portc_on; // 33
|
||||||
unsigned char portc_off;
|
unsigned char portc_off; // 34
|
||||||
unsigned char hvosc_freq;
|
unsigned char hvosc_freq; // 35
|
||||||
unsigned char hvosc_dc;
|
unsigned char hvosc_dc; // 36
|
||||||
unsigned char padding[3];
|
unsigned char inpdis; // 37
|
||||||
} conf;
|
unsigned char wdt_load; // 38
|
||||||
|
unsigned char padding; // 39
|
||||||
|
} conf; // 40
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
FLAG_WDT = 1,
|
FLAG_WDT = 1,
|
||||||
|
|
@ -141,6 +152,7 @@ enum {
|
||||||
FLAG2_PC_HV = 2,
|
FLAG2_PC_HV = 2,
|
||||||
FLAG2_HVOSC = 4,
|
FLAG2_HVOSC = 4,
|
||||||
FLAG2_HVLED = 8,
|
FLAG2_HVLED = 8,
|
||||||
|
FLAG2_INPDIS = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
__attribute__((section(".eeprom")))
|
__attribute__((section(".eeprom")))
|
||||||
|
|
@ -148,55 +160,64 @@ const struct conf runconf[] = {
|
||||||
[0] = { // Default
|
[0] = { // Default
|
||||||
.magic = MAGIC,
|
.magic = MAGIC,
|
||||||
.version = VERSION,
|
.version = VERSION,
|
||||||
|
.flags = FLAG_RAMP | FLAG_ADCCONF | FLAG_DACADC,
|
||||||
|
.flags2 = FLAG2_HVOSC | FLAG2_HVLED | FLAG2_INPDIS,
|
||||||
|
.wdt_mode = 1,
|
||||||
.wdt_timeout = 120, // 2 min
|
.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
|
.avradc = 0x7f, // off
|
||||||
.adcconf = 0x8500,// RST
|
.adcconf = 0x8500,// RST
|
||||||
.ddrc = 2, // OC1B HVOSC
|
.ddrc = 2, // OC1B HVOSC
|
||||||
.adcgain = ADC_GAINS,
|
.adcgain = ADC_GAINS,
|
||||||
.auxadc_n = 4,
|
.auxadc_n = 4,
|
||||||
.hvadc_ch = 1,
|
.hvadc_ch = 2,
|
||||||
.hvadc_n = 4,
|
.hvadc_n = 2,
|
||||||
.hvadc_safe = 0x8100,
|
.hvadc_safe = 0,
|
||||||
|
.inpdis = 0x3f,
|
||||||
|
.wdt_load = 20,
|
||||||
},
|
},
|
||||||
[1] = { // ON
|
[1] = { // ON
|
||||||
.magic = MAGIC,
|
.magic = MAGIC,
|
||||||
.version = VERSION,
|
.version = VERSION,
|
||||||
.flags = FLAG_WDT | FLAG_RAMP | FLAG_ADCCONF | FLAG_DACADC,
|
.flags = FLAG_WDT | FLAG_ADCCONF | FLAG_DACADC,
|
||||||
.flags2 = FLAG2_HVOSC | FLAG2_HVLED,
|
.flags2 = FLAG2_HVOSC | FLAG2_HVLED | FLAG2_INPDIS,
|
||||||
|
.wdt_mode = 4,
|
||||||
.wdt_timeout = 120, // 2 min
|
.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
|
.avradc = 0x7f, // off
|
||||||
.adcconf = 0x8500,// RST
|
.adcconf = 0x8500,// RST
|
||||||
.adcgain = ADC_GAINS,
|
.adcgain = ADC_GAINS,
|
||||||
.auxadc_n = 4,
|
.auxadc_n = 4,
|
||||||
.hvadc_ch = 1,
|
.hvadc_ch = 2,
|
||||||
.hvadc_n = 4,
|
.hvadc_n = 2,
|
||||||
.hvadc_safe = 0x8100,
|
.hvadc_safe = 0,
|
||||||
.ddrc = 2, // OC1B HVOSC
|
.ddrc = 2, // OC1B HVOSC
|
||||||
.hvosc_freq = 64,
|
.hvosc_freq = 55,
|
||||||
.hvosc_dc = 19,
|
.hvosc_dc = 14,
|
||||||
.dac_nominal = 100,
|
.dac_off = 1000,
|
||||||
|
.dac_nominal = 34832, // 700 V
|
||||||
|
.inpdis = 0x3f,
|
||||||
},
|
},
|
||||||
[2] = { // SAFE
|
[2] = { // SAFE
|
||||||
.magic = MAGIC,
|
.magic = MAGIC,
|
||||||
.version = VERSION,
|
.version = VERSION,
|
||||||
.safe = 1,
|
.safe = 1,
|
||||||
.flags = FLAG_WDT | FLAG_RAMP | FLAG_ADCCONF | FLAG_DACADC,
|
.flags = FLAG_WDT | FLAG_RAMP | FLAG_ADCCONF,
|
||||||
.flags2 = FLAG2_HVOSC | FLAG2_HVLED,
|
.flags2 = FLAG2_HVOSC | FLAG2_HVLED | FLAG2_INPDIS,
|
||||||
.wdt_timeout = 120, // 2 min
|
.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
|
.avradc = 0x7f, // off
|
||||||
.adcconf = 0x8500,// RST
|
.adcconf = 0x8500,// RST
|
||||||
.adcgain = ADC_GAINS,
|
.adcgain = ADC_GAINS,
|
||||||
.auxadc_n = 4,
|
.auxadc_n = 4,
|
||||||
.hvadc_ch = 1,
|
.hvadc_ch = 2,
|
||||||
.hvadc_n = 4,
|
.hvadc_n = 2,
|
||||||
.hvadc_safe = 0x8100,
|
.hvadc_safe = 683 + 0x8000, // 30V
|
||||||
.ddrc = 2, // OC1B HVOSC
|
.ddrc = 2, // OC1B HVOSC
|
||||||
.hvosc_freq = 0,
|
.inpdis = 0x3f,
|
||||||
.hvosc_dc = 0,
|
|
||||||
.dac_nominal = 0,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -213,20 +234,23 @@ void conf_init()
|
||||||
ads8688_config();
|
ads8688_config();
|
||||||
if (conf.flags & FLAG_DACADC)
|
if (conf.flags & FLAG_DACADC)
|
||||||
conf.dac = read_auxadc(conf.auxadc_n);
|
conf.dac = read_auxadc(conf.auxadc_n);
|
||||||
if (conf.flags & FLAG_RAMP)
|
|
||||||
dac_ramp(conf.dac_nominal);
|
|
||||||
if (conf.flags & FLAG_ADC)
|
if (conf.flags & FLAG_ADC)
|
||||||
avradc_enable(conf.avradc);
|
avradc_enable(conf.avradc);
|
||||||
if (conf.flags & FLAG_DAC)
|
if (conf.flags & FLAG_DAC)
|
||||||
avrdac_set(conf.avrdac);
|
avrdac_set(conf.avrdac);
|
||||||
if (conf.flags2 & FLAG2_HVLED) {
|
if (conf.flags2 & FLAG2_HVLED) {
|
||||||
conf.ddrc |= LED_MASK;
|
|
||||||
led_init();
|
led_init();
|
||||||
}
|
}
|
||||||
if (conf.flags2 & FLAG2_PORTC) {
|
if (conf.flags2 & FLAG2_PORTC) {
|
||||||
PORTC = conf.portc;
|
PORTC = conf.portc;
|
||||||
DDRC = conf.ddrc;
|
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>
|
#include <avr/eeprom.h>
|
||||||
|
|
@ -253,7 +277,8 @@ int hv_is_safe()
|
||||||
{
|
{
|
||||||
return !hvosc_is_on()
|
return !hvosc_is_on()
|
||||||
&& conf.dac <= conf.dac_off
|
&& 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))
|
__attribute__((noinline))
|
||||||
void hv_safe()
|
void hv_safe()
|
||||||
{
|
{
|
||||||
|
|
@ -278,17 +342,33 @@ void hv_safe()
|
||||||
ltc1655_cmd(INT2FRAME(conf.dac_off));
|
ltc1655_cmd(INT2FRAME(conf.dac_off));
|
||||||
conf.dac = conf.dac_off;
|
conf.dac = conf.dac_off;
|
||||||
unsigned int adc_last = 0xffff;
|
unsigned int adc_last = 0xffff;
|
||||||
while (!read_hvadc()) {
|
unsigned int toggle = 0;
|
||||||
if (adc_hv < conf.hvadc_safe || adc_hv >= adc_last)
|
if (conf.hvadc_safe) {
|
||||||
break;
|
spi_busy_init();
|
||||||
adc_last = adc_hv;
|
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);
|
enable_irq(sreg);
|
||||||
toggle_hv_led();
|
hv_led_on();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned char wdt_killed_us;
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
|
wdt_killed_us = MCUSR;
|
||||||
|
MCUSR = 0;
|
||||||
|
wdt_init(0);
|
||||||
|
|
||||||
// turn of unused IO modules
|
// turn of unused IO modules
|
||||||
PRR = (1<<PRPSC)|(1<<PRCAN)|(1<<PRTIM1)|(1<<PRLIN)|(1<<PRADC);
|
PRR = (1<<PRPSC)|(1<<PRCAN)|(1<<PRTIM1)|(1<<PRLIN)|(1<<PRADC);
|
||||||
|
|
||||||
|
|
@ -296,20 +376,33 @@ int main()
|
||||||
DDRB |= (1<<PB0); // make MISO an output
|
DDRB |= (1<<PB0); // make MISO an output
|
||||||
ads8688_init();
|
ads8688_init();
|
||||||
ltc1655_init();
|
ltc1655_init();
|
||||||
hv_safe();
|
|
||||||
eeprom_load(0);
|
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();
|
conf_init();
|
||||||
|
if (conf.safe)
|
||||||
|
hv_safe();
|
||||||
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
|
sei();
|
||||||
|
clear_spi_busy();
|
||||||
unsigned char cmd[3];
|
unsigned char cmd[3];
|
||||||
unsigned char resp[3];
|
unsigned char resp[3];
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
unsigned char sreg;
|
|
||||||
const char *p;
|
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];
|
resp[0] = cmd[0];
|
||||||
toggle_hv_led();
|
|
||||||
sreg = disable_irq();
|
|
||||||
if (conf.wdt_mode == WDT_MODE_LIVE)
|
if (conf.wdt_mode == WDT_MODE_LIVE)
|
||||||
wdt_kick();
|
wdt_kick();
|
||||||
switch (cmd[0]) {
|
switch (cmd[0]) {
|
||||||
|
|
@ -328,15 +421,11 @@ int main()
|
||||||
int2frame(conf.dac_nominal, resp+1);
|
int2frame(conf.dac_nominal, resp+1);
|
||||||
conf.dac_nominal = frame2int(cmd+1);
|
conf.dac_nominal = frame2int(cmd+1);
|
||||||
break;
|
break;
|
||||||
case 'w':
|
|
||||||
int2frame(conf.dac_off, resp+1);
|
|
||||||
conf.dac_off = frame2int(cmd+1);
|
|
||||||
break;
|
|
||||||
case 'H':
|
case 'H':
|
||||||
int2frame(conf.dac, resp+1);
|
int2frame(conf.dac, resp+1);
|
||||||
if (conf.wdt_mode >= WDT_MODE_HV)
|
if (conf.wdt_mode >= WDT_MODE_HV)
|
||||||
wdt_kick();
|
wdt_kick();
|
||||||
enable_irq(sreg);
|
sei();
|
||||||
spi_slave_Tx(resp, 3);
|
spi_slave_Tx(resp, 3);
|
||||||
dac_ramp(frame2int(cmd+1));
|
dac_ramp(frame2int(cmd+1));
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -348,7 +437,7 @@ int main()
|
||||||
int2frame(conf.dac, resp+1);
|
int2frame(conf.dac, resp+1);
|
||||||
if (conf.wdt_mode >= WDT_MODE_HV)
|
if (conf.wdt_mode >= WDT_MODE_HV)
|
||||||
wdt_kick();
|
wdt_kick();
|
||||||
enable_irq(sreg);
|
sei();
|
||||||
spi_slave_Tx(resp, 3);
|
spi_slave_Tx(resp, 3);
|
||||||
dac_ramp(conf.dac_nominal);
|
dac_ramp(conf.dac_nominal);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -361,6 +450,7 @@ int main()
|
||||||
conf.hvosc_dc = cmd[2];
|
conf.hvosc_dc = cmd[2];
|
||||||
}
|
}
|
||||||
hvosc_init(conf.hvosc_freq, conf.hvosc_dc);
|
hvosc_init(conf.hvosc_freq, conf.hvosc_dc);
|
||||||
|
hv_led_on();
|
||||||
conf.safe = 0;
|
conf.safe = 0;
|
||||||
break;
|
break;
|
||||||
case 'I':
|
case 'I':
|
||||||
|
|
@ -378,7 +468,7 @@ int main()
|
||||||
case 't':
|
case 't':
|
||||||
resp[1] = adc_status;
|
resp[1] = adc_status;
|
||||||
resp[2] = adc_error;
|
resp[2] = adc_error;
|
||||||
enable_irq(sreg);
|
sei();
|
||||||
spi_slave_Tx(resp, 3);
|
spi_slave_Tx(resp, 3);
|
||||||
if (cmd[1]) {
|
if (cmd[1]) {
|
||||||
if (upcase(cmd[0])) {
|
if (upcase(cmd[0])) {
|
||||||
|
|
@ -395,20 +485,17 @@ int main()
|
||||||
if (c>8)
|
if (c>8)
|
||||||
c = 8;
|
c = 8;
|
||||||
switch (cmd[2]) {
|
switch (cmd[2]) {
|
||||||
case 1: int2frame(adc_sum[c], resp+1); break;
|
case 1: int2frame(adc_sum[c] >> 8, resp+1); break;
|
||||||
case 2: resp[1] = adc_sum[c] >> 16; resp[2] = adc_n[c]; break;
|
case 2: resp[1] = adc_sum[c]; resp[2] = adc_n[c]; break;
|
||||||
case 3: int2frame(adc_noise[c], resp+1); break;
|
case 3: int2frame(adc_noise[c], resp+1); break;
|
||||||
default: resp[1] = adc_status; resp[2] = adc_error; break;
|
default: resp[1] = adc_status; resp[2] = adc_error; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
if (adc_error) {
|
if (cmd[1])
|
||||||
resp[0] = 'E';
|
int2frame(adc_hv, resp+1);
|
||||||
resp[1] = 'r';
|
else
|
||||||
resp[2] = adc_error;
|
int2frame(adc_aux, resp+1);
|
||||||
break;
|
|
||||||
}
|
|
||||||
int2frame(adc_aux, resp+1);
|
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
p = revision;
|
p = revision;
|
||||||
|
|
@ -420,18 +507,26 @@ int main()
|
||||||
resp[1] = *p;
|
resp[1] = *p;
|
||||||
resp[2] = cmd[1]-c;
|
resp[2] = cmd[1]-c;
|
||||||
break;
|
break;
|
||||||
|
case 'w':
|
||||||
|
resp[1] = conf.wdt_mode;
|
||||||
|
resp[2] = wdt_count;
|
||||||
|
sei();
|
||||||
|
spi_slave_Tx(resp, 3);
|
||||||
|
hv_safe();
|
||||||
|
break;
|
||||||
case 'W':
|
case 'W':
|
||||||
|
if (cmd[1]==0xff && cmd[2]==0xd1)
|
||||||
|
die();
|
||||||
resp[1] = conf.wdt_mode;
|
resp[1] = conf.wdt_mode;
|
||||||
resp[2] = conf.wdt_timeout;
|
resp[2] = conf.wdt_timeout;
|
||||||
if (cmd[2])
|
if (cmd[2])
|
||||||
conf.wdt_timeout = cmd[2];
|
conf.wdt_timeout = cmd[2];
|
||||||
if (cmd[1]) {
|
if (cmd[1])
|
||||||
wdt_init(cmd[1]);
|
wdt_init(cmd[1]);
|
||||||
sreg = (1<<SREG_I);
|
|
||||||
}
|
|
||||||
else {
|
else {
|
||||||
resp[2] = wdt_count;
|
resp[2] = wdt_count;
|
||||||
wdt_kick();
|
wdt_kick();
|
||||||
|
toggle_hv_led();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
|
|
@ -449,7 +544,7 @@ int main()
|
||||||
case 'S':
|
case 'S':
|
||||||
resp[1] = cmd[1];
|
resp[1] = cmd[1];
|
||||||
resp[2] = sizeof(conf);
|
resp[2] = sizeof(conf);
|
||||||
enable_irq(sreg);
|
sei();
|
||||||
spi_slave_Tx(resp, 3);
|
spi_slave_Tx(resp, 3);
|
||||||
eeprom_save(cmd[1]);
|
eeprom_save(cmd[1]);
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -465,7 +560,7 @@ int main()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cmd[1] && upcase(cmd[1])) {
|
if (cmd[1] && upcase(cmd[1])) {
|
||||||
enable_irq(sreg);
|
sei();
|
||||||
spi_slave_Tx(resp, 3);
|
spi_slave_Tx(resp, 3);
|
||||||
conf_init();
|
conf_init();
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -533,8 +628,20 @@ int main()
|
||||||
if (!upcase(cmd[0]))
|
if (!upcase(cmd[0]))
|
||||||
*(unsigned char *)(cmd[1]+0) = cmd[2];
|
*(unsigned char *)(cmd[1]+0) = cmd[2];
|
||||||
break;
|
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);
|
spi_slave_Tx(resp, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -555,8 +662,13 @@ void ads8688_config()
|
||||||
}, r);
|
}, r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile unsigned char adc_lock;
|
||||||
|
|
||||||
unsigned char read_adc(unsigned char c, unsigned char n)
|
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 nn = (1<<n) - 1;
|
||||||
unsigned char cc;
|
unsigned char cc;
|
||||||
if (c >= 8) {
|
if (c >= 8) {
|
||||||
|
|
@ -566,42 +678,58 @@ unsigned char read_adc(unsigned char c, unsigned char n)
|
||||||
else
|
else
|
||||||
cc = 1<<c;
|
cc = 1<<c;
|
||||||
|
|
||||||
spi_int_init();
|
|
||||||
unsigned char cmd[2] = {0, 0xc0 | (c << 2)};
|
unsigned char cmd[2] = {0, 0xc0 | (c << 2)};
|
||||||
unsigned char resp[2];
|
unsigned char resp[2];
|
||||||
unsigned char i;
|
unsigned char i;
|
||||||
|
adc_lock = 1;
|
||||||
|
unsigned char sreg = disable_irq();
|
||||||
for (i=0; i<3; i++)
|
for (i=0; i<3; i++)
|
||||||
ads8688_cmd(cmd, resp);
|
ads8688_cmd(cmd, resp);
|
||||||
|
enable_irq(sreg);
|
||||||
unsigned int s0 = frame2int(resp);
|
unsigned int s0 = frame2int(resp);
|
||||||
unsigned long s = s0;
|
unsigned long s = s0;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
unsigned long q = 0;
|
unsigned long q = 0;
|
||||||
|
spi_busy_init();
|
||||||
for (i=0; i<nn; i++) {
|
for (i=0; i<nn; i++) {
|
||||||
if (spi_int())
|
if (spi_busy()) {
|
||||||
return adc_error |= cc;
|
e = adc_error |= cc;
|
||||||
unsigned char sreg = disable_irq();
|
goto out;
|
||||||
|
}
|
||||||
|
sreg = disable_irq();
|
||||||
ads8688_cmd(cmd, resp);
|
ads8688_cmd(cmd, resp);
|
||||||
enable_irq(sreg);
|
enable_irq(sreg);
|
||||||
unsigned int s1 = frame2int(resp);
|
unsigned int s1 = frame2int(resp);
|
||||||
s += s1;
|
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;
|
r += d;
|
||||||
q += d * d;
|
q += d * d;
|
||||||
}
|
}
|
||||||
unsigned long rr = (long)r*r;
|
unsigned long rr = (long)r*r;
|
||||||
unsigned long qq = (nn+1)*q;
|
unsigned long qq = q << n;
|
||||||
unsigned long chi2 = qq-rr;
|
unsigned long chi2 = qq - rr;
|
||||||
adc_sum[c] = s;
|
adc_sum[c] = s << (8-n);
|
||||||
adc_noise[c] = chi2 >> n;
|
chi2 >>= 2*n - 1;
|
||||||
|
chi2 += 1;
|
||||||
|
chi2 >>= 1;
|
||||||
|
adc_noise[c] = chi2;
|
||||||
adc_n[c] = n;
|
adc_n[c] = n;
|
||||||
adc_status |= cc;
|
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)
|
void adc_read(unsigned char chs, unsigned char n)
|
||||||
{
|
{
|
||||||
spi_int_init();
|
|
||||||
adc_status = 0;
|
adc_status = 0;
|
||||||
adc_error = 0;
|
adc_error = 0;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
|
@ -610,34 +738,24 @@ void adc_read(unsigned char chs, unsigned char n)
|
||||||
continue;
|
continue;
|
||||||
if (read_adc(c, n))
|
if (read_adc(c, n))
|
||||||
return;
|
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 int read_auxadc()
|
||||||
{
|
{
|
||||||
unsigned char n = conf.auxadc_n;
|
unsigned char n = conf.auxadc_n;
|
||||||
if (!read_adc(8, n))
|
if (!read_adc(8, n))
|
||||||
adc_aux = adc_sum[8] >> n;
|
adc_aux = adc_sum[8] >> 8;
|
||||||
return adc_aux;
|
return adc_aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
void dac_ramp(unsigned int target)
|
void dac_ramp(unsigned int target)
|
||||||
{
|
{
|
||||||
conf.safe = 0;
|
conf.safe = 0;
|
||||||
spi_int_init();
|
unsigned char toggle = 0;
|
||||||
|
spi_busy_init();
|
||||||
while (conf.dac != target) {
|
while (conf.dac != target) {
|
||||||
if (spi_int())
|
if (spi_busy())
|
||||||
return;
|
return;
|
||||||
if (!tick(TICKO))
|
if (!tick(TICKO))
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -649,24 +767,36 @@ void dac_ramp(unsigned int target)
|
||||||
conf.dac = target;
|
conf.dac = target;
|
||||||
ltc1655_cmd(INT2FRAME(conf.dac));
|
ltc1655_cmd(INT2FRAME(conf.dac));
|
||||||
enable_irq(sreg);
|
enable_irq(sreg);
|
||||||
|
toggle++;
|
||||||
|
if (!toggle)
|
||||||
|
toggle_hv_led();
|
||||||
}
|
}
|
||||||
|
hv_led_on();
|
||||||
}
|
}
|
||||||
|
|
||||||
ISR(WDT_vect)
|
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();
|
wdt_reset();
|
||||||
if (conf.wdt_save_addr && !wdt_saved) {
|
wdt_count++;
|
||||||
wdt_saved = 1;
|
if (wdt_count >= conf.wdt_toggle) {
|
||||||
eeprom_save(conf.wdt_save_addr);
|
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:
|
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)
|
void wdt_init(unsigned char mode)
|
||||||
|
|
@ -674,7 +804,12 @@ void wdt_init(unsigned char mode)
|
||||||
conf.wdt_mode = mode;
|
conf.wdt_mode = mode;
|
||||||
wdt_reset();
|
wdt_reset();
|
||||||
if (mode < WDT_MODE_LIVE) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
// 1s timeout, WDT interrupt enabled
|
// 1s timeout, WDT interrupt enabled
|
||||||
|
|
@ -713,10 +848,4 @@ void avradc_enable(unsigned char c)
|
||||||
if (!(c&0x80))
|
if (!(c&0x80))
|
||||||
ADCSRA |= 1<<ADEN;
|
ADCSRA |= 1<<ADEN;
|
||||||
ADCSRA |= 1<<ADSC;
|
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)
|
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) {
|
if (!dc || freq <= dc) {
|
||||||
TCCR1A = 0;
|
TCCR1A = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PRR &=~ (1<<PRTIM1);
|
PRR &=~ (1<<PRTIM1);
|
||||||
DDRC |= (1<<PC1);
|
|
||||||
DDRD |= (1<<PD2);
|
|
||||||
TCCR1A = (2<<COM1A0) | (3<<COM1B0) | (2<<WGM10);
|
TCCR1A = (2<<COM1A0) | (3<<COM1B0) | (2<<WGM10);
|
||||||
TCCR1B = (1<<CS10) | (2<<WGM12);
|
TCCR1B = (1<<CS10) | (2<<WGM12);
|
||||||
ICR1H = 0;
|
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;
|
SPSR;
|
||||||
SPDR;
|
SPDR;
|
||||||
|
|
@ -55,17 +76,3 @@ static inline unsigned int frame2int(unsigned char *f)
|
||||||
}
|
}
|
||||||
#define INT2FRAME(i) ((unsigned char []){i, i>>8})
|
#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