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

pybricks / pybricks-micropython / 13809131738

12 Mar 2025 10:27AM UTC coverage: 56.949% (+0.6%) from 56.307%
13809131738

Pull #297

github

web-flow
Merge 17057d313 into aae52d0d7
Pull Request #297: pbio/port: Rework ports as pbio module.

513 of 789 new or added lines in 24 files covered. (65.02%)

20 existing lines in 5 files now uncovered.

3827 of 6720 relevant lines covered (56.95%)

20681701.42 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);
×
NEW
33
    void *data = NULL;
×
NEW
34
    pb_assert(pbio_port_lump_get_data(sensor->lump_dev, mode, &data));
×
UNCOV
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);
×
NEW
50
    pb_assert(pbio_port_lump_set_mode(sensor->lump_dev, mode));
×
51
    pbio_error_t err;
×
NEW
52
    while ((err = pbio_port_lump_is_ready(sensor->lump_dev)) == PBIO_ERROR_AGAIN) {
×
53
        MICROPY_EVENT_POLL_HOOK
×
54
    }
55
    pb_assert(err);
×
NEW
56
    void *data = NULL;
×
NEW
57
    pb_assert(pbio_port_lump_get_data(sensor->lump_dev, mode, &data));
×
UNCOV
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
 * @param [in]  self_in     The sensor object instance.
69
 * @param [in]  end_time    Not used.
70
 * @return                  True if operation is complete (device ready),
71
 *                          false otherwise.
72
 */
73
static bool pb_pup_device_test_completion(mp_obj_t self_in, uint32_t end_time) {
×
74
    pb_type_device_obj_base_t *sensor = MP_OBJ_TO_PTR(self_in);
×
NEW
75
    pbio_error_t err = pbio_port_lump_is_ready(sensor->lump_dev);
×
76
    if (err == PBIO_ERROR_AGAIN) {
×
77
        return false;
78
    }
79
    pb_assert(err);
×
80
    return true;
×
81
}
82

83
/**
84
 * Implements calling of async sensor methods. This is called when a (constant)
85
 * entry of pb_type_device_method type in a sensor class is called. It is
86
 * responsible for setting the sensor mode and returning an awaitable object.
87
 *
88
 * This is also called in a few places where a simple constant sensor method
89
 * is not sufficient, where additional wrapping code is used to dynamically
90
 * set the mode or return mapping, such as in the multi-purpose PUPDevice, or
91
 * the ColorSensor class variants, where different modes or mappings are needed
92
 * for a single method depending on a keyword argument.
93
 */
94
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) {
×
95
    assert(mp_obj_is_type(self_in, &pb_type_device_method));
×
96
    pb_type_device_method_obj_t *method = MP_OBJ_TO_PTR(self_in);
×
97
    mp_arg_check_num(n_args, n_kw, 1, 1, false);
×
98

99
    mp_obj_t sensor_in = args[0];
×
100
    pb_type_device_obj_base_t *sensor = MP_OBJ_TO_PTR(sensor_in);
×
NEW
101
    pb_assert(pbio_port_lump_set_mode(sensor->lump_dev, method->mode));
×
102

103
    return pb_type_awaitable_await_or_wait(
×
104
        sensor_in,
105
        sensor->awaitables,
106
        pb_type_awaitable_end_time_none,
107
        pb_pup_device_test_completion,
108
        method->get_values,
109
        pb_type_awaitable_cancel_none,
110
        PB_TYPE_AWAITABLE_OPT_NONE);
111
}
112

113
/**
114
 * Function-like callable type for async sensor methods. This type is used for
115
 * constant pb_type_device_method_obj_t instances, which store a sensor mode to
116
 * set and a mapping function to create a return object when that data is ready.
117
 */
118
MP_DEFINE_CONST_OBJ_TYPE(
119
    pb_type_device_method, MP_QSTR_function, MP_TYPE_FLAG_BINDS_SELF | MP_TYPE_FLAG_BUILTIN_FUN,
120
    call, pb_type_device_method_call,
121
    unary_op, mp_generic_unary_op
122
    );
123

124
/**
125
 * Set data for a Powered Up device, such as the brightness of multiple external
126
 * lights on a sensor. Automatically sets the mode if not already set. Returns
127
 * an awaitable object that can be used to wait for the operation to complete.
128
 *
129
 * @param [in]  sensor      The powered up device.
130
 * @param [in]  mode        Desired mode.
131
 * @param [in]  data        Data to set.
132
 * @param [in]  size        Size of data.
133
 * @return                  Awaitable object.
134
 */
135
mp_obj_t pb_type_device_set_data(pb_type_device_obj_base_t *sensor, uint8_t mode, const void *data, uint8_t size) {
×
NEW
136
    pb_assert(pbio_port_lump_set_mode_with_data(sensor->lump_dev, mode, data, size));
×
137
    return pb_type_awaitable_await_or_wait(
×
138
        MP_OBJ_FROM_PTR(sensor),
139
        sensor->awaitables,
140
        pb_type_awaitable_end_time_none,
141
        pb_pup_device_test_completion,
142
        pb_type_awaitable_return_none,
143
        pb_type_awaitable_cancel_none,
144
        PB_TYPE_AWAITABLE_OPT_RAISE_ON_BUSY);
145
}
146

NEW
147
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) {
×
148

UNCOV
149
    pb_module_tools_assert_blocking();
×
150

NEW
151
    pbio_port_id_t port_id = pb_type_enum_get_value(port_in, &pb_enum_type_Port);
×
152

153
    // Get the port instance.
NEW
154
    pbio_port_t *port;
×
NEW
155
    pb_assert(pbio_port_get_port(port_id, &port));
×
156

UNCOV
157
    pbio_error_t err;
×
NEW
158
    lego_device_type_id_t actual_id = valid_id;
×
NEW
159
    while ((err = pbio_port_get_lump_device(port, &actual_id, &self->lump_dev)) == PBIO_ERROR_AGAIN) {
×
UNCOV
160
        mp_hal_delay_ms(50);
×
161
    }
UNCOV
162
    pb_assert(err);
×
UNCOV
163
    self->awaitables = mp_obj_new_list(0, NULL);
×
UNCOV
164
    return actual_id;
×
165
}
166

167
#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