/// \method read() /// Read the value on the analog pin and return it. The returned value /// will be between 0 and 4095. STATIC mp_obj_t adc_read(mp_obj_t self_in) { pyb_obj_adc_t *self = self_in; adc_config_channel(&self->handle, self->channel); uint32_t data = adc_read_channel(&self->handle); return mp_obj_new_int(data); }
int board_get_version(void) { static int version = BOARD_VERSION_UNKNOWN; int mv, i; if (version != BOARD_VERSION_UNKNOWN) return version; /* FIXME(dhendrix): enable ADC */ gpio_set_flags(GPIO_EC_BRD_ID_EN_ODL, GPIO_ODR_HIGH); gpio_set_level(GPIO_EC_BRD_ID_EN_ODL, 0); /* Wait to allow cap charge */ msleep(1); mv = adc_read_channel(ADC_BOARD_ID); /* FIXME(dhendrix): disable ADC */ gpio_set_level(GPIO_EC_BRD_ID_EN_ODL, 1); gpio_set_flags(GPIO_EC_BRD_ID_EN_ODL, GPIO_INPUT); if (mv == ADC_READ_ERROR) { version = BOARD_VERSION_UNKNOWN; return version; } for (i = 0; i < BOARD_VERSION_COUNT; i++) { if (mv < reef_board_versions[i].thresh_mv) { version = reef_board_versions[i].version; break; } } CPRINTS("Board version: %d\n", version); return version; }
/// \method read_timed(buf, freq) /// Read analog values into the given buffer at the given frequency. Buffer /// can be bytearray or array.array for example. If a buffer with 8-bit elements /// is used, sample resolution will be reduced to 8 bits. /// /// Example: /// /// adc = pyb.ADC(pyb.Pin.board.X19) # create an ADC on pin X19 /// buf = bytearray(100) # create a buffer of 100 bytes /// adc.read_timed(buf, 10) # read analog values into buf at 10Hz /// # this will take 10 seconds to finish /// for val in buf: # loop over all values /// print(val) # print the value out /// /// This function does not allocate any memory. STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) { pyb_obj_adc_t *self = self_in; mp_buffer_info_t bufinfo; mp_get_buffer_raise(buf_in, &bufinfo, MP_BUFFER_WRITE); int typesize = mp_binary_get_size('@', bufinfo.typecode, NULL); // Init TIM6 at the required frequency (in Hz) timer_tim6_init(mp_obj_get_int(freq_in)); // Start timer HAL_TIM_Base_Start(&TIM6_Handle); // This uses the timer in polling mode to do the sampling // We could use DMA, but then we can't convert the values correctly for the buffer adc_config_channel(self); for (uint index = 0; index < bufinfo.len; index++) { // Wait for the timer to trigger while (__HAL_TIM_GET_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE) == RESET) { } __HAL_TIM_CLEAR_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE); uint value = adc_read_channel(&self->handle); if (typesize == 1) { value >>= 4; } mp_binary_set_val_array_from_int(bufinfo.typecode, bufinfo.buf, index, value); }
int pd_snk_is_vbus_provided(int port) { int mv = adc_read_channel(port == USBPD_PORT_A ? ADC_VBUSSA : ADC_VBUSSB); /* level shift voltage of VBUS > threshold */ return (mv * 23 / 3) > PD_VBUS_PROVIDED_THRESHOLD; }
/** * Physical check of battery presence. */ enum battery_present battery_is_present(void) { /* * This pin has a pullup, so if it's not completely pegged there's * something attached. Probably a battery. */ int analog_val = adc_read_channel(ADC_CH_BAT_TEMP); return analog_val < (9 * ADC_READ_MAX / 10) ? BP_YES : BP_NO; }
static mp_obj_t adc_read(mp_obj_t self_in) { pyb_obj_adc_t *self = self_in; if (self->is_enabled) { uint32_t data = adc_read_channel(self->channel); return mp_obj_new_int(data); } else { return mp_const_none; } }
int adc_read_all_channels(int *data) { int index; for (index = 0; index < ADC_CH_COUNT; index++) { data[index] = adc_read_channel(index); if (data[index] == ADC_READ_ERROR) return EC_ERROR_UNKNOWN; } return EC_SUCCESS; }
static mp_obj_t adc_all_read_channel(mp_obj_t self_in, mp_obj_t channel) { pyb_obj_adc_all_t *self = self_in; if (self->is_enabled) { uint32_t chan = mp_obj_get_int(channel); uint32_t data = adc_read_channel(chan); return mp_obj_new_int(data); } else { return mp_const_none; } }
int board_get_ambient_temp(int idx, int *temp_ptr) { int mv = adc_read_channel(NPCX_ADC_CH1); if (mv < 0) return -1; *temp_ptr = thermistor_linear_interpolate(mv, &amb_thermistor_info); *temp_ptr = C_TO_K(*temp_ptr); return 0; }
int adc_read_all_channels(int *data) { int i; for (i = 0; i < ADC_CH_COUNT; ++i) { data[i] = adc_read_channel(i); if (data[i] == ADC_READ_ERROR) return EC_ERROR_UNKNOWN; } return EC_SUCCESS; }
__attribute__((weak)) int adc_read_all_channels(int *data) { int i; int rv = EC_SUCCESS; for (i = 0; i < ADC_CH_COUNT; ++i) { data[i] = adc_read_channel(i); if (data[i] == ADC_READ_ERROR) rv = EC_ERROR_UNKNOWN; } return rv; }
STATIC uint32_t adc_config_and_read_channel(ADC_HandleTypeDef *adcHandle, uint32_t channel) { adc_config_channel(adcHandle, channel); uint32_t raw_value = adc_read_channel(adcHandle); #if defined(STM32F4) || defined(STM32F7) // ST docs say that (at least on STM32F42x and STM32F43x), VBATE must // be disabled when TSVREFE is enabled for TEMPSENSOR and VREFINT // conversions to work. VBATE is enabled by the above call to read // the channel, and here we disable VBATE so a subsequent call for // TEMPSENSOR or VREFINT works correctly. if (channel == ADC_CHANNEL_VBAT) { ADC->CCR &= ~ADC_CCR_VBATE; } #endif return raw_value; }
static void chip_temp_sensor_poll(void) { #ifdef CONFIG_CMD_ECTEMP last_val = adc_read_channel(ADC_CH_EC_TEMP); #endif }
/** * Fills passed power_info structure with current info about the passed port. */ static void charge_manager_fill_power_info(int port, struct ec_response_usb_pd_power_info *r) { int sup = CHARGE_SUPPLIER_NONE; int i; /* Determine supplier information to show. */ if (port == charge_port) sup = charge_supplier; else /* Find highest priority supplier */ for (i = 0; i < CHARGE_SUPPLIER_COUNT; ++i) if (available_charge[i][port].current > 0 && available_charge[i][port].voltage > 0 && (sup == CHARGE_SUPPLIER_NONE || supplier_priority[i] < supplier_priority[sup] || (supplier_priority[i] == supplier_priority[sup] && POWER(available_charge[i][port]) > POWER(available_charge[sup] [port])))) sup = i; /* Fill in power role */ if (charge_port == port) r->role = USB_PD_PORT_POWER_SINK; else if (pd_is_connected(port) && pd_get_role(port) == PD_ROLE_SOURCE) r->role = USB_PD_PORT_POWER_SOURCE; else if (sup != CHARGE_SUPPLIER_NONE) r->role = USB_PD_PORT_POWER_SINK_NOT_CHARGING; else r->role = USB_PD_PORT_POWER_DISCONNECTED; /* Is port partner dual-role capable */ r->dualrole = (dualrole_capability[port] == CAP_DUALROLE); if (sup == CHARGE_SUPPLIER_NONE || r->role == USB_PD_PORT_POWER_SOURCE) { r->type = USB_CHG_TYPE_NONE; r->meas.voltage_max = 0; r->meas.voltage_now = r->role == USB_PD_PORT_POWER_SOURCE ? 5000 : 0; r->meas.current_max = 0; r->max_power = 0; } else { #if defined(HAS_TASK_CHG_RAMP) || defined(CONFIG_CHARGE_RAMP_HW) /* Read ramped current if active charging port */ int use_ramp_current = (charge_port == port); #else const int use_ramp_current = 0; #endif switch (sup) { case CHARGE_SUPPLIER_PD: r->type = USB_CHG_TYPE_PD; break; case CHARGE_SUPPLIER_TYPEC: r->type = USB_CHG_TYPE_C; break; case CHARGE_SUPPLIER_PROPRIETARY: r->type = USB_CHG_TYPE_PROPRIETARY; break; case CHARGE_SUPPLIER_BC12_DCP: r->type = USB_CHG_TYPE_BC12_DCP; break; case CHARGE_SUPPLIER_BC12_CDP: r->type = USB_CHG_TYPE_BC12_CDP; break; case CHARGE_SUPPLIER_BC12_SDP: r->type = USB_CHG_TYPE_BC12_SDP; break; case CHARGE_SUPPLIER_VBUS: r->type = USB_CHG_TYPE_VBUS; break; default: r->type = USB_CHG_TYPE_OTHER; } r->meas.voltage_max = available_charge[sup][port].voltage; if (use_ramp_current) { /* * If charge_ramp has not detected charger yet, * then charger type is unknown. */ if (!chg_ramp_is_detected()) r->type = USB_CHG_TYPE_UNKNOWN; /* Current limit is output of ramp module */ r->meas.current_lim = chg_ramp_get_current_limit(); /* * If ramp is allowed, then the max current depends * on if ramp is stable. If ramp is stable, then * max current is same as input current limit. If * ramp is not stable, then we report the maximum * current we could ramp up to for this supplier. * If ramp is not allowed, max current is just the * available charge current. */ if (board_is_ramp_allowed(sup)) { r->meas.current_max = chg_ramp_is_stable() ? r->meas.current_lim : board_get_ramp_current_limit( sup, available_charge[sup][port].current); } else { r->meas.current_max = available_charge[sup][port].current; } r->max_power = r->meas.current_max * r->meas.voltage_max; } else { r->meas.current_max = r->meas.current_lim = available_charge[sup][port].current; r->max_power = POWER(available_charge[sup][port]); } /* * If we are sourcing power, or sinking but not charging, then * VBUS must be 5V. If we are charging, then read VBUS ADC. */ if (r->role == USB_PD_PORT_POWER_SINK_NOT_CHARGING) r->meas.voltage_now = 5000; else if (ADC_VBUS >= 0) r->meas.voltage_now = adc_read_channel(ADC_VBUS); else /* No VBUS ADC channel - voltage is unknown */ r->meas.voltage_now = 0; } }
int pd_board_checks(void) { #ifdef CONFIG_HIBERNATE static timestamp_t hib_to; static int hib_to_ready; #endif int vbus_volt; int ovp_idx; /* Reload the watchdog */ STM32_IWDG_KR = STM32_IWDG_KR_RELOAD; #ifdef CONFIG_HIBERNATE /* If output is disabled for long enough, then hibernate */ if (!pd_is_connected(0) && hib_to_ready) { if (get_time().val >= hib_to.val) { debug_printf("hib\n"); __enter_hibernate(0, 0); } } else { hib_to.val = get_time().val + 60*SECOND; hib_to_ready = 1; } #endif /* if it's been a while since last RX edge, then allow deep sleep */ if (get_time_since_last_edge(0) > PD_RX_SLEEP_TIMEOUT) enable_sleep(SLEEP_MASK_USB_PD); vbus_volt = adc_read_channel(ADC_CH_V_SENSE); vbus_amp = adc_read_channel(ADC_CH_A_SENSE); if (fault == FAULT_FAST_OCP) { debug_printf("Fast OCP\n"); pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_FAST_OCP, NULL); fault = FAULT_OCP; /* reset over-current after 1 second */ fault_deadline.val = get_time().val + OCP_TIMEOUT; return EC_ERROR_INVAL; } if (vbus_amp > MAX_CURRENT) { /* 3 more samples to check whether this is just a transient */ int count; for (count = 0; count < 3; count++) if (adc_read_channel(ADC_CH_A_SENSE) < MAX_CURRENT) break; /* trigger the slow OCP iff all 4 samples are above the max */ if (count == 3) { debug_printf("OCP %d mA\n", vbus_amp * VDDA_MV / CURR_GAIN * 1000 / R_SENSE / ADC_SCALE); pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_OCP, NULL); fault = FAULT_OCP; /* reset over-current after 1 second */ fault_deadline.val = get_time().val + OCP_TIMEOUT; return EC_ERROR_INVAL; } } /* * Optimize power consumption when the sink is idle : * Enable STOP mode while we are connected, * this kills fast OCP as the actual ADC conversion for the analog * watchdog will happen on the next wake-up (x0 ms latency). */ if (vbus_amp < SINK_IDLE_CURRENT && !discharge_is_enabled()) /* override the PD state machine sleep mask */ enable_sleep(SLEEP_MASK_USB_PWR); else if (vbus_amp > SINK_IDLE_CURRENT) disable_sleep(SLEEP_MASK_USB_PWR); /* * Set the voltage index to use for checking OVP. During a down step * transition, use the previous voltage index to check for OVP. */ ovp_idx = discharge_is_enabled() ? last_volt_idx : volt_idx; if ((output_is_enabled() && (vbus_volt > voltages[ovp_idx].ovp)) || (fault && (vbus_volt > voltages[ovp_idx].ovp_rec))) { if (!fault) { debug_printf("OVP %d mV\n", ADC_TO_VOLT_MV(vbus_volt)); pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_OVP, NULL); } fault = FAULT_OVP; /* no timeout */ fault_deadline.val = get_time().val; return EC_ERROR_INVAL; } /* the discharge did not work properly */ if (discharge_is_enabled() && (get_time().val > discharge_deadline.val)) { /* ensure we always finish a 2-step discharge */ volt_idx = discharge_volt_idx; set_output_voltage(voltages[volt_idx].select); /* stop it */ discharge_disable(); /* enable over-current monitoring */ adc_enable_watchdog(ADC_CH_A_SENSE, MAX_CURRENT_FAST, 0); debug_printf("Disch FAIL %d mV\n", ADC_TO_VOLT_MV(vbus_volt)); pd_log_event(PD_EVENT_PS_FAULT, 0, PS_FAULT_DISCH, NULL); fault = FAULT_DISCHARGE; /* reset it after 1 second */ fault_deadline.val = get_time().val + OCP_TIMEOUT; return EC_ERROR_INVAL; } /* everything is good *and* the error condition has expired */ if ((fault != FAULT_OK) && (get_time().val > fault_deadline.val)) { fault = FAULT_OK; debug_printf("Reset fault\n"); /* * Reset the PD state and communication on both side, * so we can now re-negociate a voltage. */ return EC_ERROR_INVAL; } return EC_SUCCESS; }
static int command_ectemp(int argc, char **argv) { int t = adc_read_channel(ADC_CH_EC_TEMP); ccprintf("EC temperature is %d K = %d C\n", t, K_TO_C(t)); return EC_SUCCESS; }