zoom/firmware/mode_normal.c

143 lines
2.8 KiB
C

#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 "calibrate.h"
#include "util.h"
#include "mode.h"
#include "led.h"
#include "packet.h"
int send_data = 0;
uint16_t send_adc;
uint16_t send_dac;
int possibly_clamped = 0;
uint16_t dac_cmd;
#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_ISR_TIME
#define ADC_WINDOW_MIN 512
#define ADC_WINDOW_MIN_STEPTO 1280
#define ADC_WINDOW_MAX 1536
#define ADC_WINDOW_MAX_STEPTO 768
/* Run mode */
void TISR_HANDLER(5)
{
static int count = 0;
int16_t v;
#ifdef DEBUG_ISR_TIME
LATAbits.LATA9 = 1;
#endif
timer_clear_txif(5);
/* Get most recent sample from 12-bit ADC. */
v = adc_get();
if (v < ADC_CLAMP_MIN || v >= ADC_CLAMP_MAX)
possibly_clamped = 1;
/* Send data to PC */
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;
}
#define WINDOW
#ifdef WINDOW
/* If ADC value is outside the window, step DAC */
if (v < ADC_WINDOW_MIN)
dac_cmd = adc_to_dac(dac_cmd, v, ADC_WINDOW_MIN_STEPTO,
g_scale);
else if (v > ADC_WINDOW_MAX)
dac_cmd = adc_to_dac(dac_cmd, v, ADC_WINDOW_MAX_STEPTO,
g_scale);
#else
dac_cmd = adc_to_dac(dac_cmd, v, 1024, g_scale);
#endif
/* Send it out */
dac_write(dac_cmd);
#ifdef DEBUG_ISR_TIME
LATAbits.LATA9 = 0;
#endif
}
void run_normal(void)
{
int i;
uart1_init(500000);
led_pattern(0b00110011);
/* Keep writing zero to the DAC for about 30 seconds after startup,
or until we receive a character on the UART */
while(uart1_can_get())
uart1_get();
for (i = 0; i < 1500; i++) {
dac_write(DAC_MID);
if (uart1_can_get()) {
uart1_get();
break;
}
msleep(10);
}
led_on();
/* Assume startup current is 0 */
msleep(100);
dac_cmd = do_calibrate();
timer_setup_16bit(5, TIMER_RATE, 1);
timer_set_priority(5, 6);
while(1) {
if (send_data) {
/* There's data to send. Disable the ISR briefly
while we grab it */
uint16_t a, d, o;
disable_int({
if (possibly_clamped) {
/* Mark a possible
* overflow in the
* output */
o = 1;
possibly_clamped = 0;
} else o = 0;
a = send_adc;
d = send_dac;
send_data = 0;
});
packet_send_adc_dac(a, d, o);
}
if (uart1_can_get()) {
switch (uart1_get()) {
case 'c':
disable_int({
send_data = 0;
dac_cmd = do_calibrate();
});
packet_send_calibration(g_scale);
default:
break;
}
}
}
}