Skip to content

Commit

Permalink
ports/psoc6: Fix ADC and enable hw test.
Browse files Browse the repository at this point in the history
Signed-off-by: NikhitaR-IFX <Nikhita.Rajasekhar@infineon.com>
  • Loading branch information
NikhitaR-IFX committed Mar 6, 2024
1 parent 65978eb commit 75c31de
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 39 deletions.
2 changes: 1 addition & 1 deletion docs/psoc6/feature_list.rst
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ Table :ref:`configuration details <table_mpy_configuration>` below lists specifi
| | |
| | Constants not yet implemented : *WLAN_WAKE*, *PIN_WAKE*, *RTC_WAKE*, *IDLE*, *SLEEP*, *DEEPSLEEP*. |
| | |
| | Submodules/classes not yet implemented: *ADC*, *bitstream*, *mem*, *Signal*, *SD*, *SDCard*, *SoftSPI*, *SPI*, |
| | Submodules/classes not yet implemented: *bitstream*, *mem*, *Signal*, *SD*, *SDCard*, *SoftSPI*, *SPI*, |
| | *Timer*, *UART*, *WDT*. |
+-----------------+----------------------------------------------------------------------------------------------------------------------+
| machine.Pin | Functions not yet implemented: *drive()*, *mode()*, *pull()*. |
Expand Down
13 changes: 8 additions & 5 deletions docs/psoc6/quickref.rst
Original file line number Diff line number Diff line change
Expand Up @@ -619,10 +619,6 @@ PSoC6 supports only 1 12-bit SAR ADC with the following channel to pin mapping a

..
TODO: This is only applicable to the CY8CPROTO-062-4343W. This does not belong here.
TODO: Define approach on how the user gets to know the pinout diagram, alternate function of each board
- From board manual?
- From datasheet?
- To create a pinout diagram?
.. note::
Arbitrary connection of ADC channels to GPIO is not supported. Specifying a pin that is not connected to this block,
Expand All @@ -633,10 +629,17 @@ To use the APIs:
from machine import ADCBlock

adcBlock = ADCBlock(0, bits=12) # create an ADCBlock 0 object
adcBlock = ADCBlock(0, bits=11) # create an ADCBlock 0 object
adc = adcBlock.connect(0, "P10_0") # connect channel 0 to pin P10_0
val = adc.read_uv() # read an analog value in micro volts

.. note::
The ADC block supports only 11 bits resolution. If bits are not passed, by default 11 bits is considered.

.. warning::
When the input to ADC pin is connected to GND, it may not return value 0 as digitized output. This is a known issue and
needs fix in low-level API's.

I2S bus
-------

Expand Down
9 changes: 4 additions & 5 deletions ports/psoc6/machine_adc.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,10 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_block_obj, machine_adc_block);
// read_u16()
STATIC mp_obj_t machine_adc_read_u16(mp_obj_t self_in) {
machine_adc_obj_t *self = MP_OBJ_TO_PTR(self_in);
return MP_OBJ_NEW_SMALL_INT(cyhal_adc_read(&(self->adc_chan_obj)));
// !ToDo:This currently return value scaled from 0-2047, while it should be 0-4096.
// Acc to MPY Docs, this should be mapped to range of 0-65535 (using taylow series?) as below.
// mp_int_t bits = (mp_int_t)adc_get_resolution(self);
// mp_uint_t u16 = adc_raw_result << (16 - bits) | adc_raw_result >> (2 * bits - 16);
int32_t adc_raw_result = cyhal_adc_read(&(self->adc_chan_obj));
mp_int_t bits = (mp_int_t)adc_get_resolution(self);
mp_uint_t u16 = adc_raw_result << (16 - bits);
return MP_OBJ_NEW_SMALL_INT(u16);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_adc_read_u16_obj, machine_adc_read_u16);

