adc^2
Ondřej Hruška 7 years ago
parent ddfbbeeb95
commit 3584830dc5
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 3
      platform/hw_utils.c
  2. 53
      units/adc/_adc_init.c
  3. 4
      units/adc/_adc_internal.h
  4. 26
      units/adc/unit_adc.c

@ -371,7 +371,10 @@ bool solve_timer(uint32_t base_freq, uint32_t required_freq, bool is16bit,
*presc = (uint16_t) wPresc;
if (wPresc * wCount == 0) return false;
if (real_freq != NULL) {
*real_freq = (base_freq / (wPresc * wCount));
}
return true;
}

@ -28,6 +28,30 @@ error_t UADC_preInit(Unit *unit)
return E_SUCCESS;
}
/** Configure frequency */
error_t UADC_SetSampleRate(Unit *unit, uint32_t hertz)
{
struct priv *priv = unit->data;
uint16_t presc;
uint32_t count;
if (!solve_timer(PLAT_APB1_HZ, hertz, true, &presc, &count,
&priv->real_frequency)) {
dbg("Failed to resolve timer params.");
return E_BAD_VALUE;
}
dbg("Frequency error %d ppm, presc %d, count %d",
(int) lrintf(1000000.0f *
((priv->real_frequency - hertz) / (float) hertz)),
(int) presc, (int) count);
LL_TIM_SetPrescaler(priv->TIMx, (uint32_t) (presc - 1));
LL_TIM_SetAutoReload(priv->TIMx, count - 1);
return E_SUCCESS;
}
/** Finalize unit set-up */
error_t UADC_init(Unit *unit)
{
@ -103,19 +127,20 @@ error_t UADC_init(Unit *unit)
// ------------------- CONFIGURE THE TIMER --------------------------
dbg("Setting up TIMER");
{
// Find suitable timer values
uint16_t presc;
uint32_t count;
float real_freq;
if (!solve_timer(PLAT_APB1_HZ, priv->frequency, true, &presc, &count, &real_freq)) {
dbg("Failed to resolve timer params.");
return E_BAD_VALUE;
}
dbg("Frequency error %d ppm, presc %d, count %d",
(int) lrintf(1000000.0f * ((real_freq - priv->frequency) / (float)priv->frequency)), (int) presc, (int) count);
LL_TIM_SetPrescaler(priv->TIMx, (uint32_t) (presc - 1));
LL_TIM_SetAutoReload(priv->TIMx, count - 1);
TRY(UADC_SetSampleRate(unit, priv->frequency));
// // Find suitable timer values
// uint16_t presc;
// uint32_t count;
// float real_freq;
// if (!solve_timer(PLAT_APB1_HZ, priv->frequency, true, &presc, &count, &real_freq)) {
// dbg("Failed to resolve timer params.");
// return E_BAD_VALUE;
// }
// dbg("Frequency error %d ppm, presc %d, count %d",
// (int) lrintf(1000000.0f * ((real_freq - priv->frequency) / (float)priv->frequency)), (int) presc, (int) count);
//
// LL_TIM_SetPrescaler(priv->TIMx, (uint32_t) (presc - 1));
// LL_TIM_SetAutoReload(priv->TIMx, count - 1);
LL_TIM_EnableARRPreload(priv->TIMx);
LL_TIM_EnableUpdateEvent(priv->TIMx);
LL_TIM_SetTriggerOutput(priv->TIMx, LL_TIM_TRGO_UPDATE);
@ -208,8 +233,10 @@ error_t UADC_init(Unit *unit)
irqd_attach(priv->DMA_CHx, UADC_DMA_Handler, unit);
irqd_attach(priv->ADCx, UADC_ADC_EOS_Handler, unit);
dbg("irqs attached");
UADC_SwitchMode(unit, ADC_OPMODE_IDLE);
dbg("ADC done");
return E_SUCCESS;
}

@ -40,6 +40,7 @@ struct priv {
uint16_t averaging_factor; //!< Exponential averaging factor 0-1000
// internal state
float real_frequency;
uint32_t extended_channels_mask; //!< channels bitfield including tsense and vref
float avg_factor_as_float;
ADC_TypeDef *ADCx; //!< The ADC peripheral used
@ -126,4 +127,7 @@ void UADC_StartStream(Unit *unit, TF_ID frame_id);
/** End stream */
void UADC_StopStream(Unit *unit);
/** Configure frequency */
error_t UADC_SetSampleRate(Unit *unit, uint32_t hertz);
#endif //GEX_F072_ADC_INTERNAL_H

@ -15,6 +15,7 @@ enum TplCmd_ {
CMD_READ_SMOOTHED = 1,
CMD_GET_ENABLED_CHANNELS = 10,
CMD_GET_SAMPLE_RATE = 11,
CMD_SETUP_TRIGGER = 20,
CMD_ARM = 21,
@ -25,6 +26,7 @@ enum TplCmd_ {
CMD_STREAM_START = 26,
CMD_STREAM_STOP = 27,
CMD_SET_SMOOTHING_FACTOR = 28,
CMD_SET_SAMPLE_RATE = 29,
};
/** Handle a request message */
@ -33,6 +35,8 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
struct priv *priv = unit->data;
PayloadBuilder pb = pb_start(unit_tmp512, UNIT_TMP_LEN, NULL);
// TODO toggling individual channels - would require DMA re-init and various changes in the usage of the struct
switch (command) {
/**
* Get enabled channels.
@ -47,6 +51,23 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
com_respond_pb(frame_id, MSG_SUCCESS, &pb);
return E_SUCCESS;
case CMD_SET_SAMPLE_RATE:
{
uint32_t freq = pp_u32(pp);
if (freq == 0) return E_BAD_VALUE;
TRY(UADC_SetSampleRate(unit, freq));
}
// Pass through - send back the obtained sample rate
/**
* Read the real used frequency, expressed as float.
* May differ from the configured or requested value due to prescaller limitations.
*/
case CMD_GET_SAMPLE_RATE:
pb_float(&pb, priv->real_frequency);
com_respond_pb(frame_id, MSG_SUCCESS, &pb);
return E_SUCCESS;
/**
* Set smoothing factor 0-1000.
* pld: u16:factor
@ -117,7 +138,7 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
const uint8_t source = pp_u8(pp);
const uint16_t level = pp_u16(pp);
const uint8_t edge = pp_u8(pp);
const uint16_t pretrig = pp_u16(pp); // TODO test pre-trigger ...
const uint16_t pretrig = pp_u16(pp);
const uint32_t count = pp_u32(pp);
const uint16_t holdoff = pp_u16(pp);
const bool auto_rearm = pp_bool(pp);
@ -260,7 +281,6 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
* u32 - sample count (for each channel)
*/
case CMD_BLOCK_CAPTURE:
// TODO test
dbg("> Block cpt");
if (priv->opmode != ADC_OPMODE_ARMED &&
priv->opmode != ADC_OPMODE_REARM_PENDING &&
@ -276,7 +296,6 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
* The stream can be terminated by the stop command.
*/
case CMD_STREAM_START:
// TODO test
dbg("> Stream ON");
if (priv->opmode != ADC_OPMODE_ARMED &&
priv->opmode != ADC_OPMODE_REARM_PENDING &&
@ -289,7 +308,6 @@ static error_t UADC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
* Stop a stream.
*/
case CMD_STREAM_STOP:
// TODO test
dbg("> Stream OFF");
if (priv->opmode != ADC_OPMODE_STREAM) {
com_respond_str(MSG_ERROR, frame_id, "Not streaming");

Loading…
Cancel
Save