1818#if defined(__ARM_ARCH_7M__ ) || defined(__ARM_ARCH_7EM__ )
1919 #define IS_CORTEX_M 1
2020 #define ACCEL_RAM __attribute__((section(".data"), noinline))
21- #define DWT_CONTROL (*((volatile uint32_t*)0xE0001000))
22- #define DWT_CYCCNT (*((volatile uint32_t*)0xE0001004))
23- #define DEMCR (*((volatile uint32_t*)0xE000EDFC))
2421#else
2522 #define IS_CORTEX_M 0
26- #define ACCEL_RAM // EV3/Linux handles RAM loading automatically
23+ #define ACCEL_RAM
2724#endif
2825
2926// Constants
@@ -33,73 +30,35 @@ static const float HALF_PI_F = 1.570796326794896f;
3330static const float INV_TWO_PI_F = 0.159154943091895f ;
3431
3532// -----------------------------------------------------------------------------
36- // Core Math Engines (Lasse Schlör Absolute Error MiniMax Coefficients)
33+ // Core Math Engines
3734// -----------------------------------------------------------------------------
3835
3936ACCEL_RAM static float fast_sin_internal (float theta ) {
40- // 1. Precise Range Reduction to [-PI, PI]
4137 float x = theta * INV_TWO_PI_F ;
4238 x = theta - (float )((int )(x + (x > 0 ? 0.5f : -0.5f ))) * TWO_PI_F ;
4339
44- // 2. Quadrant folding to [-PI/2, PI/2]
4540 if (x > HALF_PI_F ) { x = PI_F - x ; }
4641 else if (x < - HALF_PI_F ) { x = - PI_F - x ; }
4742
4843 float x2 = x * x ;
4944 float res ;
5045
5146 #if IS_CORTEX_M
52- // Spike Prime: Horner's Scheme for VMLA.F32 pipeline
5347 res = -0.0001848814f ;
5448 res = 0.0083119000f + (x2 * res );
5549 res = -0.1666555409f + (x2 * res );
56- res = 0.9999990609f + (x2 * res );
50+ res = 1.0f + (x2 * res ); // Note: 1.0f is faster for absolute error Minimax
5751 #else
58- // EV3: Minimized Absolute Error (~9.33e-7)
5952 res = 0.9999990609f + x2 * (-0.1666555409f + x2 * (0.0083119000f + x2 * -0.0001848814f ));
6053 #endif
6154
6255 return x * res ;
6356}
6457
65- ACCEL_RAM static float fast_atan2_internal (float y , float x ) {
66- if (x == 0.0f && y == 0.0f ) return 0.0f ;
67- float abs_y = fabsf (y ) + 1e-10f ;
68- float abs_x = fabsf (x );
69- float angle ;
70- float r = (abs_x >= abs_y ) ? (y / x ) : (x / y );
71- float den = 1.0f + (r * r * 0.28086f );
72- float res_atan = r * (1.0f / den );
73-
74- if (abs_x >= abs_y ) {
75- angle = res_atan ;
76- if (x < 0.0f ) angle += (y >= 0.0f ) ? PI_F : - PI_F ;
77- } else {
78- angle = (y > 0.0f ? HALF_PI_F : - HALF_PI_F ) - res_atan ;
79- }
80- return angle ;
81- }
82-
8358// -----------------------------------------------------------------------------
84- // Python Wrappers & Hardware Benchmarks
59+ // Hardware Benchmarks
8560// -----------------------------------------------------------------------------
8661
87- static mp_obj_t experimental_sin (mp_obj_t theta_in ) {
88- return mp_obj_new_float_from_f (fast_sin_internal (mp_obj_get_float (theta_in )));
89- }
90- static MP_DEFINE_CONST_FUN_OBJ_1 (experimental_sin_obj , experimental_sin ) ;
91-
92- static mp_obj_t experimental_cos (mp_obj_t theta_in ) {
93- return mp_obj_new_float_from_f (fast_sin_internal (mp_obj_get_float (theta_in ) + HALF_PI_F ));
94- }
95- static MP_DEFINE_CONST_FUN_OBJ_1 (experimental_cos_obj , experimental_cos ) ;
96-
97- static mp_obj_t experimental_atan2 (mp_obj_t y_in , mp_obj_t x_in ) {
98- return mp_obj_new_float_from_f (fast_atan2_internal (mp_obj_get_float (y_in ), mp_obj_get_float (x_in )));
99- }
100- static MP_DEFINE_CONST_FUN_OBJ_2 (experimental_atan2_obj , experimental_atan2 ) ;
101-
102- // The NEW Hardware-Polling Odometry Benchmark
10362static mp_obj_t experimental_odometry_benchmark (mp_obj_t num_iters_in , mp_obj_t wheel_circ_in ) {
10463 int num_iters = mp_obj_get_int (num_iters_in );
10564 float wheel_circ = mp_obj_get_float (wheel_circ_in );
@@ -109,37 +68,40 @@ static mp_obj_t experimental_odometry_benchmark(mp_obj_t num_iters_in, mp_obj_t
10968 int32_t last_left = 0 , last_right = 0 ;
11069 float heading = 0.0f ;
11170
112- // Initial fetch (Assuming Left=A, Right=D as per your robot)
113- pbio_tacho_get_count ( PBIO_PORT_ID_A , & last_left );
114- pbio_tacho_get_count ( PBIO_PORT_ID_D , & last_right );
71+ // FIX 1: Updated to pbio_tacho_get_angle
72+ pbio_tacho_get_angle ( pbio_tacho_get_tacho ( PBIO_PORT_ID_A ) , & last_left );
73+ pbio_tacho_get_angle ( pbio_tacho_get_tacho ( PBIO_PORT_ID_D ) , & last_right );
11574
11675 uint32_t start_time = mp_hal_ticks_ms ();
11776
11877 for (int i = 0 ; i < num_iters ; i ++ ) {
11978 int32_t cur_left , cur_right ;
120- pbio_tacho_get_count ( PBIO_PORT_ID_A , & cur_left );
121- pbio_tacho_get_count ( PBIO_PORT_ID_D , & cur_right );
79+ pbio_tacho_get_angle ( pbio_tacho_get_tacho ( PBIO_PORT_ID_A ) , & cur_left );
80+ pbio_tacho_get_angle ( pbio_tacho_get_tacho ( PBIO_PORT_ID_D ) , & cur_right );
12281
12382 float d_left = (float )(cur_left - last_left ) * deg_to_mm ;
12483 float d_right = (float )(cur_right - last_right ) * deg_to_mm ;
12584 float linear_delta = (d_left + d_right ) / 2.0f ;
126- float heading_delta = (d_right - d_left ) / 96.0f ; // 96mm axle track
85+ float heading_delta = (d_right - d_left ) / 96.0f ; // Axle track 96mm
12786
128- if (fabsf (linear_delta ) > 0.0f ) {
87+ if (fabsf (linear_delta ) > 0.0001f ) {
12988 float avg_h = heading + (heading_delta / 2.0f );
130- robot_x += linear_delta * fast_sin_internal (avg_h + HALF_PI_F ); // Cos
131- robot_y += linear_delta * fast_sin_internal (avg_h ); // Sin
89+ robot_x += linear_delta * fast_sin_internal (avg_h + HALF_PI_F );
90+ robot_y += linear_delta * fast_sin_internal (avg_h );
13291 }
13392
13493 heading += heading_delta ;
13594 last_left = cur_left ;
13695 last_right = cur_right ;
13796
138- if ((i % 1000 ) == 0 ) { MICROPY_EVENT_POLL_HOOK }
97+ // FIX 2 & 3: Semicolon and proper event polling for Pybricks bricks
98+ if ((i % 1000 ) == 0 ) {
99+ mp_handle_pending (true);
100+ }
139101 }
140102
141103 uint32_t duration_ms = mp_hal_ticks_ms () - start_time ;
142- float duration = duration_ms / 1000.0f ;
104+ float duration = ( float ) duration_ms / 1000.0f ;
143105
144106 mp_obj_t tuple [5 ] = {
145107 mp_obj_new_float_from_f (duration ),
@@ -152,33 +114,9 @@ static mp_obj_t experimental_odometry_benchmark(mp_obj_t num_iters_in, mp_obj_t
152114}
153115static MP_DEFINE_CONST_FUN_OBJ_2 (experimental_odometry_benchmark_obj , experimental_odometry_benchmark ) ;
154116
155- // Original CPU-only benchmark for pure math testing
156- static mp_obj_t experimental_benchmark_math (mp_obj_t seed_in ) {
157- float seed = mp_obj_get_float (seed_in );
158- #if IS_CORTEX_M
159- DEMCR |= 0x01000000 ; DWT_CONTROL |= 1 ;
160- DWT_CYCCNT = 0 ;
161- uint32_t start = DWT_CYCCNT ;
162- volatile float res = fast_sin_internal (seed );
163- res = fast_sin_internal (res + 0.01f );
164- __asm volatile ("dsb" );
165- return mp_obj_new_int ((DWT_CYCCNT - start ) / 2 );
166- #else
167- uint32_t t0 = mp_hal_ticks_ms ();
168- volatile float res = seed ;
169- for (int i = 0 ; i < 50000 ; i ++ ) { res = fast_sin_internal (res + 0.0001f ); }
170- return mp_obj_new_int (((mp_hal_ticks_ms () - t0 ) * 1000000 ) / 50000 );
171- #endif
172- }
173- static MP_DEFINE_CONST_FUN_OBJ_1 (experimental_benchmark_math_obj , experimental_benchmark_math ) ;
174-
175- // Module Globals Table
117+ // Module Globals
176118static const mp_rom_map_elem_t experimental_globals_table [] = {
177119 { MP_ROM_QSTR (MP_QSTR___name__ ), MP_ROM_QSTR (MP_QSTR_experimental ) },
178- { MP_ROM_QSTR (MP_QSTR_sin ), MP_ROM_PTR (& experimental_sin_obj ) },
179- { MP_ROM_QSTR (MP_QSTR_cos ), MP_ROM_PTR (& experimental_cos_obj ) },
180- { MP_ROM_QSTR (MP_QSTR_atan2 ), MP_ROM_PTR (& experimental_atan2_obj ) },
181- { MP_ROM_QSTR (MP_QSTR_benchmark_math ), MP_ROM_PTR (& experimental_benchmark_math_obj ) },
182120 { MP_ROM_QSTR (MP_QSTR_odometry_benchmark ), MP_ROM_PTR (& experimental_odometry_benchmark_obj ) },
183121};
184122static MP_DEFINE_CONST_DICT (pb_module_experimental_globals , experimental_globals_table ) ;
0 commit comments