Expand Down
4 changes: 2 additions & 2 deletions ports/psoc6/machine_adcblock.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ STATIC mp_obj_t machine_adcblock_make_new(const mp_obj_type_t *type, size_t n_po
mp_arg_parse_all(n_pos_args - 1, all_args + 1, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
uint8_t bits = args[ARG_bits].u_int;
if (bits != DEFAULT_ADC_BITS) {
mp_raise_TypeError(MP_ERROR_TEXT("Invalid bits. Current ADC configuration supports only 12 bits resolution!"));
mp_raise_TypeError(MP_ERROR_TEXT("Invalid bits. Current ADC configuration supports only 11 bits resolution!"));
}

return MP_OBJ_FROM_PTR(machine_adcblock_make_init(adc_id, bits));
Expand Down Expand Up @@ -299,7 +299,7 @@ STATIC mp_obj_t machine_adcblock_connect(size_t n_pos_args, const mp_obj_t *pos_
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(machine_adcblock_connect_obj, 2, machine_adcblock_connect);

STATIC const mp_rom_map_elem_t machine_adcblock_locals_dict_table[] = {
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adcblock_deinit_obj) },
{ MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_adcblock_deinit_obj)},
{ MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&machine_adcblock_connect_obj) },
};
STATIC MP_DEFINE_CONST_DICT(machine_adcblock_locals_dict, machine_adcblock_locals_dict_table);
Expand Down
122 changes: 100 additions & 22 deletions tests/psoc6/hw_ext/adc.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,110 @@
### ADC Functional test
""" Setup description:
Connect 3.3V input to adc_pin0 and 0V input to adc_pin1. With the setup done, run the test.
*Known issue: The max output voltage currently is ~2.3V for 3.3V input.
Construct a basic voltage divider with 120 ohms each resistor. Supply the ends with 3.3V and GND.
Available voltage values are then - 3.3V, ~1.7V, 0V.
Pin connections:
Voltage Divider circuit On Target Board
3.3V end adc_pin_max
Mid point adc_pin_mid
GND end adc_pin_gnd
*Known issue: When connected to GND, you may not get exact 0V and this may vary board to board.
"""
import os
import time
from machine import PWM, ADC
from machine import ADC, ADCBlock

# Allocate pin based on board
machine = os.uname().machine
if "CY8CPROTO-062-4343W" in machine:
adc_pin0 = "P10_0"
adc_pin1 = "P10_1"
# TODO: Refactor test for more functionality coverage
print("SKIP")
raise SystemExit
adc_pin_gnd = "P10_1"
adc_pin_mid = "P10_3"
adc_pin_max = "P10_0"
adc_wrong_pin_name = "P13_7"
elif "CY8CPROTO-063-BLE" in machine:
adc_pin0 = "P10_0"
adc_pin1 = "P10_1"
# TODO: Refactor test for more functionality coverage
print("SKIP")
raise SystemExit

adc0 = ADC(adc_pin0, sample_ns=1000)
adc1 = ADC(adc_pin1, sample_ns=1000)

print("Voltage (in microvolts) on pin", adc_pin0, "is max: ", adc0.read_uv() > 1000000)
print("Voltage (raw count) on pin", adc_pin0, "is max: ", adc0.read_u16() > 500)
print("Voltage (in microvolts) on pin", adc_pin1, "is max: ", adc1.read_uv() < 1000000)
print("Voltage (raw count) on pin", adc_pin1, "is max: ", adc1.read_u16() < 500)
adc_pin_gnd = "P10_1"
adc_pin_mid = "P10_3"
adc_pin_max = "P10_0"
adc_wrong_pin_name = "P13_7"

# 0.35V
tolerance_uv = 350000

tolerance_raw = 4000

block = None


def validate_adc_uv_value(adc_pin, exp_volt, act_volt):
print(
"\nExpected voltage - ",
exp_volt,
"(uV) on pin ",
adc_pin,
"is approx same as obtained voltage(uV): ",
(exp_volt - tolerance_uv) < act_volt < (exp_volt + tolerance_uv),
)


def validate_adc_raw_value(adc_pin, exp_volt, act_volt):
print(
"\nExpected voltage - ",
exp_volt,
"(raw) on pin ",
adc_pin,
"is approx same as obtained voltage(raw): ",
(exp_volt - tolerance_raw) < act_volt < (exp_volt + tolerance_raw),
)


