@@ -74,6 +74,65 @@ STATIC void claim_and_never_reset_pins(mp_obj_t seq) {
74
74
}
75
75
}
76
76
77
+ STATIC void preflight_pins_or_throw (uint8_t clock_pin , uint8_t * rgb_pins , uint8_t rgb_pin_count , bool allow_inefficient ) {
78
+ uint32_t port = clock_pin / 32 ;
79
+ uint32_t bit_mask = 1 << (clock_pin % 32 );
80
+
81
+ for (uint8_t i = 0 ; i < rgb_pin_count ; i ++ ) {
82
+ uint32_t pin_port = rgb_pins [i ] / 32 ;
83
+
84
+ if (pin_port != port ) {
85
+ mp_raise_ValueError_varg (
86
+ translate ("rgb_pins[%d] is not on the same port as clock" ), i );
87
+ }
88
+
89
+ uint32_t pin_mask = 1 << (rgb_pins [i ] % 32 );
90
+ if (pin_mask & bit_mask ) {
91
+ mp_raise_ValueError_varg (
92
+ translate ("rgb_pins[%d] duplicates another pin assignment" ), i );
93
+ }
94
+
95
+ bit_mask |= pin_mask ;
96
+ }
97
+
98
+ if (allow_inefficient ) {
99
+ return ;
100
+ }
101
+
102
+ uint8_t byte_mask = 0 ;
103
+ if (bit_mask & 0x000000FF ) byte_mask |= 0b0001 ;
104
+ if (bit_mask & 0x0000FF00 ) byte_mask |= 0b0010 ;
105
+ if (bit_mask & 0x00FF0000 ) byte_mask |= 0b0100 ;
106
+ if (bit_mask & 0xFF000000 ) byte_mask |= 0b1000 ;
107
+
108
+ uint8_t bytes_per_element = 0xff ;
109
+ uint8_t ideal_bytes_per_element = (rgb_pin_count + 7 ) / 8 ;
110
+
111
+ switch (byte_mask ) {
112
+ case 0b0001 :
113
+ case 0b0010 :
114
+ case 0b0100 :
115
+ case 0b1000 :
116
+ bytes_per_element = 1 ;
117
+ break ;
118
+
119
+ case 0b0011 :
120
+ case 0b1100 :
121
+ bytes_per_element = 2 ;
122
+ break ;
123
+
124
+ default :
125
+ bytes_per_element = 4 ;
126
+ break ;
127
+ }
128
+
129
+ if (bytes_per_element != ideal_bytes_per_element ) {
130
+ mp_raise_ValueError_varg (
131
+ translate ("Pinout uses %d bytes per element, which consumes more than the ideal %d bytes. If this cannot be avoided, pass allow_inefficient=True to the constructor" ),
132
+ bytes_per_element , ideal_bytes_per_element );
133
+ }
134
+ }
135
+
77
136
//| :class:`~_protomatter.Protomatter` displays an in-memory framebuffer to an LED matrix.
78
137
//|
79
138
//| .. class:: Protomatter(width, bit_depth, rgb_pins, addr_pins, clock_pin, latch_pin, oe_pin, *, doublebuffer=True, framebuffer=None)
@@ -141,6 +200,8 @@ STATIC mp_obj_t protomatter_protomatter_make_new(const mp_obj_type_t *type, size
141
200
validate_pins (MP_QSTR_rgb_pins , rgb_pins , MP_ARRAY_SIZE (self -> rgb_pins ), args [ARG_rgb_list ].u_obj , & rgb_count );
142
201
validate_pins (MP_QSTR_addr_pins , addr_pins , MP_ARRAY_SIZE (self -> addr_pins ), args [ARG_addr_list ].u_obj , & addr_count );
143
202
203
+ preflight_pins_or_throw (clock_pin , rgb_pins , rgb_count , true);
204
+
144
205
mp_obj_t framebuffer = args [ARG_framebuffer ].u_obj ;
145
206
if (framebuffer == mp_const_none ) {
146
207
int width = args [ARG_width ].u_int ;
0 commit comments