@@ -32,35 +32,36 @@ typedef struct _iodevices_PUPDevice_obj_t {
3232 uint8_t last_mode ;
3333 // ID of a passive device, if any.
3434 lego_device_type_id_t passive_id ;
35+ // Device port.
36+ pbio_port_t * port ;
3537} iodevices_PUPDevice_obj_t ;
3638
3739/**
3840 * Tests if the given device is a passive device and stores ID.
3941 *
4042 * @param [in] self The PUP device.
41- * @param [in] port_in The port.
4243 * @return True if passive device, false otherwise.
4344 */
44- static bool init_passive_pup_device (iodevices_PUPDevice_obj_t * self , mp_obj_t port_in ) {
45- pb_module_tools_assert_blocking ();
45+ static bool init_passive_pup_device (iodevices_PUPDevice_obj_t * self ) {
4646
47- pbio_port_id_t port_id = pb_type_enum_get_value (port_in , & pb_enum_type_Port );
48-
49- // Get the port instance.
50- pbio_port_t * port ;
51- pb_assert (pbio_port_get_port (port_id , & port ));
47+ // Check for custom devices that follow the Powered Up spec for simple
48+ // switches as touch sensors.
49+ uint32_t value ;
50+ pbio_error_t err = pbio_port_get_analog_value (self -> port , LEGO_DEVICE_TYPE_ID_LPF2_TOUCH , false, & value );
51+ if (err == PBIO_SUCCESS ) {
52+ self -> passive_id = LEGO_DEVICE_TYPE_ID_LPF2_TOUCH ;
53+ return true;
54+ }
5255
56+ // Check for DC motor or light.
5357 lego_device_type_id_t type_id = LEGO_DEVICE_TYPE_ID_ANY_DC_MOTOR ;
5458 pbio_dcmotor_t * dcmotor ;
55- pbio_error_t err = pbio_port_get_dcmotor (port , & type_id , & dcmotor );
56-
59+ err = pbio_port_get_dcmotor (self -> port , & type_id , & dcmotor );
5760 if (err == PBIO_SUCCESS ) {
5861 self -> passive_id = type_id ;
5962 return true;
6063 }
6164 return false;
62-
63- self -> passive_id = type_id ;
6465}
6566
6667// pybricks.iodevices.PUPDevice.__init__
@@ -70,8 +71,14 @@ static mp_obj_t iodevices_PUPDevice_make_new(const mp_obj_type_t *type, size_t n
7071
7172 iodevices_PUPDevice_obj_t * self = mp_obj_malloc (iodevices_PUPDevice_obj_t , type );
7273
74+ pb_module_tools_assert_blocking ();
75+
76+ // Get the port instance.
77+ pbio_port_id_t port_id = pb_type_enum_get_value (port_in , & pb_enum_type_Port );
78+ pb_assert (pbio_port_get_port (port_id , & self -> port ));
79+
7380 // For backwards compatibility, allow class to be used with passive devices.
74- if (init_passive_pup_device (self , port_in )) {
81+ if (init_passive_pup_device (self )) {
7582 return MP_OBJ_FROM_PTR (self );
7683 }
7784
@@ -164,7 +171,16 @@ static mp_obj_t iodevices_PUPDevice_read(size_t n_args, const mp_obj_t *pos_args
164171 iodevices_PUPDevice_obj_t , self ,
165172 PB_ARG_REQUIRED (mode ));
166173
167- // Passive devices don't support reading.
174+ // Allow reading from passive touch sensors as per the Powered Up spec.
175+ // These do not have modes. For this special case, alwyas return a bool,
176+ // even in async mode when other reads would return awaitables.
177+ if (self -> passive_id == LEGO_DEVICE_TYPE_ID_LPF2_TOUCH ) {
178+ uint32_t value ;
179+ pb_assert (pbio_port_get_analog_value (self -> port , self -> passive_id , false, & value ));
180+ return mp_obj_new_bool (value );
181+ }
182+
183+ // Other passive devices don't support reading.
168184 if (self -> passive_id != LEGO_DEVICE_TYPE_ID_LPF2_UNKNOWN_UART ) {
169185 pb_assert (PBIO_ERROR_INVALID_OP );
170186 }
0 commit comments