# Exception should be raised
try:
adc = ADC(adc_wrong_pin_name)
except:
print("Invalid ADC Pin\n")

adc0 = ADC(adc_pin_gnd, sample_ns=1000)
print(adc0)

block = ADCBlock(0, bits=12)
# ADCBlock.connect(channel)
adc1 = block.connect(3)
print("\nADCBlock.connect(channel): ", adc1)
block.deinit()
print("ADCBlock.deinit(): ", block)

# ADCBlock.connect(source)
block = ADCBlock(0, bits=12)
adc1 = block.connect(adc_pin_mid)
print("ADCBlock.connect(source): ", adc1)
block.deinit()
print("ADCBlock.deinit(): ", block)

# ADCBlock.connect(channel,source)
block = ADCBlock(0, bits=12)
adc1 = block.connect(3, adc_pin_mid)
print("ADCBlock.connect(channel,source)", adc1)

adc2 = ADC(adc_pin_max, sample_ns=1000)
print("\n", adc2)

adc0_value_uv = adc0.read_uv()
validate_adc_uv_value(adc_pin_gnd, 0, adc0_value_uv)
adc0_value_raw = adc0.read_u16()
validate_adc_raw_value(adc_pin_gnd, 0, adc0_value_raw)

adc1_value_uv = adc1.read_uv()
validate_adc_uv_value(adc_pin_mid, 1650000, adc1_value_uv)
adc1_value_raw = adc1.read_u16()
validate_adc_raw_value(adc_pin_mid, 16385, adc1_value_raw)

adc2_value_uv = adc2.read_uv()
validate_adc_uv_value(adc_pin_max, 3300000, adc2_value_uv)
adc2_value_raw = adc2.read_u16()
validate_adc_raw_value(adc_pin_max, 32767, adc2_value_raw)

adc0.deinit()
print("\n", adc0)
adc1.deinit()
print(adc1)
adc2.deinit()
print(adc2)
31 changes: 27 additions & 4 deletions tests/psoc6/hw_ext/adc.py.exp
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
Voltage (in microvolts) on pin P10_0 is max: True
Voltage (raw count) on pin P10_0 is max: True
Voltage (in microvolts) on pin P10_1 is max: True
Voltage (raw count) on pin P10_1 is max: True
Invalid ADC Pin

<ADC Pin=81, ADCBlock_id=0, sampling_time_ns=1000>

ADCBlock.connect(channel): <ADC Pin=83, ADCBlock_id=0, sampling_time_ns=1000>
ADCBlock.deinit(): ADCBlock(0, bits=12)
ADCBlock.connect(source): <ADC Pin=83, ADCBlock_id=0, sampling_time_ns=1000>
ADCBlock.deinit(): ADCBlock(0, bits=12)
ADCBlock.connect(channel,source) <ADC Pin=83, ADCBlock_id=0, sampling_time_ns=1000>

<ADC Pin=80, ADCBlock_id=0, sampling_time_ns=1000>

Expected voltage - 0 (uV) on pin P10_1 is approx same as obtained voltage(uV): True

Expected voltage - 0 (raw) on pin P10_1 is approx same as obtained voltage(raw): True

Expected voltage - 1650000 (uV) on pin P10_3 is approx same as obtained voltage(uV): True

Expected voltage - 16385 (raw) on pin P10_3 is approx same as obtained voltage(raw): True

Expected voltage - 3300000 (uV) on pin P10_0 is approx same as obtained voltage(uV): True

Expected voltage - 32767 (raw) on pin P10_0 is approx same as obtained voltage(raw): True

<ADC Pin=81, ADCBlock_id=0, sampling_time_ns=1000>
<ADC Pin=83, ADCBlock_id=0, sampling_time_ns=1000>
<ADC Pin=80, ADCBlock_id=0, sampling_time_ns=1000>

0 comments on commit 75c31de

Please sign in to comment.