static inline void _set_fixed_point_scroll(fix16_t *scroll, fix16_t amount, uint16_t *in, uint16_t *dn) { int32_t integral; integral = fix16_to_int(amount); fix16_t fractional; fractional = fix16_fractional(amount); *in = integral; *dn = fractional & 0xFF00; *scroll = fix16_add(fix16_from_int(*in), fractional); }
/* A basic single-frequency DFT, useful when you are interested in just a single signal. */ static cell AMX_NATIVE_CALL amx_dft(AMX *amx, const cell *params) { // dft(input{}, Fixed: &real, Fixed: &imag, Fixed: period, count); uint8_t *input = (uint8_t*)params[1]; int count = params[5]; fix16_t period = params[4]; fix16_t *realp = (fix16_t*)params[2]; fix16_t *imagp = (fix16_t*)params[3]; // Round the count to a multiple of period int multiple = fix16_from_int(count) / period; count = fix16_to_int(fix16_mul(fix16_from_int(multiple), period)); fix16_t real = 0; fix16_t imag = 0; fix16_t step = fix16_div(2 * fix16_pi, period); fix16_t angle = 0; for (int i = 0; i < count; i++) { // We scale by 256 to achieve a good compromise between precision and // range. fix16_t value = input[INPUT_INDEX(i)] * 256; // Calculate value * (cos(angle) - i * sin(angle)) and add to sum. real += fix16_mul(value, fix16_cos(angle)); imag += fix16_mul(value, -fix16_sin(angle)); angle += step; } fix16_t scale = count * 256; *realp = fix16_div(real, scale); *imagp = fix16_div(imag, scale); return 0; }
operator int16_t() const { return fix16_to_int(value); }
static inline void _set_integer_scroll(int16_t *scroll, fix16_t amount, uint16_t *in) { *scroll = WRAP_INTEGER((int16_t)fix16_to_int(amount)); *in = *scroll; }
void main(void) { hardware_init(); uint32_t color_idx; for (color_idx = 0; color_idx < TEAPOT_POLYGON_CNT; color_idx++) { uint32_t idx; idx = color_idx; uint32_t polygon_idx; fix16_vector4_t *polygon[4]; for (polygon_idx = 0; polygon_idx < 4; polygon_idx++) { uint32_t vertex_idx; vertex_idx = teapot_indices[(4 * idx) + polygon_idx]; fix16_vector4_t *vertex; vertex = &teapot_vertices[vertex_idx]; polygon[polygon_idx] = vertex; } fix16_t avg; avg = fix16_add(fix16_mul(fix16_add( fix16_add(polygon[0]->z, polygon[1]->z), fix16_add(polygon[2]->z, polygon[3]->z)), F16(1.0f / 4.0f)), F16(0.1f)); uint16_t color; color = fix16_to_int(fix16_add( fix16_mul(fix16_abs(avg), F16(255.0f)), F16(16.0f))); colors[color_idx] = RGB888_TO_RGB555(color, color, color); } ot_init(); matrix_stack_init(); matrix_stack_mode(MATRIX_STACK_MODE_PROJECTION); fix16_t ratio; ratio = F16((float)SCREEN_WIDTH / (float)SCREEN_HEIGHT); matrix_stack_orthographic_project(-fix16_mul(F16(1.0f), ratio), fix16_mul(F16(1.0f), ratio), F16(1.0f), F16(-1.0f), F16(1.0f), F16(1.0f)); matrix_stack_mode(MATRIX_STACK_MODE_MODEL_VIEW); matrix_stack_translate(F16(0.0f), F16(0.0f), F16(-10.0f)); vdp1_cmdt_list_begin(0); { struct vdp1_cmdt_local_coord local_coord; local_coord.lc_coord.x = SCREEN_WIDTH / 2; local_coord.lc_coord.y = SCREEN_HEIGHT / 2; vdp1_cmdt_local_coord_set(&local_coord); vdp1_cmdt_end(); } vdp1_cmdt_list_end(0); struct vdp1_cmdt_polygon polygon; memset(&polygon, 0x00, sizeof(polygon)); vdp2_tvmd_vblank_out_wait(); vdp2_tvmd_vblank_in_wait(); fix16_t angle = F16(0.0f); while (true) { vdp2_tvmd_vblank_out_wait(); // Update matrix_stack_mode(MATRIX_STACK_MODE_MODEL_VIEW); matrix_stack_push(); { matrix_stack_rotate(angle, 0); matrix_stack_rotate(angle, 1); matrix_stack_rotate(angle, 2); angle = fix16_add(angle, F16(-1.0f)); model_polygon_project(teapot_vertices, teapot_indices, teapot_normals, TEAPOT_POLYGON_CNT); } matrix_stack_pop(); vdp1_cmdt_list_begin(1); { int32_t idx; for (idx = OT_PRIMITIVE_BUCKETS - 1; idx >= 0; idx--) { /* Skip empty buckets */ if (ot_bucket_empty(idx)) { continue; } #if POLYGON_SORT == 1 ot_bucket_primitive_sort(idx & (OT_PRIMITIVE_BUCKETS - 1), OT_PRIMITIVE_BUCKET_SORT_INSERTION); #endif #if RENDER == 1 struct ot_primitive *otp; TAILQ_FOREACH (otp, ot_bucket(idx), otp_entries) { polygon.cp_color = otp->otp_color; polygon.cp_mode.transparent_pixel = true; polygon.cp_mode.end_code = true; polygon.cp_vertex.a.x = otp->otp_coords[0].x; polygon.cp_vertex.a.y = otp->otp_coords[0].y; polygon.cp_vertex.b.x = otp->otp_coords[1].x; polygon.cp_vertex.b.y = otp->otp_coords[1].y; polygon.cp_vertex.c.x = otp->otp_coords[2].x; polygon.cp_vertex.c.y = otp->otp_coords[2].y; polygon.cp_vertex.d.x = otp->otp_coords[3].x; polygon.cp_vertex.d.y = otp->otp_coords[3].y; vdp1_cmdt_polygon_draw(&polygon); } #endif /* Clear OT bucket */ ot_bucket_init(idx); } vdp1_cmdt_end(); } vdp1_cmdt_list_end(1); vdp2_tvmd_vblank_in_wait(); // Draw vdp1_cmdt_list_commit(); }