Beispiel #1
0
/// \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);
}
Beispiel #2
0
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;
}
Beispiel #3
0
/// \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);
    }
Beispiel #4
0
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;
}
Beispiel #5
0
/**
 * 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;
}
Beispiel #6
0
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;
    }
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
    }
}
Beispiel #9
0
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;
}
Beispiel #10
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
static void chip_temp_sensor_poll(void)
{
#ifdef CONFIG_CMD_ECTEMP
	last_val = adc_read_channel(ADC_CH_EC_TEMP);
#endif
}
Beispiel #14
0
/**
 * 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;
	}
}
Beispiel #15
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;

}
Beispiel #16
0
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;
}