| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- #include <furi.h>
- #include "speaker_hal.h"
- #include "zero_tracker.h"
- /**
- * @brief Note record
- *
- * AH AL
- * FEDCBA98 76543210
- * nnnnnnee eedddddd
- * -------- --------
- * nnnnnn = [0] note kill, [1..60] note number, [61..63] service values
- * ee ee = [0..F] effect
- * 111222 = [0..63] or [0..7, 0..7] effect data
- */
- typedef uint16_t NoteRecord;
- #define NOTE_NONE 0
- #define NOTE_C2 1
- #define NOTE_Cs2 2
- #define NOTE_D2 3
- #define NOTE_Ds2 4
- #define NOTE_E2 5
- #define NOTE_F2 6
- #define NOTE_Fs2 7
- #define NOTE_G2 8
- #define NOTE_Gs2 9
- #define NOTE_A2 10
- #define NOTE_As2 11
- #define NOTE_B2 12
- #define NOTE_C3 13
- #define NOTE_Cs3 14
- #define NOTE_D3 15
- #define NOTE_Ds3 16
- #define NOTE_E3 17
- #define NOTE_F3 18
- #define NOTE_Fs3 19
- #define NOTE_G3 20
- #define NOTE_Gs3 21
- #define NOTE_A3 22
- #define NOTE_As3 23
- #define NOTE_B3 24
- #define NOTE_C4 25
- #define NOTE_Cs4 26
- #define NOTE_D4 27
- #define NOTE_Ds4 28
- #define NOTE_E4 29
- #define NOTE_F4 30
- #define NOTE_Fs4 31
- #define NOTE_G4 32
- #define NOTE_Gs4 33
- #define NOTE_A4 34
- #define NOTE_As4 35
- #define NOTE_B4 36
- #define NOTE_C5 37
- #define NOTE_Cs5 38
- #define NOTE_D5 39
- #define NOTE_Ds5 40
- #define NOTE_E5 41
- #define NOTE_F5 42
- #define NOTE_Fs5 43
- #define NOTE_G5 44
- #define NOTE_Gs5 45
- #define NOTE_A5 46
- #define NOTE_As5 47
- #define NOTE_B5 48
- #define NOTE_C6 49
- #define NOTE_Cs6 50
- #define NOTE_D6 51
- #define NOTE_Ds6 52
- #define NOTE_E6 53
- #define NOTE_F6 54
- #define NOTE_Fs6 55
- #define NOTE_G6 56
- #define NOTE_Gs6 57
- #define NOTE_A6 58
- #define NOTE_As6 59
- #define NOTE_B6 60
- #define NOTE_KILL 63
- uint8_t record_get_note(NoteRecord note) {
- return note & 0x3F;
- }
- uint8_t record_get_effect(NoteRecord note) {
- return (note >> 6) & 0xF;
- }
- uint8_t record_get_effect_data(NoteRecord note) {
- return (note >> 10) & 0x3F;
- }
- #define RECORD_MAKE(note, effect, data) \
- ((NoteRecord)(((note)&0x3F) | (((effect)&0xF) << 6) | (((data)&0x3F) << 10)))
- #define NOTES_PER_OCT 12
- const float notes_oct[NOTES_PER_OCT] = {
- 130.813f,
- 138.591f,
- 146.832f,
- 155.563f,
- 164.814f,
- 174.614f,
- 184.997f,
- 195.998f,
- 207.652f,
- 220.00f,
- 233.082f,
- 246.942f,
- };
- float note_to_freq(uint8_t note) {
- if(note == NOTE_NONE) return 0.0f;
- note = note - NOTE_C2;
- uint8_t octave = note / NOTES_PER_OCT;
- uint8_t note_in_oct = note % NOTES_PER_OCT;
- return notes_oct[note_in_oct] * (1 << octave);
- }
- #define PATTERN_SIZE 64
- typedef struct {
- NoteRecord notes[PATTERN_SIZE];
- } NoteRow;
- typedef struct {
- uint8_t row_count;
- NoteRow* rows;
- } NotePattern;
- NoteRow row = {
- .notes =
- {
- //
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_C3, 0, 0),
- RECORD_MAKE(NOTE_F2, 0, 0),
- RECORD_MAKE(NOTE_C3, 0, 0),
- //
- RECORD_MAKE(NOTE_E4, 0, 0),
- RECORD_MAKE(NOTE_C3, 0, 0),
- RECORD_MAKE(NOTE_E4, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_E5, 0, 0),
- RECORD_MAKE(NOTE_E5, 0, 0),
- RECORD_MAKE(NOTE_E5, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_D5, 0, 0),
- RECORD_MAKE(NOTE_C3, 0, 0),
- RECORD_MAKE(NOTE_F2, 0, 0),
- RECORD_MAKE(NOTE_C3, 0, 0),
- //
- RECORD_MAKE(NOTE_C5, 0, 0),
- RECORD_MAKE(NOTE_C3, 0, 0),
- RECORD_MAKE(NOTE_C5, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(0, 0, 0),
- RECORD_MAKE(0, 0, 0),
- RECORD_MAKE(0, 0, 0),
- //
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_B4, 0, 0),
- RECORD_MAKE(NOTE_D3, 0, 0),
- RECORD_MAKE(NOTE_G2, 0, 0),
- RECORD_MAKE(NOTE_D3, 0, 0),
- //
- RECORD_MAKE(NOTE_E4, 0, 0),
- RECORD_MAKE(NOTE_D3, 0, 0),
- RECORD_MAKE(NOTE_E4, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_E5, 0, 0),
- RECORD_MAKE(NOTE_E5, 0, 0),
- RECORD_MAKE(NOTE_E5, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_D5, 0, 0),
- RECORD_MAKE(NOTE_D3, 0, 0),
- RECORD_MAKE(NOTE_G2, 0, 0),
- RECORD_MAKE(NOTE_D3, 0, 0),
- //
- RECORD_MAKE(NOTE_C5, 0, 0),
- RECORD_MAKE(NOTE_D3, 0, 0),
- RECORD_MAKE(NOTE_C5, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- //
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(0, 0, 0),
- RECORD_MAKE(0, 0, 0),
- RECORD_MAKE(0, 0, 0),
- //
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_A4, 0, 0),
- RECORD_MAKE(NOTE_KILL, 0, 0),
- },
- };
- uint8_t counter = 0;
- uint8_t counter_limit = 2;
- uint8_t row_counter = 0;
- void tracker_interrupt_body() {
- if(counter == 0) {
- uint8_t note = record_get_note(row.notes[row_counter]);
- if(note == NOTE_KILL) {
- tracker_speaker_stop();
- } else if(note > 0 && note < NOTE_KILL) {
- float freq = note_to_freq(note);
- tracker_speaker_play(freq, 0.5f);
- }
- row_counter = (row_counter + 1) % PATTERN_SIZE;
- }
- counter = (counter + 1) % counter_limit;
- }
- void tracker_interrupt_cb() {
- tracker_debug_set(true);
- tracker_interrupt_body();
- tracker_debug_set(false);
- }
- int32_t zero_tracker_app(void* p) {
- UNUSED(p);
- tracker_debug_init();
- tracker_speaker_init();
- tracker_interrupt_init(60.0f, tracker_interrupt_cb, NULL);
- while(1) {
- furi_delay_ms(1000);
- }
- return 0;
- }
|