• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pybricks / pybricks-micropython / 19016791193

02 Nov 2025 06:40PM UTC coverage: 57.167% (-2.6%) from 59.744%
19016791193

Pull #406

github

laurensvalk
bricks/virtualhub: Replace with embedded simulation.

Instead of using the newly introduced simhub alongside the virtualhub, we'll just replace the old one entirely now that it has reached feature parity. We can keep calling it the virtualhub.
Pull Request #406: New virtual hub for more effective debugging

41 of 48 new or added lines in 7 files covered. (85.42%)

414 existing lines in 53 files now uncovered.

4479 of 7835 relevant lines covered (57.17%)

17178392.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pybricks/common/pb_type_device.c
1
// SPDX-License-Identifier: MIT
2
// Copyright (c) 2018-2023 The Pybricks Authors
3

4
#include "py/mpconfig.h"
5

6
#if PYBRICKS_PY_DEVICES
7

8

9
#include <pbio/port_interface.h>
10
#include <pbio/port_lump.h>
11

12
#include <pybricks/common.h>
13
#include <pybricks/pupdevices.h>
14
#include <pybricks/common/pb_type_device.h>
15

16
#include <pybricks/util_pb/pb_error.h>
17

18
#include <py/runtime.h>
19
#include <py/mphal.h>
20

21
/**
22
 * Non-blocking version of powered up data getter. Will raise exception if
23
 * sensor is not already in the right mode.
24
 *
25
 * Object @p self_in must be of pb_type_device_obj_base_t type or equivalent.
26
 *
27
 * @param [in]  sensor      The powered up device.
28
 * @param [in]  mode        Desired mode.
29
 * @return                  Void pointer to data.
30
 */
31
void *pb_type_device_get_data(mp_obj_t self_in, uint8_t mode) {
×
32
    pb_type_device_obj_base_t *sensor = MP_OBJ_TO_PTR(self_in);
×
33
    void *data = NULL;
×
34
    pb_assert(pbio_port_lump_get_data(sensor->lump_dev, mode, &data));
×
35
    return data;
×
36
}
37

38
/**
39
 * Always-blocking version of powered up data getter. Can be used during sensor
40
 * or motor initialization.
41
 *
42
 * Object @p self_in must be of pb_type_device_obj_base_t type or equivalent.
43
 *
44
 * @param [in]  sensor      The powered up device.
45
 * @param [in]  mode        Desired mode.
46
 * @return                  Void pointer to data.
47
 */
48
void *pb_type_device_get_data_blocking(mp_obj_t self_in, uint8_t mode) {
×
49
    pb_type_device_obj_base_t *sensor = MP_OBJ_TO_PTR(self_in);
×
50
    pb_assert(pbio_port_lump_set_mode(sensor->lump_dev, mode));
×
51
    pbio_error_t err;
52
    while ((err = pbio_port_lump_is_ready(sensor->lump_dev)) == PBIO_ERROR_AGAIN) {
×
53
        MICROPY_EVENT_POLL_HOOK
×
54
    }
55
    pb_assert(err);
×
56
    void *data = NULL;
×
57
    pb_assert(pbio_port_lump_get_data(sensor->lump_dev, mode, &data));
×
58
    return data;
×
59
}
60

61
/**
62
 * Tests that a Powered Up device read or write operation has completed.
63
 * For reading, this means that the mode has been set and the first data for
64
 * the mode is ready. For writing, this means that the mode has been set and
65
 * data has been written to the device, including the neccessary delays for
66
 * discarding stale data or the time needed to externally process written data.
67
 *
68
 * See ::pbio_port_lump_is_ready for details.
69
 */
70
static pbio_error_t pb_pup_device_iter_once(pbio_os_state_t *state, mp_obj_t self_in) {
×
71
    pb_type_device_obj_base_t *sensor = MP_OBJ_TO_PTR(self_in);
×
72
    return pbio_port_lump_is_ready(sensor->lump_dev);
×
73
}
74

75
/**
76
 * Implements calling of async sensor methods. This is called when a (constant)
77
 * entry of pb_type_device_method type in a sensor class is called. It is
78
 * responsible for setting the sensor mode and returning an awaitable object.
79
 *
80
 * This is also called in a few places where a simple constant sensor method
81
 * is not sufficient, where additional wrapping code is used to dynamically
82
 * set the mode or return mapping, such as in the multi-purpose PUPDevice, or
83
 * the ColorSensor class variants, where different modes or mappings are needed
84
 * for a single method depending on a keyword argument.
85
 */
