@@ -0,0 +1,9 @@ | |||
#ifndef MODE_H | |||
#define MODE_H | |||
#include "config.h" | |||
void run_normal(void); | |||
void run_debug(void); | |||
#endif |
@@ -0,0 +1,182 @@ | |||
#include "config.h" | |||
#include "adc.h" | |||
#include "dac.h" | |||
#include "uart.h" | |||
#include "timer.h" | |||
#include <stdio.h> | |||
#include <math.h> | |||
#include "scaling.h" | |||
#include "util.h" | |||
#include "led.h" | |||
#include "mode.h" | |||
#include "zoom.h" | |||
#define DEBUG_BLINK_RATE 4 | |||
/* Debug LED */ | |||
void TISR_HANDLER(6) | |||
{ | |||
static int toggle = 0; | |||
timer_clear_txif(6); | |||
toggle = !toggle; | |||
if (toggle) | |||
led_on(); | |||
else | |||
led_off(); | |||
} | |||
static uint16_t dac = 32768; | |||
#define TIMER_RATE 8000 | |||
static int zero_adc = 0; | |||
void TISR_HANDLER(7) | |||
{ | |||
int16_t v; | |||
float dac_current, i; | |||
timer_clear_txif(7); | |||
if (zero_adc) { | |||
dac_current = dac_to_current(dac); | |||
v = adc_get(); | |||
i = adc12_to_current(v); | |||
/* adjust by 50% of the estimated value, in case our calibration is wrong */ | |||
dac_current -= (i * 0.5); | |||
if (dac_current < dac_current_min) | |||
dac_current = dac_current_min; | |||
if (dac_current > dac_current_max) | |||
dac_current = dac_current_max; | |||
dac = current_to_dac(dac_current); | |||
dac_write(dac); | |||
} | |||
} | |||
void sweep(void) | |||
{ | |||
int32_t d; | |||
int16_t a; | |||
/* sweep range */ | |||
for (d = (int32_t)dac - 1500; d < (int32_t)dac + 1500; d++) { | |||
if (d < 0x0000) { | |||
uart1_put_string("0 0\r\n"); | |||
continue; | |||
} | |||
if (d > 0xffff) { | |||
uart1_put_string("65535 0\r\n"); | |||
continue; | |||
} | |||
dac_write(d); | |||
msleep(1); | |||
a = adc_get(); | |||
uart1_put_dec(d); | |||
uart1_put(' '); | |||
uart1_put_dec(a); | |||
uart1_crlf(); | |||
} | |||
} | |||
void run_debug(void) | |||
{ | |||
int16_t adc; | |||
int32_t v; | |||
char buf[4]; | |||
uart1_init(115200); | |||
timer_setup_16bit(6, DEBUG_BLINK_RATE, 1); | |||
timer_setup_16bit(7, TIMER_RATE, 1); | |||
uart1_put_string("Zoom NILM Debug\r\n"); | |||
while (1) { | |||
dac_write(dac); | |||
uart1_put_hex16(dac); | |||
uart1_put(' '); | |||
uart1_put_dec(dac); | |||
uart1_put(' '); | |||
uart1_put(' '); | |||
adc = adc_get(); | |||
uart1_put_hex16(adc); | |||
uart1_put(' '); | |||
uart1_put_dec(adc); | |||
uart1_crlf(); | |||
switch (uart1_get()) { | |||
// small step | |||
case '[': | |||
dac--; | |||
break; | |||
case ']': | |||
dac++; | |||
break; | |||
// medium step | |||
case '-': | |||
dac -= 16; | |||
break; | |||
case '+': | |||
case '=': | |||
dac += 16; | |||
break; | |||
// big step | |||
case ',': | |||
case '<': | |||
dac -= 1024; | |||
break; | |||
case '.': | |||
case '>': | |||
dac += 1024; | |||
break; | |||
// set DAC to midpoint | |||
case '0': | |||
dac = 32768; | |||
break; | |||
// run degauss (currently a noop) | |||
case 'd': | |||
uart1_put_string("degauss..."); | |||
degauss(); | |||
uart1_crlf(); | |||
dac = 32768; | |||
break; | |||
// set DAC to specified hex value | |||
case 'v': | |||
case 'V': | |||
buf[0] = uart1_get(); | |||
buf[1] = uart1_get(); | |||
buf[2] = uart1_get(); | |||
buf[3] = uart1_get(); | |||
v = hex_to_u16(buf); | |||
if (v < 0) | |||
uart1_put_string("bad value\r\n"); | |||
else | |||
dac = v; | |||
break; | |||
// maintain ADC input at zero | |||
case 'z': | |||
case 'Z': | |||
uart1_put_string("zeroing input...\r\n"); | |||
zero_adc = 1; | |||
uart1_get(); | |||
zero_adc = 0; | |||
break; | |||
// sweep DAC | |||
case 's': | |||
case 'S': | |||
uart1_put_string("sweep around "); | |||
uart1_put_dec(dac); | |||
uart1_crlf(); | |||
sweep(); | |||
break; | |||
} | |||
} | |||
} | |||
@@ -0,0 +1,121 @@ | |||
#include "config.h" | |||
#include "adc.h" | |||
#include "adcext.h" | |||
#include "dac.h" | |||
#include "uart.h" | |||
#include "timer.h" | |||
#include <stdio.h> | |||
#include <math.h> | |||
#include "scaling.h" | |||
#include "util.h" | |||
#include "mode.h" | |||
#include "zoom.h" | |||
int send_data = 0; | |||
uint16_t send_adc; | |||
uint16_t send_dac; | |||
int possible_overflow = 0; | |||
float dac_current; | |||
#define TIMER_RATE 8000 /* how often to read the ADC and update DAC */ | |||
#define PC_RATE 8000 /* how often to send data to the PC */ | |||
/* Run mode */ | |||
void TISR_HANDLER(5) | |||
{ | |||
static int count = 0; | |||
static uint16_t dac_cmd; | |||
int16_t v; | |||
float i; | |||
/* toggle A9 every time an interrupt occurs */ | |||
LATAbits.LATA9 = 1; | |||
timer_clear_txif(5); | |||
/* Get most recent sample from 12-bit ADC. */ | |||
v = adc_get(); | |||
if (v < 0 || v >= 2047) | |||
possible_overflow = 1; | |||
/* Send data to PC at 1 Hz */ | |||
if (++count >= (TIMER_RATE / PC_RATE)) { | |||
count = 0; | |||
/* Send most recent sample and old DAC value */ | |||
send_adc = v; | |||
send_dac = dac_cmd; | |||
send_data = 1; | |||
} | |||
/* Convert ADC value to current */ | |||
i = adc12_to_current(v); | |||
#if 0 | |||
/* Adjust DAC to null this current to 0 */ | |||
dac_current -= i; | |||
#else | |||
/* If this current exceeds +-1A, cancel it out at the DAC */ | |||
if (i < -1.0 || i > 1.0) | |||
dac_current -= i; | |||
#endif | |||
if (dac_current < dac_current_min) | |||
dac_current = dac_current_min; | |||
if (dac_current > dac_current_max) | |||
dac_current = dac_current_max; | |||
/* Now send it out */ | |||
dac_cmd = current_to_dac(dac_current); | |||
dac_write(dac_cmd); | |||
LATAbits.LATA9 = 0; | |||
} | |||
void send_to_pc(uint16_t adc, uint16_t dac) | |||
{ | |||
/* Sent data format: | |||
1Aaa aaaa 0aaa aaDd 0ddd dddd 0ddd dddd | |||
Aaaaaaaaaaaa = 12-bit ADC value (2s compliment signed) | |||
Dddddddddddddddd = 16-bit DAC command (unsigned) | |||
*/ | |||
uart1_put(0x80 | ((adc & 0x0FE0) >> 5)); | |||
uart1_put(((adc & 0x001F) << 2) | ((dac & 0xC000) >> 14)); | |||
uart1_put((dac & 0x3F80) >> 7); | |||
uart1_put((dac & 0x007F)); | |||
} | |||
void run_normal(void) | |||
{ | |||
uart1_init(500000); | |||
/* Assume startup current is 0 */ | |||
dac_current = 0.0; | |||
dac_write(current_to_dac(dac_current)); | |||
msleep(100); | |||
degauss(); | |||
timer_setup_16bit(5, TIMER_RATE, 1); | |||
while(1) { | |||
if (send_data) { | |||
/* There's data to send. Disable the ISR briefly | |||
while we grab it */ | |||
uint16_t a, d; | |||
disable_int({ | |||
if (possible_overflow) { | |||
/* Mark a possible overflow in the output | |||
by setting ADC to an unlikely value */ | |||
possible_overflow = 0; | |||
a = 0x0800; | |||
} else { | |||
a = send_adc; | |||
} | |||
d = send_dac; | |||
send_data = 0; | |||
}); | |||
send_to_pc(a, d); | |||
} | |||
} | |||
} |
@@ -1,6 +0,0 @@ | |||
#ifndef MODE_NORMAL_H | |||
#define MODE_NORMAL_H | |||
#include "config.h" | |||
#endif |
@@ -37,3 +37,12 @@ float adc12_to_current(int16_t picv) | |||
amps = (picv - 1024.0) / 404.0; | |||
return amps; | |||
} | |||
float dac_current_min; | |||
float dac_current_max; | |||
void scaling_init(void) | |||
{ | |||
dac_current_min = dac_to_current(0x0000); | |||
dac_current_max = dac_to_current(0xffff); | |||
} |
@@ -5,4 +5,9 @@ float adc12_to_current(int16_t picv); | |||
float dac_to_current(uint16_t dacv); | |||
uint16_t current_to_dac(float amps); | |||
void scaling_init(void); | |||
extern float dac_current_min; | |||
extern float dac_current_max; | |||
#endif |
@@ -4,118 +4,10 @@ | |||
#include "dac.h" | |||
#include "uart.h" | |||
#include "timer.h" | |||
#include <stdio.h> | |||
#include <math.h> | |||
#include "scaling.h" | |||
#include "util.h" | |||
#include "led.h" | |||
int send_data = 0; | |||
uint16_t send_adc; | |||
uint16_t send_dac; | |||
int possible_overflow = 0; | |||
#define DAC_MIN 0x0000 | |||
#define DAC_MAX 0xFFFF | |||
float dac_current; | |||
float dac_current_min; | |||
float dac_current_max; | |||
#define TIMER_RATE 8000 /* how often to read the ADC and update DAC */ | |||
#define PC_RATE 8000 /* how often to send data to the PC */ | |||
#define DEBUG_BLINK_RATE 4 | |||
/* Debug LED */ | |||
void TISR_HANDLER(6) | |||
{ | |||
static int toggle = 0; | |||
timer_clear_txif(6); | |||
toggle = !toggle; | |||
if (toggle) | |||
led_on(); | |||
else | |||
led_off(); | |||
} | |||
/* Debug mode */ | |||
int debug_zero_adc = 0; | |||
void TISR_HANDLER(7) | |||
{ | |||
timer_clear_txif(7); | |||
if (debug_zero_adc) | |||
{ | |||
} | |||
} | |||
/* Run mode */ | |||
void TISR_HANDLER(5) | |||
{ | |||
static int count = 0; | |||
static uint16_t dac_cmd; | |||
uint16_t v; | |||
float i; | |||
/* toggle A9 every time an interrupt occurs */ | |||
LATAbits.LATA9 = 1; | |||
timer_clear_txif(5); | |||
/* Get most recent sample from 12-bit ADC. */ | |||
v = adc_get(); | |||
if (v < 0 || v >= 2047) | |||
possible_overflow = 1; | |||
/* Send data to PC at 1 Hz */ | |||
if (++count >= (TIMER_RATE / PC_RATE)) { | |||
count = 0; | |||
/* Send most recent sample and old DAC value */ | |||
send_adc = v; | |||
send_dac = dac_cmd; | |||
send_data = 1; | |||
} | |||
/* Convert ADC value to current */ | |||
i = adc12_to_current(v); | |||
#if 0 | |||
/* Adjust DAC to null this current to 0 */ | |||
dac_current -= i; | |||
#else | |||
/* If this current exceeds +-1A, cancel it out at the DAC */ | |||
if (i < -1.0 || i > 1.0) | |||
dac_current -= i; | |||
#endif | |||
if (dac_current < dac_current_min) | |||
dac_current = dac_current_min; | |||
if (dac_current > dac_current_max) | |||
dac_current = dac_current_max; | |||
/* Now send it out */ | |||
dac_cmd = current_to_dac(dac_current); | |||
dac_write(dac_cmd); | |||
LATAbits.LATA9 = 0; | |||
} | |||
void send_to_pc(uint16_t adc, uint16_t dac) | |||
{ | |||
/* Sent data format: | |||
1Aaa aaaa 0aaa aaDd 0ddd dddd 0ddd dddd | |||
Aaaaaaaaaaaa = 12-bit ADC value (2s compliment signed) | |||
Dddddddddddddddd = 16-bit DAC command (unsigned) | |||
*/ | |||
uart1_put(0x80 | ((adc & 0x0FE0) >> 5)); | |||
uart1_put(((adc & 0x001F) << 2) | ((dac & 0xC000) >> 14)); | |||
uart1_put((dac & 0x3F80) >> 7); | |||
uart1_put((dac & 0x007F)); | |||
} | |||
#include "mode.h" | |||
#include "zoom.h" | |||
void degauss(void) | |||
{ | |||
@@ -130,143 +22,6 @@ void degauss(void) | |||
#endif | |||
} | |||
void run_debug(void) | |||
{ | |||
uint16_t dac = 32768; | |||
int16_t adc; | |||
int32_t v; | |||
char buf[4]; | |||
uart1_init(115200); | |||
timer_setup_16bit(6, DEBUG_BLINK_RATE, 1); | |||
uart1_put_string("Zoom NILM Debug\r\n"); | |||
while (1) { | |||
dac_write(dac); | |||
uart1_put_hex16(dac); | |||
uart1_put(' '); | |||
uart1_put_dec(dac); | |||
uart1_put(' '); | |||
uart1_put(' '); | |||
adc = adc_get(); | |||
uart1_put_hex16(adc); | |||
uart1_put(' '); | |||
uart1_put_dec(adc); | |||
uart1_crlf(); | |||
switch (uart1_get()) { | |||
// small step | |||
case '[': | |||
dac--; | |||
break; | |||
case ']': | |||
dac++; | |||
break; | |||
// medium step | |||
case '-': | |||
dac -= 16; | |||
break; | |||
case '+': | |||
case '=': | |||
dac += 16; | |||
break; | |||
// big step | |||
case ',': | |||
case '<': | |||
dac -= 1024; | |||
break; | |||
case '.': | |||
case '>': | |||
dac += 1024; | |||
break; | |||
// set DAC to midpoint | |||
case '0': | |||
dac = 32768; | |||
break; | |||
// run degauss (currently a noop) | |||
case 'd': | |||
uart1_put_string("degauss..."); | |||
degauss(); | |||
uart1_crlf(); | |||
dac = 32768; | |||
break; | |||
// set DAC to specified hex value | |||
case 'v': | |||
case 'V': | |||
buf[0] = uart1_get(); | |||
buf[1] = uart1_get(); | |||
buf[2] = uart1_get(); | |||
buf[3] = uart1_get(); | |||
v = hex_to_u16(buf); | |||
if (v < 0) | |||
uart1_put_string("bad value\r\n"); | |||
else | |||
dac = v; | |||
break; | |||
// maintain ADC input at zero | |||
case 'z': | |||
case 'Z': | |||
uart1_put_string("zeroing input...\r\n"); | |||
debug_zero_adc = 1; | |||
uart1_get(); | |||
debug_zero_adc = 0; | |||
break; | |||
// sweep DAC | |||
case 's': | |||
case 'S': | |||
uart1_put_string("sweep\r\n"); | |||
debug_sweep(); | |||
break; | |||
} | |||
} | |||
} | |||
void run_normal(void) | |||
{ | |||
uart1_init(500000); | |||
/* Assume startup current is 0 */ | |||
dac_current = 0.0; | |||
dac_write(current_to_dac(dac_current)); | |||
msleep(100); | |||
degauss(); | |||
/* Set min/max */ | |||
dac_current_min = dac_to_current(DAC_MIN); | |||
dac_current_max = dac_to_current(DAC_MAX); | |||
timer_setup_16bit(5, TIMER_RATE, 1); | |||
while(1) { | |||
if (send_data) { | |||
/* There's data to send. Disable the ISR briefly | |||
while we grab it */ | |||
uint16_t a, d; | |||
disable_int({ | |||
if (possible_overflow) { | |||
/* Mark a possible overflow in the output | |||
by setting ADC to an unlikely value */ | |||
possible_overflow = 0; | |||
a = 0x0800; | |||
} else { | |||
a = send_adc; | |||
} | |||
d = send_dac; | |||
send_data = 0; | |||
}); | |||
send_to_pc(a, d); | |||
} | |||
} | |||
} | |||
int main(void) | |||
{ | |||
int jumper; | |||
@@ -278,6 +33,7 @@ int main(void) | |||
/* debug output */ | |||
TRISAbits.TRISA9 = 0; | |||
scaling_init(); | |||
adcext_init(); | |||
dac_init(); | |||
dac_write(32768); | |||
@@ -0,0 +1,6 @@ | |||
#ifndef ZOOM_H | |||
#define ZOOM_H | |||
void degauss(void); | |||
#endif |
@@ -63,8 +63,8 @@ file_017=adcext.h | |||
file_018=adc.h | |||
file_019=scaling.h | |||
file_020=led.h | |||
file_021=mode_debug.h | |||
file_022=mode_normal.h | |||
file_021=mode.h | |||
file_022=zoom.h | |||
file_023=p33fj256gp710.gld | |||
[SUITE_INFO] | |||
suite_guid={479DDE59-4D56-455E-855E-FFF59A3DB57E} | |||