This commit is contained in:
yichin
2019-05-28 18:53:55 +08:00
parent aa662f4a7b
commit 495d4deb91
2 changed files with 129 additions and 198 deletions
@@ -67,6 +67,7 @@ TODO
#include "headstage_debug.h"
#include "headstage_power.h"
#include "headstage_pin.h"
#include "headstage_notify.h"
#include "sti/headstage_gptimer.h"
#include "sti/headstage_pwm.h"
@@ -92,19 +93,21 @@ static uint32_t cpu_frequency;
#ifdef headstage_gptimer_set_frequency
#undef headstage_gptimer_set_frequency
#endif
#define headstage_gptimer_set_frequency(gptimer_handle, frequency) \
do { \
GPTimerCC26XX_setLoadValue(gptimer_handle, headstage_gptimer_get_frequency_load_value(frequency)); \
} while (0)
#endif
#ifdef headstage_gptimer_set_timeout
#undef headstage_gptimer_set_timeout
#endif
#define headstage_gptimer_set_timeout(gptimer_handle, timeout_us) \
do { \
GPTimerCC26XX_setLoadValue(gptimer_handle, headstage_gptimer_get_timeout_load_value(timeout_us)); \
} while (0)
#endif
/*======================
@@ -281,7 +284,7 @@ typedef struct {
uint16_t times;
} NeuLiveStiChannelParameter;
typedef struct {
typedef struct NeuLiveStiChannelState{
/**
* waveform
*/
@@ -307,11 +310,6 @@ typedef struct {
*/
uint8_t stage;
/**
* stage number
*/
uint8_t stage_limit;
/**
* PIN pin value through the pulse stage
*/
@@ -323,9 +321,10 @@ typedef struct {
uint8_t ponv;
/**
* counter for lwo frequenct timer.
* counter for lwo frequency timer.
*/
uint8_t low_freq_counter;
uint8_t low_freq_load;
/**
* timeout in us for each pulse stage
@@ -336,16 +335,17 @@ typedef struct {
* period timer handle
*/
GPTimerCC26XX_Handle perd_handle;
GPTimerCC26XX_Handle step_handle;
/**
* period timer timeout callback for low frequency mode.
*/
GPTimerCC26XX_HwiFxn perd_callback;
void (*perd_callback)(struct NeuLiveStiChannelState *s);
/**
* step timer handle
* stepping timer timeout callback for high frequency timer.
*/
GPTimerCC26XX_Handle handle[3];
void (*step_callback)(struct NeuLiveStiChannelState *s);
} NeuLiveStiChannelState;
#define headstage_sti_output_pol(s, t) headstage_pin_output(s->pol, s->polv &(1 << (t)));
@@ -378,10 +378,9 @@ static uint8_t headstage_sti_gptimer_init(uint8_t channel);
static void headstage_sti_gptimer_start();
static void headstage_sti_gptimer_stop();
static void headstage_sti_gptimer_term();
static void headstage_sti_gptimer_single_channel_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
static void headstage_sti_gptimer_perd_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
static void headstage_sti_gptimer_step_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
static void headstage_sti_gptimer_low_freq_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
static void headstage_sti_single_callback(NeuLiveStiChannelState *s);
static void headstage_sti_period_callback(NeuLiveStiChannelState *s);
static void headstage_sti_stepping_callback(NeuLiveStiChannelState *s);
/*=======================
==== event dispatch ====
@@ -409,8 +408,10 @@ static void headstage_init() {
BIOS_getCpuFreq(&cpu_freq);
cpu_frequency = cpu_freq.lo;
// init gptimer
headstage_gptimer_open();
// init PWM
headstage_pwm_open();
// init gpio
@@ -432,20 +433,20 @@ static void headstage_init() {
headstage_update_ris_instruction(2, ins);
ins[0] = 0x40;
ins[1] = 0x00;
ins[1] = 0x40;
ins[2] = 0x0A;
ins[3] = 0x32;
ins[3] = 0x05;
ins[4] = 0x00;
ins[5] = 0xAF;
ins[6] = 0xA0;
headstage_update_ris_instruction(7, ins);
ins[0] = 0x41;
ins[1] = 0x00;
ins[1] = 0x40;
ins[2] = 0x0A;
ins[3] = 0x32;
ins[4] = 0x00;
ins[5] = 0xAF;
ins[4] = 0x06;
ins[5] = 0x4F;
ins[6] = 0xA0;
headstage_update_ris_instruction(7, ins);
@@ -660,7 +661,6 @@ static uint8_t headstage_sti_gptimer_init(uint8_t channel) {
switch (p->mode) {
case STI_WAVEFORM_POS:
// +1 0
s->stage_limit = 1;
s->polv = 0x03; // 11
s->ponv = 0x01; // 01
s->timeout_us[0] = p->pulse_width;
@@ -670,7 +670,6 @@ static uint8_t headstage_sti_gptimer_init(uint8_t channel) {
case STI_WAVEFORM_NEG:
// -1 0
s->stage_limit = 1;
s->polv = 0x00; // 00
s->ponv = 0x01; // 01
s->timeout_us[0] = p->pulse_width;
@@ -683,7 +682,6 @@ static uint8_t headstage_sti_gptimer_init(uint8_t channel) {
if (p->pw_ipi == 0) {
// +1 -1 0
s->mode = STI_WAVEFORM_P2N;
s->stage_limit = 2;
s->polv = 0x05; // 101
s->ponv = 0x03; // 011
s->timeout_us[0] = p->pulse_width;
@@ -692,8 +690,7 @@ static uint8_t headstage_sti_gptimer_init(uint8_t channel) {
} else {
// +1 0 -1 0
s->mode = STI_WAVEFORM_PIN;
s->stage_limit = 3;
s->polv = 0x0B; // 1011
s->polv = 0x09; // 1001
s->ponv = 0x05; // 0101
s->timeout_us[0] = p->pulse_width;
s->timeout_us[1] = p->pw_ipi;
@@ -706,7 +703,6 @@ static uint8_t headstage_sti_gptimer_init(uint8_t channel) {
if (p->pw_ipi == 0) {
// -1 +1 0
s->mode = STI_WAVEFORM_N2P;
s->stage_limit = 2;
s->polv = 0x02; // 010
s->ponv = 0x03; // 011
s->timeout_us[0] = p->pulse_width;
@@ -715,8 +711,7 @@ static uint8_t headstage_sti_gptimer_init(uint8_t channel) {
} else {
// -1 0 +1 0
s->mode = STI_WAVEFORM_NIP;
s->stage_limit = 3;
s->polv = 0x06; // 0110
s->polv = 0x04; // 0100
s->ponv = 0x05; // 0101
s->timeout_us[0] = p->pulse_width;
s->timeout_us[1] = p->pw_ipi;
@@ -737,18 +732,15 @@ static void headstage_sti_gptimer_init_post(uint8_t channel) {
GPTimerCC26XX_Handle g;
GPTimerCC26XX_Handle gs;
GPTimerCC26XX_Handle gi;
switch (channel) {
case CHANNEL_STI_0:
g = gptimer_handle_p0;
gs = gptimer_handle_s0;
gi = gptimer_handle_i0;
break;
case CHANNEL_STI_1:
g = gptimer_handle_p1;
gs = gptimer_handle_s1;
gi = gptimer_handle_i1;
break;
case CHANNEL_BATTERY:
default:
@@ -764,63 +756,26 @@ static void headstage_sti_gptimer_init_post(uint8_t channel) {
headstage_gptimer_set_frequency(g, p->frequency);
if (p->precision) {
s->low_freq_counter = 10;
s->low_freq_counter = 9;
s->low_freq_load = 9;
} else {
s->low_freq_counter = 0;
s->low_freq_load = 0;
}
s->perd_handle = g;
s->handle[0] = NULL;
s->handle[1] = NULL;
s->handle[2] = NULL;
switch (s->mode) {
case STI_WAVEFORM_POS:
case STI_WAVEFORM_NEG:
s->handle[0] = gs;
headstage_gptimer_set_timeout(gs, p->pulse_width);
break;
case STI_WAVEFORM_P2N:
case STI_WAVEFORM_N2P:
s->handle[0] = gs;
s->handle[1] = gs;
headstage_gptimer_set_timeout(gs, p->pulse_width);
break;
case STI_WAVEFORM_PIN:
case STI_WAVEFORM_NIP:
s->handle[0] = gs;
s->handle[1] = gi;
s->handle[2] = gs;
headstage_gptimer_set_timeout(gs, p->pulse_width);
headstage_gptimer_set_timeout(gi, p->pw_ipi);
break;
}
s->step_handle = gs;
if (channel_enable_number == 1) {
if (p->precision) {
s->timeout_us[0] = get_spin_timeout_value(s->timeout_us[0]);
s->timeout_us[1] = get_spin_timeout_value(s->timeout_us[1]);
s->timeout_us[2] = get_spin_timeout_value(s->timeout_us[2]);
s->perd_callback = headstage_sti_gptimer_single_channel_callback;
headstage_gptimer_set_callback(g, headstage_sti_gptimer_low_freq_callback);
} else {
s->timeout_us[0] = get_spin_timeout_value(s->timeout_us[0]);
s->timeout_us[1] = get_spin_timeout_value(s->timeout_us[1]);
s->timeout_us[2] = get_spin_timeout_value(s->timeout_us[2]);
s->perd_callback = NULL;
headstage_gptimer_set_callback(g, headstage_sti_gptimer_single_channel_callback);
}
} else {
if (p->precision) {
s->perd_callback = headstage_sti_gptimer_perd_callback;
headstage_gptimer_set_callback(g, headstage_sti_gptimer_low_freq_callback);
} else {
s->perd_callback = NULL;
headstage_gptimer_set_callback(g, headstage_sti_gptimer_perd_callback);
}
s->timeout_us[0] = get_spin_timeout_value(s->timeout_us[0]);
s->timeout_us[1] = get_spin_timeout_value(s->timeout_us[1]);
s->timeout_us[2] = get_spin_timeout_value(s->timeout_us[2]);
headstage_gptimer_set_callback(gs, headstage_sti_gptimer_step_callback);
headstage_gptimer_set_callback(gi, headstage_sti_gptimer_step_callback);
s->perd_callback = &headstage_sti_single_callback;
s->step_callback = NULL;
} else {
s->perd_callback = &headstage_sti_period_callback;
s->step_callback = &headstage_sti_stepping_callback;
}
}
@@ -918,8 +873,6 @@ static void headstage_sti_gptimer_stop() {
headstage_gptimer_stop(gptimer_handle_p1);
headstage_gptimer_stop(gptimer_handle_s0);
headstage_gptimer_stop(gptimer_handle_s1);
headstage_gptimer_stop(gptimer_handle_i0);
headstage_gptimer_stop(gptimer_handle_i1);
headstage_pin_output(PIN_LED_R, 0);
}
@@ -927,13 +880,14 @@ static void headstage_sti_gptimer_stop() {
static void headstage_sti_gptimer_term() {
uint8_t channel_enable_number = 0;
NeuLiveStiChannelParameter *p = INSTRUCTION.channel + 1;
NeuLiveStiChannelState *s0 = INSTRUCTION.state + CHANNEL_STI_0;
NeuLiveStiChannelState *s1 = INSTRUCTION.state + CHANNEL_STI_1;
if (p->enable && p->times > 0) {
if (s0->times > 0) {
channel_enable_number++;
}
if (p->enable && p->times > 0) {
if (s1->times > 0) {
channel_enable_number++;
}
@@ -945,7 +899,7 @@ static void headstage_sti_gptimer_term() {
INSTRUCTION.channel_enable_number = channel_enable_number;
}
static void headstage_sti_gptimer_single_channel_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
static void headstage_sti_gptimer_main_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
NeuLiveStiChannelState *s = INSTRUCTION.state;
if (handle == gptimer_handle_p0) {
@@ -953,19 +907,45 @@ static void headstage_sti_gptimer_single_channel_callback(GPTimerCC26XX_Handle h
} else if (handle == gptimer_handle_p1) {
s += CHANNEL_STI_1;
} else {
headstage_set_error(ERR_STATE_STI | ERR_STI_UNEXPECTED_HANDLE, handle);
headstage_set_error(ERR_STATE_STI_LOW | ERR_STI_UNEXPECTED_HANDLE, handle);
return;
}
if (s->times == 0) {
headstage_gptimer_stop(handle);
if (s->low_freq_counter == 0) {
if (s->perd_callback) {
s->perd_callback(s);
}
s->low_freq_counter = s->low_freq_load;
} else {
s->low_freq_counter--;
}
}
static void headstage_sti_gptimer_step_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
NeuLiveStiChannelState *s = INSTRUCTION.state;
if (handle == gptimer_handle_s0) {
s += CHANNEL_STI_0;
} else if (handle == gptimer_handle_s1) {
s += CHANNEL_STI_1;
} else {
headstage_set_error(ERR_STATE_STI_LOW | ERR_STI_UNEXPECTED_HANDLE, handle);
return;
}
if (s->step_callback) {
s->step_callback(s);
}
}
static void headstage_sti_single_callback(NeuLiveStiChannelState *s) {
if (s->times == 0) {
headstage_gptimer_stop(s->perd_handle);
flag_notify(EVT_STI_TERM);
return;
}
if (!infinite_times(s)) {
s->times--;
}
} else if (!infinite_times(s)) {
s->times--;
}
uint8_t pol = s->pol;
uint8_t pon = s->pon;
@@ -1034,149 +1014,97 @@ static void headstage_sti_gptimer_single_channel_callback(GPTimerCC26XX_Handle h
Hwi_restore(__key);
}
static void headstage_sti_gptimer_perd_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
NeuLiveStiChannelState *s = INSTRUCTION.state;
if (handle == gptimer_handle_p0) {
s += CHANNEL_STI_0;
} else if (handle == gptimer_handle_p1) {
s += CHANNEL_STI_1;
} else {
headstage_set_error(ERR_STATE_STI_PERD | ERR_STI_UNEXPECTED_HANDLE, handle);
return;
}
static void headstage_sti_period_callback(NeuLiveStiChannelState *s) {
if (s->times == 0) {
headstage_gptimer_stop(handle);
headstage_gptimer_stop(s->perd_handle);
flag_notify(EVT_STI_TERM);
return;
}
if (!infinite_times(s)) {
} else if (!infinite_times(s)) {
s->times--;
}
uint8 __key = Hwi_disable();
// stage 0
uint16_t timeout_us = s->timeout_us[0];
headstage_sti_output_pol(s, 0);
headstage_sti_output_pon(s, 0);
if (s->timeout_us[0] <= LIMIT_TIMEOUT_US) {
if (timeout_us <= LIMIT_TIMEOUT_US) {
// use cpu delay instead
headstage_spin_delay(get_spin_timeout_value(s->timeout_us[0] - 6));
headstage_spin_delay(get_spin_timeout_value(timeout_us - 2));
} else {
s->stage = 0;
headstage_gptimer_start(s->handle[0]);
return;
headstage_gptimer_set_timeout(s->step_handle, timeout_us);
headstage_gptimer_start(s->step_handle);
goto exit;
}
// stage 1
timeout_us = s->timeout_us[1];
headstage_sti_output_pol(s, 1);
headstage_sti_output_pon(s, 1);
if (s->stage_limit <= 1) {
return;
} else if (s->timeout_us[1] <= LIMIT_TIMEOUT_US) {
if (s->mode == STI_WAVEFORM_POS || s->mode == STI_WAVEFORM_NEG) {
goto exit;
} else if (timeout_us <= LIMIT_TIMEOUT_US) {
// use cpu delay instead
headstage_spin_delay(get_spin_timeout_value(s->timeout_us[1] - 6));
headstage_spin_delay(get_spin_timeout_value(timeout_us - 1));
} else {
s->stage = 1;
headstage_gptimer_start(s->handle[1]);
return;
headstage_gptimer_set_timeout(s->step_handle, timeout_us);
headstage_gptimer_start(s->step_handle);
goto exit;
}
// stage 2
timeout_us = s->timeout_us[2];
headstage_sti_output_pol(s, 2);
headstage_sti_output_pon(s, 2);
if (s->stage_limit <= 2) {
return;
} else if ( s->timeout_us[2] <= LIMIT_TIMEOUT_US) {
if (s->mode == STI_WAVEFORM_P2N || s->mode == STI_WAVEFORM_N2P) {
goto exit;
} else if (timeout_us <= LIMIT_TIMEOUT_US) {
// use cpu delay instead
headstage_spin_delay(get_spin_timeout_value( s->timeout_us[2] - 6));
headstage_spin_delay(get_spin_timeout_value(timeout_us - 2));
} else {
s->stage = 2;
headstage_gptimer_start(s->handle[2]);
return;
headstage_gptimer_set_timeout(s->step_handle, timeout_us);
headstage_gptimer_start(s->step_handle);
goto exit;
}
// stage 3
headstage_sti_output_pol(s, 3);
headstage_sti_output_pon(s, 3);
return;
exit:
Hwi_restore(__key);
}
static void headstage_sti_gptimer_step_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
NeuLiveStiChannelState *s = INSTRUCTION.state;
static void headstage_sti_stepping_callback(NeuLiveStiChannelState *s) {
uint8_t stage = ++ (s->stage);
if (handle == gptimer_handle_s0 || handle == gptimer_handle_i0) {
s += CHANNEL_STI_0;
} else if (handle == gptimer_handle_s1 || handle == gptimer_handle_i1) {
s += CHANNEL_STI_1;
} else {
headstage_set_error(ERR_STATE_STI_STEP | ERR_STI_UNEXPECTED_HANDLE, handle);
return;
}
headstage_sti_output_pol(s, stage);
headstage_sti_output_pon(s, stage);
s->stage++;
uint16_t timeout_us = s->timeout_us[stage];
switch(s->stage) {
case 1:
headstage_sti_output_pol(s, 1);
headstage_sti_output_pon(s, 1);
while (stage < 3 && timeout_us != 0) {
if (timeout_us <= LIMIT_TIMEOUT_US) {
// use cpu delay instead
headstage_spin_delay(get_spin_timeout_value(timeout_us - 2));
if ( s->stage_limit <= 1) {
return;
} else if (s->timeout_us[1] <= LIMIT_TIMEOUT_US) {
// use cpu delay instead
headstage_spin_delay(get_spin_timeout_value(s->timeout_us[1] - 6));
} else {
headstage_gptimer_start(s->handle[1]);
return;
}
s->stage++;
case 2:
headstage_sti_output_pol(s, 2);
headstage_sti_output_pon(s, 2);
if (s->stage_limit <= 2) {
return;
} else if (s->timeout_us[2] <= LIMIT_TIMEOUT_US) {
// use cpu delay instead
headstage_spin_delay(get_spin_timeout_value(s->timeout_us[2] - 6));
} else {
headstage_gptimer_start(s->handle[2]);
return;
}
case 3:
headstage_sti_output_pol(s, 3);
headstage_sti_output_pon(s, 3);
}
}
static void headstage_sti_gptimer_low_freq_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask) {
NeuLiveStiChannelState *s = INSTRUCTION.state;
if (handle == gptimer_handle_p0) {
s += CHANNEL_STI_0;
} else if (handle == gptimer_handle_p1) {
s += CHANNEL_STI_1;
} else {
headstage_set_error(ERR_STATE_STI_LOW | ERR_STI_UNEXPECTED_HANDLE, handle);
return;
}
if (s->low_freq_counter == 0) {
s->low_freq_counter = 10;
if (s->perd_callback) {
s->perd_callback(handle, interruptMask);
stage = ++ (s->stage);
headstage_sti_output_pol(s, stage);
headstage_sti_output_pon(s, stage);
timeout_us = s->timeout_us[stage];
} else {
headstage_gptimer_set_timeout(s->step_handle, timeout_us);
headstage_gptimer_start(s->step_handle);
return;
}
} else {
s->low_freq_counter--;
}
}
@@ -12,8 +12,9 @@ static GPTimerCC26XX_Handle gptimer_handle_p0;
static GPTimerCC26XX_Handle gptimer_handle_p1;
static GPTimerCC26XX_Handle gptimer_handle_s0;
static GPTimerCC26XX_Handle gptimer_handle_s1;
static GPTimerCC26XX_Handle gptimer_handle_i0;
static GPTimerCC26XX_Handle gptimer_handle_i1;
static void headstage_sti_gptimer_main_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
static void headstage_sti_gptimer_step_callback(GPTimerCC26XX_Handle handle, GPTimerCC26XX_IntMask interruptMask);
#define headstage_gptimer_start(gptimer_handle) GPTimerCC26XX_start(gptimer_handle)
#define headstage_gptimer_stop(gptimer_handle) GPTimerCC26XX_stop(gptimer_handle)
@@ -39,8 +40,10 @@ static void headstage_gptimer_open() {
gptimer_handle_s0 = GPTimerCC26XX_open(Board_GPTIMER1A, &params);
gptimer_handle_s1 = GPTimerCC26XX_open(Board_GPTIMER1B, &params);
gptimer_handle_i0 = GPTimerCC26XX_open(Board_GPTIMER2A, &params);
gptimer_handle_i1 = GPTimerCC26XX_open(Board_GPTIMER2B, &params);
GPTimerCC26XX_registerInterrupt(gptimer_handle_p0, headstage_sti_gptimer_main_callback, GPT_INT_TIMEOUT);
GPTimerCC26XX_registerInterrupt(gptimer_handle_p1, headstage_sti_gptimer_main_callback, GPT_INT_TIMEOUT);
GPTimerCC26XX_registerInterrupt(gptimer_handle_s0, headstage_sti_gptimer_step_callback, GPT_INT_TIMEOUT);
GPTimerCC26XX_registerInterrupt(gptimer_handle_s1, headstage_sti_gptimer_step_callback, GPT_INT_TIMEOUT);
}
#define headstage_gptimer_set_load_value(gptimer_handle, load_value) GPTimerCC26XX_setLoadValue(gptimer_handle, load_value)