86
mp_obj_t pb_type_device_method_call(mp_obj_t self_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
×
87
    assert(mp_obj_is_type(self_in, &pb_type_device_method));
×
88
    pb_type_device_method_obj_t *method = MP_OBJ_TO_PTR(self_in);
×
89
    mp_arg_check_num(n_args, n_kw, 1, 1, false);
×
90

91
    mp_obj_t sensor_in = args[0];
×
92
    pb_type_device_obj_base_t *sensor = MP_OBJ_TO_PTR(sensor_in);
×
93
    pb_assert(pbio_port_lump_set_mode(sensor->lump_dev, method->mode));
×
94

95
    pb_type_async_t config = {
×
96
        .iter_once = pb_pup_device_iter_once,
97
        .parent_obj = sensor_in,
98
        .return_map = method->get_values,
×
99
    };
100
    return pb_type_async_wait_or_await(&config, &sensor->last_awaitable, false);
×
101
}
102

103
/**
104
 * Function-like callable type for async sensor methods. This type is used for
105
 * constant pb_type_device_method_obj_t instances, which store a sensor mode to
106
 * set and a mapping function to create a return object when that data is ready.
107
 */
108
MP_DEFINE_CONST_OBJ_TYPE(
109
    pb_type_device_method, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN,
110
    call, pb_type_device_method_call);
111

112
/**
113
 * Set data for a Powered Up device, such as the brightness of multiple external
114
 * lights on a sensor. Automatically sets the mode if not already set. Returns
115
 * an awaitable object that can be used to wait for the operation to complete.
116
 *
117
 * @param [in]  sensor      The powered up device.
118
 * @param [in]  mode        Desired mode.
119
 * @param [in]  data        Data to set.
120
 * @param [in]  size        Size of data.
121
 * @return                  Awaitable object.
122
 */
123
mp_obj_t pb_type_device_set_data(pb_type_device_obj_base_t *sensor, uint8_t mode, const void *data, uint8_t size) {
×
124
    pb_assert(pbio_port_lump_set_mode_with_data(sensor->lump_dev, mode, data, size));
×
125
    pb_type_async_t config = {
×
126
        .iter_once = pb_pup_device_iter_once,
127
        .parent_obj = MP_OBJ_FROM_PTR(sensor),
128
    };
129
    return pb_type_async_wait_or_await(&config, &sensor->last_awaitable, false);
×
130
}
131

132
void pb_device_set_lego_mode(pbio_port_t *port) {
×
133
    // Set the port mode to LEGO DCM if it is not already set.
134
    pbio_error_t err = pbio_port_set_mode(port, PBIO_PORT_MODE_LEGO_DCM);
×
135
    if (err == PBIO_ERROR_AGAIN) {
×
136
        // If coming from a different mode, give port some time to get started.
137
        // This happens when the user has a custom device and decides to switch
138
        // back to LEGO mode. This should be rare, so we can afford to wait.
139
        mp_hal_delay_ms(1000);
×
140
        err = pbio_port_set_mode(port, PBIO_PORT_MODE_LEGO_DCM);
×
141
    }
142
    pb_assert(err);
×
143
}
×
144

145
lego_device_type_id_t pb_type_device_init_class(pb_type_device_obj_base_t *self, mp_obj_t port_in, lego_device_type_id_t valid_id) {
×
146

147
    pb_module_tools_assert_blocking();
×
148

149
    pbio_port_id_t port_id = pb_type_enum_get_value(port_in, &pb_enum_type_Port);
×
150

151
    // Get the port instance.
152
    pbio_port_t *port;
153
    pb_assert(pbio_port_get_port(port_id, &port));
×
154

155
    // Set the port mode to LEGO if it is not already set.
156
    pb_device_set_lego_mode(port);
×
157

158
    pbio_error_t err;
159
    lego_device_type_id_t actual_id = valid_id;
×
160
    while ((err = pbio_port_get_lump_device(port, &actual_id, &self->lump_dev)) == PBIO_ERROR_AGAIN) {
×
161
        mp_hal_delay_ms(50);
×
162
    }
163
    pb_assert(err);
×
164
    while ((err = pbio_port_lump_is_ready(self->lump_dev)) == PBIO_ERROR_AGAIN) {
×
UNCOV
165
        mp_hal_delay_ms(50);
×
166
    }
167
    pb_assert(err);
×
168
    self->last_awaitable = NULL;
×
169
    return actual_id;
×
170
}
171

172
#endif // PYBRICKS_PY_PUPDEVICES
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc