|
|
|
@ -11,13 +11,195 @@ |
|
|
|
|
// ------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
enum TplCmd_ { |
|
|
|
|
CMD_DUMMY, |
|
|
|
|
CMD_READ_RAW = 0, |
|
|
|
|
CMD_READ_SMOOTHED = 1, |
|
|
|
|
|
|
|
|
|
CMD_GET_ENABLED_CHANNELS = 10, |
|
|
|
|
|
|
|
|
|
CMD_SETUP_TRIGGER = 20, |
|
|
|
|
CMD_ARM = 21, |
|
|
|
|
CMD_DISARM = 22, |
|
|
|
|
CMD_ABORT = 23, // abort any ongoing capture or stream
|
|
|
|
|
CMD_FORCE_TRIGGER = 24, |
|
|
|
|
CMD_BLOCK_CAPTURE = 25, |
|
|
|
|
CMD_STREAM_START = 26, |
|
|
|
|
CMD_STREAM_STOP = 27, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/** Handle a request message */ |
|
|
|
|
static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp) |
|
|
|
|
{ |
|
|
|
|
struct priv *priv = unit->data; |
|
|
|
|
PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL); |
|
|
|
|
|
|
|
|
|
switch (command) { |
|
|
|
|
case CMD_GET_ENABLED_CHANNELS: |
|
|
|
|
dbg("> Query channels"); |
|
|
|
|
for (uint8_t i = 0; i < 18; i++) { |
|
|
|
|
if (priv->extended_channels_mask & (1 << i)) { |
|
|
|
|
pb_u8(&pb, i); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
com_respond_pb(frame_id, MSG_SUCCESS, &pb); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_READ_RAW: |
|
|
|
|
dbg("> Read raw"); |
|
|
|
|
if(priv->opmode != ADC_OPMODE_IDLE && priv->opmode != ADC_OPMODE_ARMED) { |
|
|
|
|
return E_BUSY; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < 18; i++) { |
|
|
|
|
if (priv->extended_channels_mask & (1 << i)) { |
|
|
|
|
pb_u8(&pb, i); |
|
|
|
|
pb_u16(&pb, priv->last_samples[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
assert_param(pb.ok); |
|
|
|
|
com_respond_pb(frame_id, MSG_SUCCESS, &pb); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_READ_SMOOTHED: |
|
|
|
|
dbg("> Read smoothed"); |
|
|
|
|
if(priv->opmode != ADC_OPMODE_IDLE && priv->opmode != ADC_OPMODE_ARMED) { |
|
|
|
|
return E_BUSY; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < 18; i++) { |
|
|
|
|
if (priv->extended_channels_mask & (1 << i)) { |
|
|
|
|
pb_u8(&pb, i); |
|
|
|
|
pb_float(&pb, priv->averaging_bins[i]); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
assert_param(pb.ok); |
|
|
|
|
com_respond_pb(frame_id, MSG_SUCCESS, &pb); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_SETUP_TRIGGER: |
|
|
|
|
dbg("> Setup trigger"); |
|
|
|
|
if(priv->opmode != ADC_OPMODE_IDLE) return E_BUSY; |
|
|
|
|
{ |
|
|
|
|
uint8_t source = pp_u8(pp); |
|
|
|
|
uint16_t level = pp_u16(pp); |
|
|
|
|
uint8_t edge = pp_u8(pp); |
|
|
|
|
uint16_t pretrig = pp_u16(pp); |
|
|
|
|
uint32_t count = pp_u32(pp); |
|
|
|
|
uint16_t holdoff = pp_u16(pp); |
|
|
|
|
bool auto_rearm = pp_bool(pp); |
|
|
|
|
|
|
|
|
|
if (source > 17) { |
|
|
|
|
com_respond_str(MSG_ERROR, frame_id, "Invalid trig source"); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (0 == (priv->extended_channels_mask & (1 << source))) { |
|
|
|
|
com_respond_str(MSG_ERROR, frame_id, "Channel not enabled"); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (level > 4095) { |
|
|
|
|
com_respond_str(MSG_ERROR, frame_id, "Level out of range (0-4095)"); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (edge == 0 || edge > 3) { |
|
|
|
|
com_respond_str(MSG_ERROR, frame_id, "Bad edge"); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// XXX the max size may be too much
|
|
|
|
|
uint16_t max_pretrig = (priv->dma_buffer_itemcount / priv->nb_channels); |
|
|
|
|
if (pretrig > max_pretrig) { |
|
|
|
|
com_respond_snprintf(frame_id, MSG_ERROR, |
|
|
|
|
"Pretrig too large (max %d)", (int) max_pretrig); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
priv->trigger_source = source; |
|
|
|
|
priv->trig_level = level; |
|
|
|
|
priv->trig_prev_level = priv->last_samples[source]; |
|
|
|
|
priv->trig_edge = edge; |
|
|
|
|
priv->pretrig_len = pretrig; |
|
|
|
|
priv->trig_len = count; |
|
|
|
|
priv->trig_holdoff = holdoff; |
|
|
|
|
priv->auto_rearm = auto_rearm; |
|
|
|
|
} |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_ARM: |
|
|
|
|
dbg("> Arm"); |
|
|
|
|
if(priv->opmode != ADC_OPMODE_IDLE) return E_BUSY; |
|
|
|
|
|
|
|
|
|
if (priv->trig_len == 0) { |
|
|
|
|
com_respond_str(MSG_ERROR, frame_id, "Trigger not configured."); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UADC_SwitchMode(unit, ADC_OPMODE_ARMED); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_DISARM: |
|
|
|
|
dbg("> Disarm"); |
|
|
|
|
if(priv->opmode == ADC_OPMODE_IDLE) { |
|
|
|
|
return E_SUCCESS; // already idle, success - no work to do
|
|
|
|
|
} |
|
|
|
|
// capture in progress
|
|
|
|
|
if(priv->opmode != ADC_OPMODE_ARMED) return E_BUSY; |
|
|
|
|
|
|
|
|
|
UADC_SwitchMode(unit, ADC_OPMODE_IDLE); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_ABORT:; |
|
|
|
|
dbg("> Abort capture"); |
|
|
|
|
enum uadc_opmode old_opmode = priv->opmode; |
|
|
|
|
UADC_SwitchMode(unit, ADC_OPMODE_IDLE); |
|
|
|
|
|
|
|
|
|
if (old_opmode == ADC_OPMODE_FIXCAPT || |
|
|
|
|
old_opmode == ADC_OPMODE_STREAM || |
|
|
|
|
old_opmode == ADC_OPMODE_TRIGD) { |
|
|
|
|
UADC_ReportEndOfStream(unit); |
|
|
|
|
} |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_FORCE_TRIGGER: |
|
|
|
|
dbg("> Force trigger"); |
|
|
|
|
if(priv->opmode == ADC_OPMODE_IDLE) { |
|
|
|
|
com_respond_str(MSG_ERROR, frame_id, "Not armed"); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
if(priv->opmode != ADC_OPMODE_ARMED) return E_BUSY; |
|
|
|
|
|
|
|
|
|
UADC_HandleTrigger(unit, 0b11, PTIM_GetMicrotime()); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_BLOCK_CAPTURE: |
|
|
|
|
dbg("> Block cpt"); |
|
|
|
|
if(priv->opmode != ADC_OPMODE_ARMED && |
|
|
|
|
priv->opmode != ADC_OPMODE_IDLE) return E_BUSY; |
|
|
|
|
|
|
|
|
|
uint32_t count = pp_u32(pp); |
|
|
|
|
|
|
|
|
|
UADC_StartBlockCapture(unit, count, frame_id); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_STREAM_START: |
|
|
|
|
dbg("> Stream ON"); |
|
|
|
|
if(priv->opmode != ADC_OPMODE_ARMED && |
|
|
|
|
priv->opmode != ADC_OPMODE_IDLE) return E_BUSY; |
|
|
|
|
|
|
|
|
|
UADC_StartStream(unit, frame_id); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
case CMD_STREAM_STOP: |
|
|
|
|
dbg("> Stream OFF"); |
|
|
|
|
if(priv->opmode != ADC_OPMODE_STREAM) { |
|
|
|
|
com_respond_str(MSG_ERROR, frame_id, "Not streaming"); |
|
|
|
|
return E_FAILURE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UADC_StopStream(unit); |
|
|
|
|
return E_SUCCESS; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
return E_UNKNOWN_COMMAND; |
|
|
|
|
} |
|
|
|
@ -28,7 +210,7 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P |
|
|
|
|
/** Unit template */ |
|
|
|
|
const UnitDriver UNIT_ADC = { |
|
|
|
|
.name = "ADC", |
|
|
|
|
.description = "Analog inputs", |
|
|
|
|
.description = "Analog/Digital converter", |
|
|
|
|
// Settings
|
|
|
|
|
.preInit = UADC_preInit, |
|
|
|
|
.cfgLoadBinary = UADC_loadBinary, |
|
|
|
|