diff options
author | Bad Diode <bd@badd10de.dev> | 2024-01-23 10:30:54 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2024-01-23 10:30:54 +0100 |
commit | a7ce765b1b57ec8a528263420852ed36da6d9d84 (patch) | |
tree | 99ce3f4b309952bae01ae5ae629c136faefe5774 | |
parent | bda8ac3969d40b28c4c14683c1f722647fd17aec (diff) | |
download | stepper-a7ce765b1b57ec8a528263420852ed36da6d9d84.tar.gz stepper-a7ce765b1b57ec8a528263420852ed36da6d9d84.zip |
Update profiling macros
-rw-r--r-- | src/gba/gba.h | 84 | ||||
-rw-r--r-- | src/main.c | 94 | ||||
-rw-r--r-- | src/profiling.c | 253 | ||||
-rw-r--r-- | src/sequencer.c | 1 | ||||
-rw-r--r-- | src/settings.c | 2 |
5 files changed, 182 insertions, 252 deletions
diff --git a/src/gba/gba.h b/src/gba/gba.h index b5868f0..2cc167f 100644 --- a/src/gba/gba.h +++ b/src/gba/gba.h | |||
@@ -237,25 +237,25 @@ flip_page(vu16 *backbuffer) { | |||
237 | static inline | 237 | static inline |
238 | void | 238 | void |
239 | profile_start(void) { | 239 | profile_start(void) { |
240 | TIMER_DATA_2 = 0; | 240 | TIMER_DATA_1 = 0; |
241 | TIMER_DATA_3 = 0; | 241 | TIMER_DATA_0 = 0; |
242 | TIMER_CTRL_2 = 0; | 242 | TIMER_CTRL_1 = 0; |
243 | TIMER_CTRL_3 = 0; | 243 | TIMER_CTRL_0 = 0; |
244 | TIMER_CTRL_3 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE; | 244 | TIMER_CTRL_1 = TIMER_CTRL_ENABLE | TIMER_CTRL_CASCADE; |
245 | TIMER_CTRL_2 = TIMER_CTRL_ENABLE; | 245 | TIMER_CTRL_0 = TIMER_CTRL_ENABLE; |
246 | } | 246 | } |
247 | 247 | ||
248 | static inline | 248 | static inline |
249 | u32 | 249 | u32 |
250 | profile_stop(void) { | 250 | profile_stop(void) { |
251 | TIMER_CTRL_2 = 0; | 251 | TIMER_CTRL_0 = 0; |
252 | return (TIMER_DATA_3 << 16) | TIMER_DATA_2; | 252 | return (TIMER_DATA_1 << 16) | TIMER_DATA_0; |
253 | } | 253 | } |
254 | 254 | ||
255 | static inline | 255 | static inline |
256 | u32 | 256 | u32 |
257 | profile_measure(void) { | 257 | profile_measure(void) { |
258 | return (TIMER_DATA_3 << 16) | TIMER_DATA_2; | 258 | return (TIMER_DATA_1 << 16) | TIMER_DATA_0; |
259 | } | 259 | } |
260 | 260 | ||
261 | // | 261 | // |
@@ -289,12 +289,24 @@ profile_measure(void) { | |||
289 | static u16 key_curr = 0; | 289 | static u16 key_curr = 0; |
290 | static u16 key_prev = 0; | 290 | static u16 key_prev = 0; |
291 | 291 | ||
292 | static inline | 292 | // Stores number of frames since a keay was pressed. |
293 | void | 293 | typedef struct Controller { |
294 | poll_keys(void) { | 294 | int key_up; |
295 | key_prev = key_curr; | 295 | int key_down; |
296 | key_curr = ~KEY_INPUTS & KEY_MASK; | 296 | int key_left; |
297 | } | 297 | int key_right; |
298 | int key_select; | ||
299 | int key_start; | ||
300 | int key_b; | ||
301 | int key_a; | ||
302 | int key_l; | ||
303 | int key_r; | ||
304 | } Controller; | ||
305 | |||
306 | static Controller ctrl = {0}; | ||
307 | |||
308 | #define RETRIG_OFFSET 16 | ||
309 | #define RETRIG_FRAMES 3 | ||
298 | 310 | ||
299 | // Returns true if the given key has been pressed at time of calling and was not | 311 | // Returns true if the given key has been pressed at time of calling and was not |
300 | // pressed since the previous call. For example, if a key is being held, this | 312 | // pressed since the previous call. For example, if a key is being held, this |
@@ -327,25 +339,6 @@ key_hold(u32 key) { | |||
327 | return key_curr & key_prev & key; | 339 | return key_curr & key_prev & key; |
328 | } | 340 | } |
329 | 341 | ||
330 | // Stores number of frames since a keay was pressed. | ||
331 | typedef struct Controller { | ||
332 | int key_up; | ||
333 | int key_down; | ||
334 | int key_left; | ||
335 | int key_right; | ||
336 | int key_select; | ||
337 | int key_start; | ||
338 | int key_b; | ||
339 | int key_a; | ||
340 | int key_l; | ||
341 | int key_r; | ||
342 | } Controller; | ||
343 | |||
344 | static Controller ctrl = {0}; | ||
345 | |||
346 | #define RETRIG_OFFSET 16 | ||
347 | #define RETRIG_FRAMES 3 | ||
348 | |||
349 | static inline | 342 | static inline |
350 | bool | 343 | bool |
351 | _key_retrig(int key, int offset, int frames) { | 344 | _key_retrig(int key, int offset, int frames) { |
@@ -438,6 +431,14 @@ update_controller(void) { | |||
438 | if (key_pressed(KEY_START)) { ctrl.key_start++; } else if (key_released(KEY_START)) { ctrl.key_start = 0; } | 431 | if (key_pressed(KEY_START)) { ctrl.key_start++; } else if (key_released(KEY_START)) { ctrl.key_start = 0; } |
439 | } | 432 | } |
440 | 433 | ||
434 | static inline | ||
435 | void | ||
436 | poll_keys(void) { | ||
437 | key_prev = key_curr; | ||
438 | key_curr = ~KEY_INPUTS & KEY_MASK; | ||
439 | update_controller(); | ||
440 | } | ||
441 | |||
441 | // | 442 | // |
442 | // Direct Memory Access (DMA) | 443 | // Direct Memory Access (DMA) |
443 | // | 444 | // |
@@ -785,6 +786,7 @@ wait_vsync(void) { | |||
785 | // General utility macros. | 786 | // General utility macros. |
786 | #define MIN(A, B) ((A) <= (B) ? (A) : (B)) | 787 | #define MIN(A, B) ((A) <= (B) ? (A) : (B)) |
787 | #define MAX(A, B) ((A) >= (B) ? (A) : (B)) | 788 | #define MAX(A, B) ((A) >= (B) ? (A) : (B)) |
789 | #define ABS(A) (((A) ^ ((A) >> (sizeof(A) * 8 - 1))) - ((A) >> (sizeof(A) * 8 - 1))) | ||
788 | #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) | 790 | #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) |
789 | #define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) | 791 | #define LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) |
790 | 792 | ||
@@ -812,10 +814,24 @@ memcpy32(u32 *dst, const u32 *src, u32 size) { | |||
812 | } | 814 | } |
813 | } | 815 | } |
814 | 816 | ||
817 | static inline | ||
818 | void | ||
819 | memset32(u32 *dst, const u32 data, u32 size) { | ||
820 | for (size_t i = 0; i < size / 4; i++) { | ||
821 | dst[i] = data; | ||
822 | } | ||
823 | } | ||
824 | |||
825 | // Optimized ARMASM versions of memcpy32 and memset32. | ||
826 | extern void copy32(u32 *dst, u32 *src, u32 chunks); | ||
827 | extern void set32(u32 *dst, u32 data, u32 chunks); | ||
828 | |||
815 | // | 829 | // |
816 | // Compiler hints. | 830 | // Compiler hints. |
817 | // | 831 | // |
818 | 832 | ||
819 | #define UNROLL_LOOPS __attribute__((optimize("unroll-loops"))) | 833 | #define UNROLL_LOOPS __attribute__((optimize("unroll-loops"))) |
834 | #define INLINE __attribute__((always_inline)) inline | ||
820 | 835 | ||
821 | #endif // GBA_H | 836 | #endif // GBA_H |
837 | |||
@@ -11,7 +11,8 @@ WITH REGARD TO THIS SOFTWARE. | |||
11 | 11 | ||
12 | // TODO: A list of features I would like to get to implement in the near future. | 12 | // TODO: A list of features I would like to get to implement in the near future. |
13 | // | 13 | // |
14 | // High priority: | 14 | // Remaining issues: |
15 | // | ||
15 | // + Higher resolution clock to allow for microtiming and more accurate tempo. | 16 | // + Higher resolution clock to allow for microtiming and more accurate tempo. |
16 | // + Look back again at the emulator issues... (I give up) | 17 | // + Look back again at the emulator issues... (I give up) |
17 | // + Sync via MIDI with the Analogue cables. | 18 | // + Sync via MIDI with the Analogue cables. |
@@ -32,30 +33,18 @@ WITH REGARD TO THIS SOFTWARE. | |||
32 | // + Fix A+B on ch3 | 33 | // + Fix A+B on ch3 |
33 | // + Make sure Attack/Decay are grey for A+B | 34 | // + Make sure Attack/Decay are grey for A+B |
34 | // + Add help for attack/decay on ch3 | 35 | // + Add help for attack/decay on ch3 |
36 | // + Bad performance when selecting patterns? | ||
35 | // - Fix any bugs we currently have | 37 | // - Fix any bugs we currently have |
36 | // - Add clipboard sharing between banks. | 38 | // - Add clipboard sharing between banks. |
37 | // - Make sure transposing a sequence past the keyboard limit doesn't affect | 39 | // - Make sure transposing a sequence past the keyboard limit doesn't affect |
38 | // the sequence and can be reversed. | 40 | // the sequence and can be reversed. |
39 | // - Study saving overhauls for bootleg cartridges. | 41 | // - Study saving overhauls for bootleg cartridges. |
40 | // - When putting a new trigger, make sure it uses the global parameters | 42 | // - When putting a new trigger, make sure it uses the global parameters |
41 | // - Bad performance when selecting patterns? | 43 | // - Improve memcpy32 performance (ASM?). We use it a lot in expensive places. |
42 | // | ||
43 | // Low priority: | ||
44 | // | ||
45 | // Quality of life improvements. | ||
46 | // - When not on play mode, adjusting a note or a parameter triggers the sound. | ||
47 | // This could get annoying, so maybe it should be a configuration option to | ||
48 | // enable it? | ||
49 | // - Undo/Redo. | ||
50 | // | ||
51 | // Advanced | ||
52 | // - Add tap tempo for BPM. | 44 | // - Add tap tempo for BPM. |
53 | // - Allow "marking" several trigs to be able to copy/paste them and/or adjust | 45 | // - Improve drawing routines even more (ASM?). |
54 | // their parameters. | 46 | // - Improve interrupt handler to allow nesting/prioritization. |
55 | // - Per trig LFO? How would we go about this? There is at least one empty slot | 47 | // |
56 | // in all channels. LFO amount? LFO speed? Would need a dedicated page for | ||
57 | // configuring LFOs | ||
58 | |||
59 | 48 | ||
60 | #include "gba/gba.h" | 49 | #include "gba/gba.h" |
61 | 50 | ||
@@ -76,37 +65,37 @@ static int frames = 0; | |||
76 | void | 65 | void |
77 | render_sequencer(void) { | 66 | render_sequencer(void) { |
78 | if (redraw_trigs) { | 67 | if (redraw_trigs) { |
79 | PROF(draw_triggers(), draw_trigs_cycles); | 68 | draw_triggers(); |
80 | redraw_trigs = false; | 69 | redraw_trigs = false; |
81 | } | 70 | } |
82 | if (redraw_channels) { | 71 | if (redraw_channels) { |
83 | PROF(draw_channels(), draw_btn_cycles); | 72 | draw_channels(); |
84 | redraw_channels = false; | 73 | redraw_channels = false; |
85 | } | 74 | } |
86 | if (redraw_pattern_buttons) { | 75 | if (redraw_pattern_buttons) { |
87 | PROF(draw_pattern_buttons(), draw_btn_cycles); | 76 | draw_pattern_buttons(); |
88 | redraw_pattern_buttons = false; | 77 | redraw_pattern_buttons = false; |
89 | } | 78 | } |
90 | if (redraw_bank_buttons) { | 79 | if (redraw_bank_buttons) { |
91 | PROF(draw_bank_buttons(), draw_btn_cycles); | 80 | draw_bank_buttons(); |
92 | redraw_bank_buttons = false; | 81 | redraw_bank_buttons = false; |
93 | } | 82 | } |
94 | if (redraw_bpm) { | 83 | if (redraw_bpm) { |
95 | PROF(draw_bpm(), draw_btn_cycles); | 84 | draw_bpm(); |
96 | redraw_bpm = false; | 85 | redraw_bpm = false; |
97 | } | 86 | } |
98 | if (redraw_play_pause) { | 87 | if (redraw_play_pause) { |
99 | PROF(draw_play(), draw_btn_cycles); | 88 | draw_play(); |
100 | PROF(draw_stop(), draw_btn_cycles); | 89 | draw_stop(); |
101 | PROF(draw_settings(), draw_btn_cycles); | 90 | draw_settings(); |
102 | redraw_play_pause = false; | 91 | redraw_play_pause = false; |
103 | } | 92 | } |
104 | if (redraw_scale) { | 93 | if (redraw_scale) { |
105 | PROF(draw_scale(), draw_btn_cycles); | 94 | draw_scale(); |
106 | redraw_scale = false; | 95 | redraw_scale = false; |
107 | } | 96 | } |
108 | if (redraw_params) { | 97 | if (redraw_params) { |
109 | PROF(draw_parameters(), draw_param_cycles); | 98 | draw_parameters(); |
110 | redraw_params = false; | 99 | redraw_params = false; |
111 | } | 100 | } |
112 | 101 | ||
@@ -117,11 +106,13 @@ render_sequencer(void) { | |||
117 | } | 106 | } |
118 | } | 107 | } |
119 | 108 | ||
120 | if (frames++ & 0x1) { | 109 | if (frames & 0x1) { |
121 | draw_notif_bar(); | 110 | draw_notif_bar(); |
122 | PROF(draw_piano_notes(), draw_piano_cycles); | ||
123 | } | 111 | } |
124 | PROF(draw_cursors(), draw_cursor_cycles); | 112 | if (frames++ % 0x4 == 0) { |
113 | draw_piano_notes(); | ||
114 | } | ||
115 | draw_cursors(); | ||
125 | } | 116 | } |
126 | 117 | ||
127 | void | 118 | void |
@@ -169,28 +160,22 @@ render_settings(void) { | |||
169 | txt_drawf("HELP", x0 + 2, y0 + 1, COL_FG); | 160 | txt_drawf("HELP", x0 + 2, y0 + 1, COL_FG); |
170 | txt_drawf("%s", x1 + 8, y0 + 1, COL_FG, toggle_settings_str[settings.help]); | 161 | txt_drawf("%s", x1 + 8, y0 + 1, COL_FG, toggle_settings_str[settings.help]); |
171 | 162 | ||
172 | PROF(draw_settings_cursor(), draw_cursor_cycles); | 163 | draw_settings_cursor(); |
173 | } | 164 | } |
174 | 165 | ||
175 | void | 166 | void |
176 | render(void) { | 167 | render(void) { |
177 | // NOTE: Debug key input | ||
178 | // PROF(screen_fill(COL_BG), clear_cycles); | ||
179 | // txt_printf("UP: %d\n", ctrl.key_up); | ||
180 | // txt_printf("DOWN: %d\n", ctrl.key_down); | ||
181 | // txt_printf("LEFT: %d\n", ctrl.key_left); | ||
182 | // txt_printf("RIGHT: %d\n", ctrl.key_right); | ||
183 | // txt_printf("A: %d\n", ctrl.key_a); | ||
184 | // txt_printf("B: %d\n", ctrl.key_b); | ||
185 | // txt_printf("L: %d\n", ctrl.key_l); | ||
186 | // txt_printf("R: %d\n", ctrl.key_r); | ||
187 | // txt_printf("SEL: %d\n", ctrl.key_select); | ||
188 | // txt_printf("START: %d\n", ctrl.key_start); | ||
189 | // txt_render(); | ||
190 | // txt_clear(); | ||
191 | if (clear_screen) { | 168 | if (clear_screen) { |
192 | PROF(screen_fill(COL_BG), clear_cycles); | 169 | PROF(screen_fill(COL_BG), PROF_FILL); |
193 | clear_screen = false; | 170 | clear_screen = false; |
171 | redraw_trigs = true; | ||
172 | redraw_channels = true; | ||
173 | redraw_pattern_buttons = true; | ||
174 | redraw_bank_buttons = true; | ||
175 | redraw_bpm = true; | ||
176 | redraw_play_pause = true; | ||
177 | redraw_params = true; | ||
178 | redraw_scale = true; | ||
194 | } | 179 | } |
195 | switch (scene) { | 180 | switch (scene) { |
196 | case SCENE_SETTINGS: { | 181 | case SCENE_SETTINGS: { |
@@ -206,6 +191,10 @@ render(void) { | |||
206 | 191 | ||
207 | void | 192 | void |
208 | handle_input(void) { | 193 | handle_input(void) { |
194 | if (key_tap(KEY_SELECT) && key_hold(KEY_START)) { | ||
195 | PROF_SHOW(); | ||
196 | clear_screen = true; | ||
197 | } | ||
209 | switch (scene) { | 198 | switch (scene) { |
210 | case SCENE_SETTINGS: { | 199 | case SCENE_SETTINGS: { |
211 | handle_settings_input(); | 200 | handle_settings_input(); |
@@ -218,7 +207,6 @@ handle_input(void) { | |||
218 | 207 | ||
219 | void | 208 | void |
220 | update(void) { | 209 | update(void) { |
221 | update_controller(); | ||
222 | if (next_scene != scene) { | 210 | if (next_scene != scene) { |
223 | scene = next_scene; | 211 | scene = next_scene; |
224 | clear_screen = true; | 212 | clear_screen = true; |
@@ -269,15 +257,15 @@ main(void) { | |||
269 | txt_spacing(6); | 257 | txt_spacing(6); |
270 | 258 | ||
271 | // Main loop. | 259 | // Main loop. |
260 | PROF_INIT(); | ||
272 | while (true) { | 261 | while (true) { |
273 | poll_keys(); | 262 | poll_keys(); |
274 | bios_vblank_wait(); | 263 | bios_vblank_wait(); |
275 | PROF_SHOW(); | ||
276 | FRAME_START(); | 264 | FRAME_START(); |
277 | PROF(flip_buffer(), flip_cycles); | 265 | PROF(flip_buffer(), PROF_FLIP); |
278 | PROF(update(), update_cycles); | 266 | PROF(update(), PROF_UPDATE); |
279 | PROF(handle_input(), input_cycles); | 267 | PROF(handle_input(), PROF_INPUT); |
280 | PROF(render(), render_cycles); | 268 | PROF(render(), PROF_RENDER); |
281 | FRAME_END(); | 269 | FRAME_END(); |
282 | } | 270 | } |
283 | 271 | ||
diff --git a/src/profiling.c b/src/profiling.c index 0255552..6b073ed 100644 --- a/src/profiling.c +++ b/src/profiling.c | |||
@@ -6,184 +6,111 @@ | |||
6 | #define PROF_ENABLE 0 | 6 | #define PROF_ENABLE 0 |
7 | #endif | 7 | #endif |
8 | 8 | ||
9 | #if PROF_ENABLE > 0 && PROF_ENABLE < 3 | 9 | #if PROF_ENABLE > 0 |
10 | 10 | ||
11 | #ifndef PROF_N_FRAMES | 11 | #ifndef PROF_RESET_MINMAX |
12 | #define PROF_N_FRAMES 30 | 12 | #define PROF_RESET_MINMAX false |
13 | #endif | 13 | #endif |
14 | 14 | ||
15 | // Profile method 1: Average per N frames. | 15 | // Maximum number of profiling to monitor. |
16 | #if PROF_ENABLE == 1 | 16 | typedef enum ProfType { |
17 | #define TEXT_ENABLE 1 | 17 | PROF_INPUT, |
18 | #define PROF(F,VAR) \ | 18 | PROF_UPDATE, |
19 | do { \ | 19 | PROF_RENDER, |
20 | u32 __tmp_prof = profile_measure();\ | 20 | PROF_FLIP, |
21 | F;\ | 21 | PROF_FILL, |
22 | (VAR) += profile_measure() - __tmp_prof;\ | 22 | PROF_NUM, |
23 | } while (0) | 23 | } ProfType; |
24 | 24 | ||
25 | // Profile method 2: Maximum in N frames. | 25 | char *prof_type_str[PROF_NUM] = { |
26 | #elif PROF_ENABLE == 2 | 26 | "INPUT ", |
27 | #define TEXT_ENABLE 1 | 27 | "UPDATE ", |
28 | #define PROF(F,VAR) \ | 28 | "RENDER ", |
29 | do { \ | 29 | "FLIPBUF", |
30 | u32 __tmp_prof = profile_measure();\ | 30 | "SCRFILL", |
31 | (F);\ | 31 | }; |
32 | (VAR) = MAX(profile_measure() - __tmp_prof, (VAR));\ | ||
33 | } while (0) | ||
34 | #endif | ||
35 | 32 | ||
36 | #ifndef PROF_SHOW_X | 33 | u32 prof_frame_time = 0; |
37 | #define PROF_SHOW_X 0 | 34 | u32 prof_frame_count = 0; |
38 | #endif | 35 | u32 prof_frame_avg = -1; |
39 | #ifndef PROF_SHOW_Y | 36 | u32 prof_frame_time_max = 0; |
40 | #define PROF_SHOW_Y 0 | 37 | u32 prof_times[PROF_NUM] = {0}; |
41 | #endif | 38 | u32 prof_count[PROF_NUM] = {0}; |
39 | u32 prof_avg[PROF_NUM] = {0}; | ||
40 | u32 prof_max[PROF_NUM] = {0}; | ||
41 | u32 prof_min[PROF_NUM] = {0}; | ||
42 | 42 | ||
43 | static bool profile_show = true; | 43 | bool prof_reset_minmax = PROF_RESET_MINMAX; |
44 | bool prof_show = true; | ||
44 | 45 | ||
45 | #define PROF_SHOW() \ | 46 | #define PROF_INIT() do { \ |
46 | do { \ | 47 | for (size_t i = 0; i < PROF_NUM; i++) { \ |
47 | if (key_tap(KEY_START)) {\ | 48 | prof_min[i] = -1; \ |
48 | profile_show ^= 1;\ | 49 | } \ |
49 | }\ | 50 | } while(0); |
50 | if (profile_show) {\ | ||
51 | txt_color(1);\ | ||
52 | txt_position((PROF_SHOW_X), (PROF_SHOW_Y));\ | ||
53 | draw_filled_rect((PROF_SHOW_X), (PROF_SHOW_X), 8 * 14, 8 * 10, 0);\ | ||
54 | txt_printf("VIDEO\n");\ | ||
55 | txt_printf(">CLEAR %.8lu\n", avg_clear_cycles);\ | ||
56 | txt_printf(">FLIP %.8lu\n", avg_flip_cycles);\ | ||
57 | txt_printf("SEQUENCER RENDER\n");\ | ||
58 | txt_printf(">TRIGS %.8lu\n", avg_draw_trigs_cycles);\ | ||
59 | txt_printf(">BTNS %.8lu\n", avg_draw_btns_cycles);\ | ||
60 | txt_printf(">PARAM %.8lu\n", avg_draw_param_cycles);\ | ||
61 | txt_printf(">PIANO %.8lu\n", avg_draw_piano_cycles);\ | ||
62 | txt_printf(">CURSOR %.8lu\n", avg_draw_cursor_cycles);\ | ||
63 | txt_printf("UPDATE %.8lu\n", avg_update_cycles);\ | ||
64 | txt_printf("INPUT %.8lu\n", avg_input_cycles);\ | ||
65 | txt_printf("RENDER %.8lu\n", avg_render_cycles);\ | ||
66 | txt_printf("TOTAL %.8lu\n", avg_frame_cycles);\ | ||
67 | txt_render();\ | ||
68 | }\ | ||
69 | u32 frame_time =\ | ||
70 | FP_DIV(\ | ||
71 | FP_NUM(avg_frame_cycles + 1, 2),\ | ||
72 | FP_NUM(2809, 2),\ | ||
73 | 2) * 166;\ | ||
74 | u32 fps =\ | ||
75 | FP_DIV(\ | ||
76 | FP_NUM(280896 * 60, 2),\ | ||
77 | FP_NUM(avg_frame_cycles + 1, 2),\ | ||
78 | 2);\ | ||
79 | draw_filled_rect(8 * 18, 0, 239, 16, 0);\ | ||
80 | txt_drawf("TIME: %.6lu", 8 * 18, 0, 1, frame_time >> 2);\ | ||
81 | txt_drawf("MAX FPS: %.4lu", 8 * 18, 8, 1, (fps >> 2) + 1);\ | ||
82 | } while (0) | ||
83 | 51 | ||
84 | static u32 prof_frame_counter = 0; | 52 | #define PROF(func, idx) do { \ |
53 | u32 time_before = profile_measure(); \ | ||
54 | (func); \ | ||
55 | u32 time_after = profile_measure(); \ | ||
56 | u32 time_current = time_after - time_before; \ | ||
57 | prof_times[idx] += time_current; \ | ||
58 | prof_count[idx]++; \ | ||
59 | prof_max[idx] = MAX(time_current, prof_max[idx]);\ | ||
60 | prof_min[idx] = MIN(time_current, prof_min[idx]);\ | ||
61 | } while(0); | ||
85 | 62 | ||
86 | static u32 frame_cycles = 0; | 63 | #define FRAME_START() do { \ |
87 | static u32 flip_cycles = 0; | 64 | profile_start();\ |
88 | static u32 clear_cycles = 0; | 65 | } while(0) |
89 | static u32 input_cycles = 0; | ||
90 | static u32 draw_trigs_cycles = 0; | ||
91 | static u32 draw_btn_cycles = 0; | ||
92 | static u32 draw_piano_cycles = 0; | ||
93 | static u32 draw_param_cycles = 0; | ||
94 | static u32 draw_cursor_cycles = 0; | ||
95 | static u32 render_cycles = 0; | ||
96 | static u32 update_cycles = 0; | ||
97 | 66 | ||
98 | static u32 avg_frame_cycles = 0; | 67 | #define FRAME_END() do { \ |
99 | static u32 avg_flip_cycles = 0; | 68 | prof_frame_count++;\ |
100 | static u32 avg_clear_cycles = 0; | 69 | prof_frame_time_max = MAX(prof_frame_time_max, profile_measure());\ |
101 | static u32 avg_input_cycles = 0; | 70 | prof_frame_time += profile_stop();\ |
102 | static u32 avg_draw_trigs_cycles = 0; | 71 | if (prof_show) { \ |
103 | static u32 avg_draw_btns_cycles = 0; | 72 | draw_filled_rect(0, 0, SCREEN_WIDTH - 1, 8 * (PROF_NUM + 1), 0); \ |
104 | static u32 avg_draw_piano_cycles = 0; | 73 | txt_drawf_small("FRAME TIME/FPS: %.9l/%.2l", 0, 0, COL_FG, \ |
105 | static u32 avg_draw_param_cycles = 0; | 74 | prof_frame_avg, \ |
106 | static u32 avg_draw_cursor_cycles = 0; | 75 | (u32)((u64)280896 * 60 / (prof_frame_avg + 1)));\ |
107 | static u32 avg_render_cycles = 0; | 76 | txt_drawf_small("MAX: %.9l/%l", 8 * 19, 0, COL_FG, \ |
108 | static u32 avg_update_cycles = 0; | 77 | prof_frame_time_max,280896);\ |
78 | for (size_t idx = 0; idx < PROF_NUM; idx++) { \ | ||
79 | txt_drawf_small("%s %.9l (%.9l %.9l) %08x:%08x", 0, 8 * (idx + 1), COL_FG, \ | ||
80 | prof_type_str[idx], \ | ||
81 | prof_avg[idx], \ | ||
82 | prof_min[idx], \ | ||
83 | prof_max[idx], \ | ||
84 | prof_avg[idx], \ | ||
85 | prof_max[idx]);\ | ||
86 | }; \ | ||
87 | } \ | ||
88 | if (prof_frame_count >= PROF_ENABLE) { \ | ||
89 | for (size_t idx = 0; idx < PROF_NUM; idx++) { \ | ||
90 | prof_avg[idx] = prof_times[idx] / prof_frame_count; \ | ||
91 | if (prof_reset_minmax) { \ | ||
92 | prof_min[idx] = -1; \ | ||
93 | prof_max[idx] = 0; \ | ||
94 | } \ | ||
95 | prof_times[idx] = 0; \ | ||
96 | prof_count[idx] = 0; \ | ||
97 | }; \ | ||
98 | prof_frame_avg = prof_frame_time / prof_frame_count; \ | ||
99 | prof_frame_count = 0; \ | ||
100 | prof_frame_time = 0; \ | ||
101 | } \ | ||
102 | } while(0) | ||
109 | 103 | ||
110 | #if PROF_ENABLE == 1 | 104 | #define PROF_SHOW() do { \ |
111 | #define FRAME_START()\ | 105 | prof_show ^= 1; \ |
112 | do { \ | 106 | } while(0) |
113 | if (prof_frame_counter == PROF_N_FRAMES) {\ | ||
114 | avg_frame_cycles = frame_cycles / prof_frame_counter;\ | ||
115 | avg_flip_cycles = flip_cycles / prof_frame_counter;\ | ||
116 | avg_clear_cycles = clear_cycles / prof_frame_counter;\ | ||
117 | avg_draw_trigs_cycles = draw_trigs_cycles / prof_frame_counter;\ | ||
118 | avg_draw_btns_cycles = draw_btn_cycles / prof_frame_counter;\ | ||
119 | avg_draw_piano_cycles = draw_piano_cycles / prof_frame_counter;\ | ||
120 | avg_draw_param_cycles = draw_param_cycles / prof_frame_counter;\ | ||
121 | avg_draw_cursor_cycles = draw_cursor_cycles / prof_frame_counter;\ | ||
122 | avg_input_cycles = input_cycles / prof_frame_counter;\ | ||
123 | avg_render_cycles = render_cycles / prof_frame_counter;\ | ||
124 | avg_update_cycles = update_cycles / prof_frame_counter;\ | ||
125 | frame_cycles = 0;\ | ||
126 | flip_cycles = 0;\ | ||
127 | clear_cycles = 0;\ | ||
128 | input_cycles = 0;\ | ||
129 | render_cycles = 0;\ | ||
130 | update_cycles = 0;\ | ||
131 | draw_trigs_cycles = 0;\ | ||
132 | draw_param_cycles = 0;\ | ||
133 | draw_cursor_cycles = 0;\ | ||
134 | draw_btn_cycles = 0;\ | ||
135 | draw_piano_cycles = 0;\ | ||
136 | prof_frame_counter = 0;\ | ||
137 | }\ | ||
138 | profile_start();\ | ||
139 | } while (0) | ||
140 | #elif PROF_ENABLE == 2 | ||
141 | #define FRAME_START()\ | ||
142 | do { \ | ||
143 | if (prof_frame_counter == PROF_N_FRAMES) {\ | ||
144 | avg_frame_cycles = frame_cycles;\ | ||
145 | avg_flip_cycles = flip_cycles;\ | ||
146 | avg_clear_cycles = clear_cycles;\ | ||
147 | avg_line_cycles = line_cycles;\ | ||
148 | avg_rect_cycles = rect_cycles;\ | ||
149 | avg_fill_rect_cycles = fill_rect_cycles;\ | ||
150 | avg_chr_cycles = chr_cycles;\ | ||
151 | avg_icn_cycles = icn_cycles;\ | ||
152 | avg_txt_drawf_cycles = txt_drawf_cycles;\ | ||
153 | avg_txt_printf_cycles = txt_printf_cycles;\ | ||
154 | avg_txt_render_cycles = txt_render_cycles;\ | ||
155 | avg_txt_clear_cycles = txt_clear_cycles;\ | ||
156 | avg_input_cycles = input_cycles;\ | ||
157 | frame_cycles = 0;\ | ||
158 | flip_cycles = 0;\ | ||
159 | clear_cycles = 0;\ | ||
160 | line_cycles = 0;\ | ||
161 | rect_cycles = 0;\ | ||
162 | fill_rect_cycles = 0;\ | ||
163 | chr_cycles = 0;\ | ||
164 | icn_cycles = 0;\ | ||
165 | txt_drawf_cycles = 0;\ | ||
166 | txt_printf_cycles = 0;\ | ||
167 | txt_render_cycles = 0;\ | ||
168 | txt_clear_cycles = 0;\ | ||
169 | input_cycles = 0;\ | ||
170 | prof_frame_counter = 0;\ | ||
171 | }\ | ||
172 | profile_start();\ | ||
173 | } while (0) | ||
174 | #endif | ||
175 | |||
176 | #define FRAME_END() \ | ||
177 | do { \ | ||
178 | prof_frame_counter++;\ | ||
179 | frame_cycles += profile_stop();\ | ||
180 | } while (0) | ||
181 | 107 | ||
182 | #else | 108 | #else |
183 | 109 | ||
184 | // No profiling. | 110 | // No profiling. |
185 | #define PROF(F,VAR) (F) | 111 | #define PROF_INIT() |
186 | #define PROF_SHOW() | 112 | #define PROF(F,VAR) do {F;} while(0) |
187 | #define FRAME_START() | 113 | #define FRAME_START() |
188 | #define FRAME_END() | 114 | #define FRAME_END() |
115 | #define PROF_SHOW() | ||
189 | #endif | 116 | #endif |
diff --git a/src/sequencer.c b/src/sequencer.c index c01f905..4f46e1f 100644 --- a/src/sequencer.c +++ b/src/sequencer.c | |||
@@ -351,7 +351,6 @@ IWRAM_CODE | |||
351 | UNROLL_LOOPS | 351 | UNROLL_LOOPS |
352 | void | 352 | void |
353 | wave_ad_tick(void) { | 353 | wave_ad_tick(void) { |
354 | Wave wave_active = {0}; | ||
355 | Wave wave_zero = { | 354 | Wave wave_zero = { |
356 | 0x77777777, 0x77777777, 0x77777777, 0x77777777, | 355 | 0x77777777, 0x77777777, 0x77777777, 0x77777777, |
357 | }; | 356 | }; |
diff --git a/src/settings.c b/src/settings.c index 9fc2f3d..3e8138e 100644 --- a/src/settings.c +++ b/src/settings.c | |||
@@ -31,7 +31,7 @@ set_audio_settings(void) { | |||
31 | case SYNC_IN_LINK_4BPQ: { irs_set(IRQ_SERIAL, sync_in_4); } break; | 31 | case SYNC_IN_LINK_4BPQ: { irs_set(IRQ_SERIAL, sync_in_4); } break; |
32 | default: break; | 32 | default: break; |
33 | } | 33 | } |
34 | irs_set(IRQ_TIMER_2, NULL); | 34 | irs_set(IRQ_TIMER_3, NULL); |
35 | SIO_MODE = SIO_MODE_GP | 35 | SIO_MODE = SIO_MODE_GP |
36 | | SIO_SC_OUT(0) | 36 | | SIO_SC_OUT(0) |
37 | | SIO_SD_OUT(0) | 37 | | SIO_SD_OUT(0) |