Sfoglia il codice sorgente

add sample and wavetable examples, parsers for both

Jack Humbert 7 anni fa
parent
commit
f52faeb5d6

+ 39 - 0
keyboards/planck/keymaps/synth_sample/config.h

@@ -0,0 +1,39 @@
+#pragma once
+
+#ifdef AUDIO_ENABLE
+    #define STARTUP_SONG SONG(PLANCK_SOUND)
+    // #define STARTUP_SONG SONG(NO_SOUND)
+
+    #define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \
+                                  SONG(COLEMAK_SOUND), \
+                                  SONG(DVORAK_SOUND) \
+                                }
+#endif
+
+/*
+ * MIDI options
+ */
+
+/* Prevent use of disabled MIDI features in the keymap */
+//#define MIDI_ENABLE_STRICT 1
+
+/* enable basic MIDI features:
+   - MIDI notes can be sent when in Music mode is on
+*/
+
+#define MIDI_BASIC
+
+/* enable advanced MIDI features:
+   - MIDI notes can be added to the keymap
+   - Octave shift and transpose
+   - Virtual sustain, portamento, and modulation wheel
+   - etc.
+*/
+//#define MIDI_ADVANCED
+
+/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
+//#define MIDI_TONE_KEYCODE_OCTAVES 2
+
+// Most tactile encoders have detents every 4 stages
+#define ENCODER_RESOLUTION 4
+

+ 298 - 0
keyboards/planck/keymaps/synth_sample/keymap.c

@@ -0,0 +1,298 @@
+/* Copyright 2019 Jack Humbert
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include QMK_KEYBOARD_H
+
+extern keymap_config_t keymap_config;
+
+enum planck_layers {
+  _QWERTY,
+  _COLEMAK,
+  _DVORAK,
+  _LOWER,
+  _RAISE,
+  _PLOVER,
+  _ADJUST
+};
+
+enum planck_keycodes {
+  QWERTY = SAFE_RANGE,
+  COLEMAK,
+  DVORAK,
+  PLOVER,
+  BACKLIT,
+  EXT_PLV
+};
+
+#define LOWER MO(_LOWER)
+#define RAISE MO(_RAISE)
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   Q  |   W  |   E  |   R  |   T  |   Y  |   U  |   I  |   O  |   P  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   S  |   D  |   F  |   G  |   H  |   J  |   K  |   L  |   ;  |  "   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   Z  |   X  |   C  |   V  |   B  |   N  |   M  |   ,  |   .  |   /  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QWERTY] = LAYOUT_planck_grid(
+    KC_TAB,  KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_BSPC,
+    KC_ESC,  KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT,
+    KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT ,
+    BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
+),
+
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   Q  |   W  |   F  |   P  |   G  |   J  |   L  |   U  |   Y  |   ;  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   R  |   S  |   T  |   D  |   H  |   N  |   E  |   I  |   O  |  "   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   Z  |   X  |   C  |   V  |   B  |   K  |   M  |   ,  |   .  |   /  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_COLEMAK] = LAYOUT_planck_grid(
+    KC_TAB,  KC_Q,    KC_W,    KC_F,    KC_P,    KC_G,    KC_J,    KC_L,    KC_U,    KC_Y,    KC_SCLN, KC_BSPC,
+    KC_ESC,  KC_A,    KC_R,    KC_S,    KC_T,    KC_D,    KC_H,    KC_N,    KC_E,    KC_I,    KC_O,    KC_QUOT,
+    KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_K,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT ,
+    BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
+),
+
+/* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   "  |   ,  |   .  |   P  |   Y  |   F  |   G  |   C  |   R  |   L  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   O  |   E  |   U  |   I  |   D  |   H  |   T  |   N  |   S  |  /   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   ;  |   Q  |   J  |   K  |   X  |   B  |   M  |   W  |   V  |   Z  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_DVORAK] = LAYOUT_planck_grid(
+    KC_TAB,  KC_QUOT, KC_COMM, KC_DOT,  KC_P,    KC_Y,    KC_F,    KC_G,    KC_C,    KC_R,    KC_L,    KC_BSPC,
+    KC_ESC,  KC_A,    KC_O,    KC_E,    KC_U,    KC_I,    KC_D,    KC_H,    KC_T,    KC_N,    KC_S,    KC_SLSH,
+    KC_LSFT, KC_SCLN, KC_Q,    KC_J,    KC_K,    KC_X,    KC_B,    KC_M,    KC_W,    KC_V,    KC_Z,    KC_ENT ,
+    BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
+),
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * |   ~  |   !  |   @  |   #  |   $  |   %  |   ^  |   &  |   *  |   (  |   )  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del  |  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   _  |   +  |   {  |   }  |  |   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |ISO ~ |ISO | | Home | End  |      |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LOWER] = LAYOUT_planck_grid(
+    KC_TILD, KC_EXLM, KC_AT,   KC_HASH, KC_DLR,  KC_PERC, KC_CIRC, KC_AMPR,    KC_ASTR,    KC_LPRN, KC_RPRN, KC_BSPC,
+    KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_UNDS,    KC_PLUS,    KC_LCBR, KC_RCBR, KC_PIPE,
+    _______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  S(KC_NUHS), S(KC_NUBS), KC_HOME, KC_END,  _______,
+    _______, _______, _______, _______, _______, _______, _______, _______,    KC_MNXT,    KC_VOLD, KC_VOLU, KC_MPLY
+),
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * |   `  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |   9  |   0  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del  |  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   -  |   =  |   [  |   ]  |  \   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |ISO # |ISO / |Pg Up |Pg Dn |      |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RAISE] = LAYOUT_planck_grid(
+    KC_GRV,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,    KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_BSPC,
+    KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_MINS, KC_EQL,  KC_LBRC, KC_RBRC, KC_BSLS,
+    _______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, _______,
+    _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY
+),
+
+/* Plover layer (http://opensteno.org)
+ * ,-----------------------------------------------------------------------------------.
+ * |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * |      |   S  |   T  |   P  |   H  |   *  |   *  |   F  |   P  |   L  |   T  |   D  |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |   S  |   K  |   W  |   R  |   *  |   *  |   R  |   B  |   G  |   S  |   Z  |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Exit |      |      |   A  |   O  |             |   E  |   U  |      |      |      |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_PLOVER] = LAYOUT_planck_grid(
+    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1   ,
+    XXXXXXX, KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_LBRC,
+    XXXXXXX, KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT,
+    EXT_PLV, XXXXXXX, XXXXXXX, KC_C,    KC_V,    XXXXXXX, XXXXXXX, KC_N,    KC_M,    XXXXXXX, XXXXXXX, XXXXXXX
+),
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * |      | Reset|      |      |      |      |      |      |      |      |      |  Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * |      |      |      |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak|Plover|      |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |Voice-|Voice+|Mus on|Musoff|MIDIon|MIDIof|      |      |      |      |      |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      |      |      |      |      |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_ADJUST] = LAYOUT_planck_grid(
+    _______, RESET,   DEBUG,   RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD,  RGB_VAI, RGB_VAD, KC_DEL ,
+    _______, _______, MU_MOD,  AU_ON,   AU_OFF,  AG_NORM, AG_SWAP, QWERTY,  COLEMAK,  DVORAK,  PLOVER,  _______,
+    _______, MUV_DE,  MUV_IN,  MU_ON,   MU_OFF,  MI_ON,   MI_OFF,  TERM_ON, TERM_OFF, _______, _______, _______,
+    _______, _______, _______, _______, _______, _______, _______, _______, _______,  _______, _______, _______
+)
+
+};
+
+#ifdef AUDIO_ENABLE
+  float plover_song[][2]     = SONG(PLOVER_SOUND);
+  float plover_gb_song[][2]  = SONG(PLOVER_GOODBYE_SOUND);
+#endif
+
+uint32_t layer_state_set_user(uint32_t state) {
+  return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+  switch (keycode) {
+    case QWERTY:
+      if (record->event.pressed) {
+        print("mode just switched to qwerty and this is a huge string\n");
+        set_single_persistent_default_layer(_QWERTY);
+      }
+      return false;
+      break;
+    case COLEMAK:
+      if (record->event.pressed) {
+        set_single_persistent_default_layer(_COLEMAK);
+      }
+      return false;
+      break;
+    case DVORAK:
+      if (record->event.pressed) {
+        set_single_persistent_default_layer(_DVORAK);
+      }
+      return false;
+      break;
+    case BACKLIT:
+      if (record->event.pressed) {
+        register_code(KC_RSFT);
+        #ifdef BACKLIGHT_ENABLE
+          backlight_step();
+        #endif
+        #ifdef KEYBOARD_planck_rev5
+          PORTE &= ~(1<<6);
+        #endif
+      } else {
+        unregister_code(KC_RSFT);
+        #ifdef KEYBOARD_planck_rev5
+          PORTE |= (1<<6);
+        #endif
+      }
+      return false;
+      break;
+    case PLOVER:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          stop_all_notes();
+          PLAY_SONG(plover_song);
+        #endif
+        layer_off(_RAISE);
+        layer_off(_LOWER);
+        layer_off(_ADJUST);
+        layer_on(_PLOVER);
+        if (!eeconfig_is_enabled()) {
+            eeconfig_init();
+        }
+        keymap_config.raw = eeconfig_read_keymap();
+        keymap_config.nkro = 1;
+        eeconfig_update_keymap(keymap_config.raw);
+      }
+      return false;
+      break;
+    case EXT_PLV:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          PLAY_SONG(plover_gb_song);
+        #endif
+        layer_off(_PLOVER);
+      }
+      return false;
+      break;
+  }
+  return true;
+}
+
+void encoder_update(bool clockwise) {
+    if (clockwise) {
+      #ifdef MOUSEKEY_ENABLE
+        register_code(KC_MS_WH_DOWN);
+        unregister_code(KC_MS_WH_DOWN);
+      #else
+        register_code(KC_PGDN);
+        unregister_code(KC_PGDN);
+      #endif
+    } else {
+      #ifdef MOUSEKEY_ENABLE
+        register_code(KC_MS_WH_UP);
+        unregister_code(KC_MS_WH_UP);
+      #else
+        register_code(KC_PGUP);
+        unregister_code(KC_PGUP);
+      #endif
+    }
+}
+
+void matrix_scan_user(void) {
+
+}
+
+bool music_mask_user(uint16_t keycode) {
+  switch (keycode) {
+    case RAISE:
+    case LOWER:
+      return false;
+    default:
+      return true;
+  }
+}
+
+#include "sample.h"
+
+uint32_t dac_sample_custom_counter = 0;
+
+uint16_t dac_value_generate(void) {
+  if (is_playing_note()) {
+    uint16_t sample = dac_sample_custom[dac_sample_custom_counter];
+    dac_sample_custom_counter = (dac_sample_custom_counter + 1) % DAC_SAMPLE_CUSTOM_LENGTH;
+    return sample;
+  } else {
+    return DAC_OFF_VALUE;
+  }
+}

+ 0 - 0
keyboards/planck/keymaps/synth_sample/rules.mk


File diff suppressed because it is too large
+ 3780 - 0
keyboards/planck/keymaps/synth_sample/sample.h


+ 39 - 0
keyboards/planck/keymaps/synth_wavetable/config.h

@@ -0,0 +1,39 @@
+#pragma once
+
+#ifdef AUDIO_ENABLE
+    #define STARTUP_SONG SONG(PLANCK_SOUND)
+    // #define STARTUP_SONG SONG(NO_SOUND)
+
+    #define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \
+                                  SONG(COLEMAK_SOUND), \
+                                  SONG(DVORAK_SOUND) \
+                                }
+#endif
+
+/*
+ * MIDI options
+ */
+
+/* Prevent use of disabled MIDI features in the keymap */
+//#define MIDI_ENABLE_STRICT 1
+
+/* enable basic MIDI features:
+   - MIDI notes can be sent when in Music mode is on
+*/
+
+#define MIDI_BASIC
+
+/* enable advanced MIDI features:
+   - MIDI notes can be added to the keymap
+   - Octave shift and transpose
+   - Virtual sustain, portamento, and modulation wheel
+   - etc.
+*/
+//#define MIDI_ADVANCED
+
+/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */
+//#define MIDI_TONE_KEYCODE_OCTAVES 2
+
+// Most tactile encoders have detents every 4 stages
+#define ENCODER_RESOLUTION 4
+

+ 326 - 0
keyboards/planck/keymaps/synth_wavetable/keymap.c

@@ -0,0 +1,326 @@
+/* Copyright 2019 Jack Humbert
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include QMK_KEYBOARD_H
+#include "audio.h"
+
+extern keymap_config_t keymap_config;
+
+enum planck_layers {
+  _QWERTY,
+  _COLEMAK,
+  _DVORAK,
+  _LOWER,
+  _RAISE,
+  _PLOVER,
+  _ADJUST
+};
+
+enum planck_keycodes {
+  QWERTY = SAFE_RANGE,
+  COLEMAK,
+  DVORAK,
+  PLOVER,
+  BACKLIT,
+  EXT_PLV
+};
+
+#define LOWER MO(_LOWER)
+#define RAISE MO(_RAISE)
+
+const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
+
+/* Qwerty
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   Q  |   W  |   E  |   R  |   T  |   Y  |   U  |   I  |   O  |   P  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   S  |   D  |   F  |   G  |   H  |   J  |   K  |   L  |   ;  |  "   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   Z  |   X  |   C  |   V  |   B  |   N  |   M  |   ,  |   .  |   /  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_QWERTY] = LAYOUT_planck_grid(
+    KC_TAB,  KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_BSPC,
+    KC_ESC,  KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT,
+    KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_N,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT ,
+    BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
+),
+
+/* Colemak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   Q  |   W  |   F  |   P  |   G  |   J  |   L  |   U  |   Y  |   ;  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   R  |   S  |   T  |   D  |   H  |   N  |   E  |   I  |   O  |  "   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   Z  |   X  |   C  |   V  |   B  |   K  |   M  |   ,  |   .  |   /  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_COLEMAK] = LAYOUT_planck_grid(
+    KC_TAB,  KC_Q,    KC_W,    KC_F,    KC_P,    KC_G,    KC_J,    KC_L,    KC_U,    KC_Y,    KC_SCLN, KC_BSPC,
+    KC_ESC,  KC_A,    KC_R,    KC_S,    KC_T,    KC_D,    KC_H,    KC_N,    KC_E,    KC_I,    KC_O,    KC_QUOT,
+    KC_LSFT, KC_Z,    KC_X,    KC_C,    KC_V,    KC_B,    KC_K,    KC_M,    KC_COMM, KC_DOT,  KC_SLSH, KC_ENT ,
+    BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
+),
+
+/* Dvorak
+ * ,-----------------------------------------------------------------------------------.
+ * | Tab  |   "  |   ,  |   .  |   P  |   Y  |   F  |   G  |   C  |   R  |   L  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Esc  |   A  |   O  |   E  |   U  |   I  |   D  |   H  |   T  |   N  |   S  |  /   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * | Shift|   ;  |   Q  |   J  |   K  |   X  |   B  |   M  |   W  |   V  |   Z  |Enter |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Brite| Ctrl | Alt  | GUI  |Lower |    Space    |Raise | Left | Down |  Up  |Right |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_DVORAK] = LAYOUT_planck_grid(
+    KC_TAB,  KC_QUOT, KC_COMM, KC_DOT,  KC_P,    KC_Y,    KC_F,    KC_G,    KC_C,    KC_R,    KC_L,    KC_BSPC,
+    KC_ESC,  KC_A,    KC_O,    KC_E,    KC_U,    KC_I,    KC_D,    KC_H,    KC_T,    KC_N,    KC_S,    KC_SLSH,
+    KC_LSFT, KC_SCLN, KC_Q,    KC_J,    KC_K,    KC_X,    KC_B,    KC_M,    KC_W,    KC_V,    KC_Z,    KC_ENT ,
+    BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER,   KC_SPC,  KC_SPC,  RAISE,   KC_LEFT, KC_DOWN, KC_UP,   KC_RGHT
+),
+
+/* Lower
+ * ,-----------------------------------------------------------------------------------.
+ * |   ~  |   !  |   @  |   #  |   $  |   %  |   ^  |   &  |   *  |   (  |   )  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del  |  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   _  |   +  |   {  |   }  |  |   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |ISO ~ |ISO | | Home | End  |      |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_LOWER] = LAYOUT_planck_grid(
+    KC_TILD, KC_EXLM, KC_AT,   KC_HASH, KC_DLR,  KC_PERC, KC_CIRC, KC_AMPR,    KC_ASTR,    KC_LPRN, KC_RPRN, KC_BSPC,
+    KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_UNDS,    KC_PLUS,    KC_LCBR, KC_RCBR, KC_PIPE,
+    _______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  S(KC_NUHS), S(KC_NUBS), KC_HOME, KC_END,  _______,
+    _______, _______, _______, _______, _______, _______, _______, _______,    KC_MNXT,    KC_VOLD, KC_VOLU, KC_MPLY
+),
+
+/* Raise
+ * ,-----------------------------------------------------------------------------------.
+ * |   `  |   1  |   2  |   3  |   4  |   5  |   6  |   7  |   8  |   9  |   0  | Bksp |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * | Del  |  F1  |  F2  |  F3  |  F4  |  F5  |  F6  |   -  |   =  |   [  |   ]  |  \   |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |ISO # |ISO / |Pg Up |Pg Dn |      |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      | Next | Vol- | Vol+ | Play |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_RAISE] = LAYOUT_planck_grid(
+    KC_GRV,  KC_1,    KC_2,    KC_3,    KC_4,    KC_5,    KC_6,    KC_7,    KC_8,    KC_9,    KC_0,    KC_BSPC,
+    KC_DEL,  KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,   KC_F6,   KC_MINS, KC_EQL,  KC_LBRC, KC_RBRC, KC_BSLS,
+    _______, KC_F7,   KC_F8,   KC_F9,   KC_F10,  KC_F11,  KC_F12,  KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, _______,
+    _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY
+),
+
+/* Plover layer (http://opensteno.org)
+ * ,-----------------------------------------------------------------------------------.
+ * |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |   #  |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * |      |   S  |   T  |   P  |   H  |   *  |   *  |   F  |   P  |   L  |   T  |   D  |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |   S  |   K  |   W  |   R  |   *  |   *  |   R  |   B  |   G  |   S  |   Z  |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * | Exit |      |      |   A  |   O  |             |   E  |   U  |      |      |      |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_PLOVER] = LAYOUT_planck_grid(
+    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1,    KC_1   ,
+    XXXXXXX, KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,    KC_Y,    KC_U,    KC_I,    KC_O,    KC_P,    KC_LBRC,
+    XXXXXXX, KC_A,    KC_S,    KC_D,    KC_F,    KC_G,    KC_H,    KC_J,    KC_K,    KC_L,    KC_SCLN, KC_QUOT,
+    EXT_PLV, XXXXXXX, XXXXXXX, KC_C,    KC_V,    XXXXXXX, XXXXXXX, KC_N,    KC_M,    XXXXXXX, XXXXXXX, XXXXXXX
+),
+
+/* Adjust (Lower + Raise)
+ * ,-----------------------------------------------------------------------------------.
+ * |      | Reset|      |      |      |      |      |      |      |      |      |  Del |
+ * |------+------+------+------+------+-------------+------+------+------+------+------|
+ * |      |      |      |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak|Plover|      |
+ * |------+------+------+------+------+------|------+------+------+------+------+------|
+ * |      |Voice-|Voice+|Mus on|Musoff|MIDIon|MIDIof|      |      |      |      |      |
+ * |------+------+------+------+------+------+------+------+------+------+------+------|
+ * |      |      |      |      |      |             |      |      |      |      |      |
+ * `-----------------------------------------------------------------------------------'
+ */
+[_ADJUST] = LAYOUT_planck_grid(
+    _______, RESET,   DEBUG,   RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD,  RGB_VAI, RGB_VAD, KC_DEL ,
+    _______, _______, MU_MOD,  AU_ON,   AU_OFF,  AG_NORM, AG_SWAP, QWERTY,  COLEMAK,  DVORAK,  PLOVER,  _______,
+    _______, MUV_DE,  MUV_IN,  MU_ON,   MU_OFF,  MI_ON,   MI_OFF,  TERM_ON, TERM_OFF, _______, _______, _______,
+    _______, _______, _______, _______, _______, _______, _______, _______, _______,  _______, _______, _______
+)
+
+};
+
+#ifdef AUDIO_ENABLE
+  float plover_song[][2]     = SONG(PLOVER_SOUND);
+  float plover_gb_song[][2]  = SONG(PLOVER_GOODBYE_SOUND);
+#endif
+
+uint32_t layer_state_set_user(uint32_t state) {
+  return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
+}
+
+bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+  switch (keycode) {
+    case QWERTY:
+      if (record->event.pressed) {
+        print("mode just switched to qwerty and this is a huge string\n");
+        set_single_persistent_default_layer(_QWERTY);
+      }
+      return false;
+      break;
+    case COLEMAK:
+      if (record->event.pressed) {
+        set_single_persistent_default_layer(_COLEMAK);
+      }
+      return false;
+      break;
+    case DVORAK:
+      if (record->event.pressed) {
+        set_single_persistent_default_layer(_DVORAK);
+      }
+      return false;
+      break;
+    case BACKLIT:
+      if (record->event.pressed) {
+        register_code(KC_RSFT);
+        #ifdef BACKLIGHT_ENABLE
+          backlight_step();
+        #endif
+        #ifdef KEYBOARD_planck_rev5
+          PORTE &= ~(1<<6);
+        #endif
+      } else {
+        unregister_code(KC_RSFT);
+        #ifdef KEYBOARD_planck_rev5
+          PORTE |= (1<<6);
+        #endif
+      }
+      return false;
+      break;
+    case PLOVER:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          stop_all_notes();
+          PLAY_SONG(plover_song);
+        #endif
+        layer_off(_RAISE);
+        layer_off(_LOWER);
+        layer_off(_ADJUST);
+        layer_on(_PLOVER);
+        if (!eeconfig_is_enabled()) {
+            eeconfig_init();
+        }
+        keymap_config.raw = eeconfig_read_keymap();
+        keymap_config.nkro = 1;
+        eeconfig_update_keymap(keymap_config.raw);
+      }
+      return false;
+      break;
+    case EXT_PLV:
+      if (record->event.pressed) {
+        #ifdef AUDIO_ENABLE
+          PLAY_SONG(plover_gb_song);
+        #endif
+        layer_off(_PLOVER);
+      }
+      return false;
+      break;
+  }
+  return true;
+}
+
+void matrix_scan_user(void) {
+
+}
+
+bool music_mask_user(uint16_t keycode) {
+  switch (keycode) {
+    case RAISE:
+    case LOWER:
+      return false;
+    default:
+      return true;
+  }
+}
+
+#include "wavetable.h"
+
+float dac_if[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
+uint8_t dac_morph = 0;
+// uint8_t dac_morph_flipped = 0;
+// uint16_t dac_morph_counter = 0;
+
+void dac_setup_note(void) {
+  dac_if[dac_number_of_voices()] = 0.0f;
+}
+
+uint16_t dac_value_generate(void) {
+  uint16_t value = DAC_OFF_VALUE;
+  uint8_t working_voices = dac_number_of_voices();
+  if (working_voices > DAC_VOICES_MAX)
+    working_voices = DAC_VOICES_MAX;
+
+  if (working_voices > 0) {
+    uint16_t value_avg = 0;
+    for (uint8_t i = 0; i < working_voices; i++) {
+      dac_if[i] = dac_if[i] + ((dac_get_frequency(i) * DAC_BUFFER_SIZE) / DAC_SAMPLE_RATE);
+
+      // Needed because % doesn't work with floats
+      while (dac_if[i] >= (DAC_BUFFER_SIZE))
+        dac_if[i] = dac_if[i] - DAC_BUFFER_SIZE;
+
+      // #define DAC_MORPH_SPEED 372
+      // #define DAC_MORPH_SPEED_COMPUTED (DAC_SAMPLE_RATE / DAC_WAVETABLE_CUSTOM_LENGTH * (1000 / DAC_MORPH_SPEED))
+
+      uint16_t dac_i = (uint16_t)dac_if[i];
+      // value_avg += dac_buffer_custom[dac_morph_flipped][dac_i] / working_voices / 2 * ((dac_morph >= 63) ? 6400 - dac_morph_counter : dac_morph_counter) / 6400;
+      // value_avg += dac_buffer_custom[dac_morph_flipped + 1][dac_i] / working_voices / 2 * ((dac_morph >= 63) ? dac_morph_counter : 6400 - dac_morph_counter) / 6400;
+
+      // value_avg += dac_wavetable_custom[dac_morph][dac_i] / working_voices / 2 * (DAC_MORPH_SPEED_COMPUTED - dac_morph_counter) / DAC_MORPH_SPEED_COMPUTED;
+      // value_avg += dac_wavetable_custom[dac_morph + 1][dac_i] / working_voices / 2 * dac_morph_counter / DAC_MORPH_SPEED_COMPUTED;
+      value_avg += dac_wavetable_custom[dac_morph][dac_i] / working_voices;
+    }
+    value = value_avg;
+
+    // dac_morph_counter++;
+    // if (dac_morph_counter >= DAC_MORPH_SPEED_COMPUTED) {
+      // dac_morph_counter = 0;
+      // dac_morph = (dac_morph + 1) % 125;
+      // dac_morph_flipped = ((dac_morph >= 63) ? (125 - dac_morph) : dac_morph);
+      // dac_morph = (dac_morph + 1) % (DAC_WAVETABLE_CUSTOM_LENGTH - 1);
+    // }
+  }
+  return value;
+}
+
+void encoder_update(bool clockwise) {
+  if (clockwise) {
+    dac_morph = (dac_morph + 1) % DAC_WAVETABLE_CUSTOM_LENGTH;
+  } else {
+    if (dac_morph == 0)
+      dac_morph = (DAC_WAVETABLE_CUSTOM_LENGTH - 1);
+    else
+      dac_morph--;
+  }
+}

+ 0 - 0
keyboards/planck/keymaps/synth_wavetable/rules.mk


File diff suppressed because it is too large
+ 2180 - 0
keyboards/planck/keymaps/synth_wavetable/wavetable.h


+ 6 - 4
quantum/audio/audio.h

@@ -13,8 +13,8 @@
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
-#ifndef AUDIO_H
-#define AUDIO_H
+
+#pragma once
 
 #include <stdint.h>
 #include <stdbool.h>
@@ -27,6 +27,9 @@
 #include "voices.h"
 #include "quantum.h"
 #include <math.h>
+#if defined(PROTOCOL_CHIBIOS)
+  #include "audio_arm.h"
+#endif
 
 // Largely untested PWM audio mode (doesn't sound as good)
 // #define PWM_AUDIO
@@ -107,6 +110,5 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat);
 #define PLAY_SONG(note_array) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), false)
 #define PLAY_LOOP(note_array) play_notes(&note_array, NOTE_ARRAY_SIZE((note_array)), true)
 
+bool is_playing_note(void);
 bool is_playing_notes(void);
-
-#endif

+ 48 - 143
quantum/audio/audio_arm.c

@@ -1,4 +1,4 @@
-/* Copyright 2016 Jack Humbert
+/* Copyright 2016-2019 Jack Humbert
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -26,75 +26,8 @@
 
 // -----------------------------------------------------------------------------
 
-/**
- * Size of the dac_buffer arrays. All must be the same size.
- */
-#define DAC_BUFFER_SIZE 256U
-
-/**
- * Highest value allowed by our 12bit DAC.
- */
-#ifndef DAC_SAMPLE_MAX
-  #define DAC_SAMPLE_MAX  4095U
-#endif
-
-#define DAC_LOW_QUALITY
-
-/**
- * These presets allow you to quickly switch between quality/voice settings for
- * the DAC. The sample rate and number of voices roughly has an inverse
- * relationship - slightly higher sample rates may be possible.
- */
-#ifdef DAC_VERY_LOW_QUALITY
-  #define DAC_SAMPLE_RATE 11025U
-  #define DAC_VOICES_MAX 8
-#endif
-
-#ifdef DAC_LOW_QUALITY
-  #define DAC_SAMPLE_RATE 22050U
-  #define DAC_VOICES_MAX 4
-#endif
-
-#ifdef DAC_HIGH_QUALITY
-  #define DAC_SAMPLE_RATE 44100U
-  #define DAC_VOICES_MAX 2
-#endif
-
-#ifdef DAC_VERY_HIGH_QUALITY
-  #define DAC_SAMPLE_RATE 88200U
-  #define DAC_VOICES_MAX 1
-#endif
-
-/**
- * Effective bitrate of the DAC. 44.1khz is the standard for most audio - any
- * lower will sacrifice perceptible audio quality. Any higher will limit the
- * number of simultaneous voices. In most situations, a tenth (1/10) of the
- * sample rate is where notes become unbearable.
- */
-#ifndef DAC_SAMPLE_RATE
-  #define DAC_SAMPLE_RATE 44100U
-#endif
-
-/**
- * The number of voices (in polyphony) that are supported. If too high a value
- * is used here, the keyboard will freeze and glitch-out when that many voices
- * are being played.
- */
-#ifndef DAC_VOICES_MAX
-  #define DAC_VOICES_MAX 2
-#endif
-
-/**
- * The default value of the DAC when not playing anything. Certain hardware
- * setups may require a high (DAC_SAMPLE_MAX) or low (0) value here.
- */
-#ifndef DAC_OFF_VALUE
-  #define DAC_OFF_VALUE DAC_SAMPLE_MAX / 2
-#endif
-
-int voices = 0;
-float frequencies[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-int volumes[8] = {0, 0, 0, 0, 0, 0, 0, 0};
+uint8_t dac_voices = 0;
+float dac_frequencies[8] = { 0.0 };
 
 bool     playing_notes = false;
 bool     playing_note = false;
@@ -129,7 +62,7 @@ bool glissando = true;
 #endif
 float startup_song[][2] = STARTUP_SONG;
 
-static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = {
+static const dacsample_t dac_buffer_sine[DAC_BUFFER_SIZE] = {
   // 256 values, max 4095
   0x800,0x832,0x864,0x896,0x8c8,0x8fa,0x92c,0x95e,
   0x98f,0x9c0,0x9f1,0xa22,0xa52,0xa82,0xab1,0xae0,
@@ -209,69 +142,40 @@ static const dacsample_t dac_buffer_square[DAC_BUFFER_SIZE] = {
 
 static dacsample_t dac_buffer_empty[DAC_BUFFER_SIZE] = { DAC_OFF_VALUE };
 
-#include "wavetable.h"
-
-float dac_if[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
-uint8_t dac_voice = 0;
-uint8_t dac_voice_flipped = 0;
-uint16_t dac_voice_counter = 0;
-float dac_voice_count_flipped = 0;
+static float dac_if[8] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
 
 /**
- * Generation of the sample being passed to the callback. Declared weak so users
+ * Generation of the waveform being passed to the callback. Declared weak so users
  * can override it with their own waveforms/noises.
  */
 __attribute__ ((weak))
-uint16_t generate_sample(void) {
-  uint16_t sample = DAC_OFF_VALUE;
-  uint8_t working_voices = voices;
+uint16_t dac_value_generate(void) {
+  uint16_t value = DAC_OFF_VALUE;
+  uint8_t working_voices = dac_voices;
   if (working_voices > DAC_VOICES_MAX)
     working_voices = DAC_VOICES_MAX;
 
   if (working_voices > 0) {
-    uint16_t sample_sum = 0;
+    uint16_t value_avg = 0;
     for (uint8_t i = 0; i < working_voices; i++) {
-      dac_if[i] = dac_if[i] + ((frequencies[i]*DAC_BUFFER_SIZE)/DAC_SAMPLE_RATE);
+      dac_if[i] = dac_if[i] + ((dac_frequencies[i] * DAC_BUFFER_SIZE) / DAC_SAMPLE_RATE);
 
       // Needed because % doesn't work with floats
-      // 0.5 less than the size because we use round() later
       while (dac_if[i] >= (DAC_BUFFER_SIZE))
         dac_if[i] = dac_if[i] - DAC_BUFFER_SIZE;
 
-      (void)dac_buffer;
-      (void)dac_buffer_square;
-      (void)dac_buffer_triangle;
-
-      #define DAC_MORPH_SPEED 3000
-      #define DAC_SAMPLE_CUSTOM_LENGTH 64
-      #define DAC_MORPH_SPEED_COMPUTED (DAC_SAMPLE_RATE / DAC_SAMPLE_CUSTOM_LENGTH * DAC_MORPH_SPEED / 1000)
-
-      uint16_t dac_i = (uint16_t)dac_if[i];
       // Wavetable generation/lookup
+      uint16_t dac_i = (uint16_t)dac_if[i];
       // SINE
-      // sample_sum += dac_buffer[dac_i] / working_voices / 3;
+      value_avg += dac_buffer_sine[dac_i] / working_voices / 3;
       // TRIANGLE
-      // sample_sum += dac_buffer_triangle[dac_i] / working_voices / 3;
-      // RISING TRIANGLE
-      // sample_sum += (uint16_t)round((dac_if[i] * DAC_SAMPLE_MAX) / DAC_BUFFER_SIZE / working_voices );
+      value_avg += dac_buffer_triangle[dac_i] / working_voices / 3;
       // SQUARE
-      // sample_sum += ((dac_if[i] > (DAC_BUFFER_SIZE / 2)) ? DAC_SAMPLE_MAX / working_voices: 0);
-      // sample_sum += dac_buffer_square[dac_i] / working_voices / 3;
-      // sample_sum += dac_buffer_custom[dac_voice_flipped][dac_i] / working_voices / 2 * ((dac_voice >= 63) ? 6400 - dac_voice_counter : dac_voice_counter) / 6400;
-      // sample_sum += dac_buffer_custom[dac_voice_flipped + 1][dac_i] / working_voices / 2 * ((dac_voice >= 63) ? dac_voice_counter : 6400 - dac_voice_counter) / 6400;
-      sample_sum += dac_buffer_custom[dac_voice][dac_i] / working_voices / 2 * (DAC_MORPH_SPEED_COMPUTED - dac_voice_counter) / DAC_MORPH_SPEED_COMPUTED;
-      sample_sum += dac_buffer_custom[dac_voice + 1][dac_i] / working_voices / 2 * dac_voice_counter / DAC_MORPH_SPEED_COMPUTED;
-    }
-    sample = sample_sum;
-    dac_voice_counter++;
-    if (dac_voice_counter >= DAC_MORPH_SPEED_COMPUTED) {
-      dac_voice_counter = 0;
-      // dac_voice = (dac_voice + 1) % 125;
-      // dac_voice_flipped = ((dac_voice >= 63) ? (125 - dac_voice) : dac_voice);
-      dac_voice = (dac_voice + 1) % (DAC_SAMPLE_CUSTOM_LENGTH - 1);
+      value_avg += dac_buffer_square[dac_i] / working_voices / 3;
     }
+    value = value_avg;
   }
-  return sample;
+  return value;
 }
 
 /**
@@ -282,7 +186,7 @@ static void dac_end(DACDriver * dacp, dacsample_t * sample_p, size_t sample_coun
   (void)dacp;
 
   for (uint8_t s = 0; s < sample_count; s++) {
-    sample_p[s] = generate_sample();
+    sample_p[s] = dac_value_generate();
   }
 
   if (playing_notes) {
@@ -402,15 +306,13 @@ void stop_all_notes() {
     if (!audio_initialized) {
         audio_init();
     }
-    voices = 0;
+    dac_voices = 0;
 
     playing_notes = false;
     playing_note = false;
 
-    for (uint8_t i = 0; i < 8; i++)
-    {
-        frequencies[i] = 0;
-        volumes[i] = 0;
+    for (uint8_t i = 0; i < 8; i++) {
+        dac_frequencies[i] = 0;
     }
 }
 
@@ -422,23 +324,20 @@ void stop_note(float freq) {
       audio_init();
     }
     for (int i = 7; i >= 0; i--) {
-      if (frequencies[i] == freq) {
-        frequencies[i] = 0;
-        volumes[i] = 0;
+      if (dac_frequencies[i] == freq) {
+        dac_frequencies[i] = 0;
         for (int j = i; (j < 7); j++) {
-          frequencies[j] = frequencies[j+1];
-          frequencies[j+1] = 0;
-          volumes[j] = volumes[j+1];
-          volumes[j+1] = 0;
+          dac_frequencies[j] = dac_frequencies[j+1];
+          dac_frequencies[j+1] = 0;
         }
         break;
       }
     }
-    voices--;
-    if (voices < 0) {
-      voices = 0;
+    dac_voices--;
+    if (dac_voices < 0) {
+      dac_voices = 0;
     }
-    if (voices == 0) {
+    if (dac_voices == 0) {
       playing_note = false;
     }
   }
@@ -472,25 +371,19 @@ void play_note(float freq, int vol) {
       audio_init();
   }
 
-  if (audio_config.enable && voices < 8) {
-
-     // Cancel notes if notes are playing
-    // if (playing_notes) {
-    //   stop_all_notes();
-    // }
-
+  if (audio_config.enable && dac_voices < 8) {
     playing_note = true;
-
     if (freq > 0) {
       envelope_index = 0;
-      frequencies[voices] = freq;
-      dac_if[voices] = 0.0f;
-      volumes[voices] = vol;
-      voices++;
+      dac_frequencies[dac_voices] = freq;
+      dac_voices++;
     }
-
   }
+}
 
+__attribute__ ((weak))
+void dac_setup_note(void) {
+  dac_if[dac_voices] = 0.0f;
 }
 
 void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) {
@@ -517,6 +410,10 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) {
   }
 }
 
+bool is_playing_note(void) {
+  return playing_note;
+}
+
 bool is_playing_notes(void) {
   return playing_notes;
 }
@@ -624,3 +521,11 @@ void increase_tempo(uint8_t tempo_change) {
     note_tempo -= tempo_change;
   }
 }
+
+uint8_t dac_number_of_voices(void) {
+  return dac_voices;
+}
+
+float dac_get_frequency(uint8_t index) {
+  return dac_frequencies[index];
+}

+ 89 - 0
quantum/audio/audio_arm.h

@@ -0,0 +1,89 @@
+/* Copyright 2019 Jack Humbert
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include "ch.h"
+
+/**
+ * Size of the dac_buffer arrays. All must be the same size.
+ */
+#define DAC_BUFFER_SIZE 256U
+
+/**
+ * Highest value allowed by our 12bit DAC.
+ */
+#ifndef DAC_SAMPLE_MAX
+  #define DAC_SAMPLE_MAX  4095U
+#endif
+
+// #define DAC_LOW_QUALITY
+
+/**
+ * These presets allow you to quickly switch between quality/voice settings for
+ * the DAC. The sample rate and number of voices roughly has an inverse
+ * relationship - slightly higher sample rates may be possible.
+ */
+#ifdef DAC_VERY_LOW_QUALITY
+  #define DAC_SAMPLE_RATE 11025U
+  #define DAC_VOICES_MAX 8
+#endif
+
+#ifdef DAC_LOW_QUALITY
+  #define DAC_SAMPLE_RATE 22050U
+  #define DAC_VOICES_MAX 4
+#endif
+
+#ifdef DAC_HIGH_QUALITY
+  #define DAC_SAMPLE_RATE 44100U
+  #define DAC_VOICES_MAX 2
+#endif
+
+#ifdef DAC_VERY_HIGH_QUALITY
+  #define DAC_SAMPLE_RATE 88200U
+  #define DAC_VOICES_MAX 1
+#endif
+
+/**
+ * Effective bitrate of the DAC. 44.1khz is the standard for most audio - any
+ * lower will sacrifice perceptible audio quality. Any higher will limit the
+ * number of simultaneous voices. In most situations, a tenth (1/10) of the
+ * sample rate is where notes become unbearable.
+ */
+#ifndef DAC_SAMPLE_RATE
+  #define DAC_SAMPLE_RATE 44100U
+#endif
+
+/**
+ * The number of voices (in polyphony) that are supported. If too high a value
+ * is used here, the keyboard will freeze and glitch-out when that many voices
+ * are being played.
+ */
+#ifndef DAC_VOICES_MAX
+  #define DAC_VOICES_MAX 2
+#endif
+
+/**
+ * The default value of the DAC when not playing anything. Certain hardware
+ * setups may require a high (DAC_SAMPLE_MAX) or low (0) value here.
+ */
+#ifndef DAC_OFF_VALUE
+  #define DAC_OFF_VALUE DAC_SAMPLE_MAX / 2
+#endif
+
+uint8_t dac_number_of_voices(void);
+float dac_get_frequency(uint8_t index);
+uint16_t dac_value_generate(void);
+void dac_setup_note(void);

File diff suppressed because it is too large
+ 0 - 2178
quantum/audio/wavetable.h


+ 39 - 0
util/sample_parser.py

@@ -0,0 +1,39 @@
+#! /bin/python
+#
+# Copyright 2019 Jack Humbert
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import wave, struct, sys
+
+waveFile = wave.open(sys.argv[1], 'r')
+# print(str(waveFile.getparams()))
+# sys.exit()
+
+if (waveFile.getsampwidth() != 2):
+    raise(Exception("This script currently only works with 16bit audio files"))
+
+length = waveFile.getnframes()
+out = "#define DAC_SAMPLE_CUSTOM_LENGTH " + str(length) + "\n\n"
+out += "static const dacsample_t dac_sample_custom[" + str(length) + "] = {"
+for i in range(0,length):
+    if (i % 8 == 0):
+        out += "\n    "
+    waveData = waveFile.readframes(1)
+    data = struct.unpack("<h", waveData)
+    out += str(int((int(data[0]) + 0x8000) / 16)) + ", "
+out = out[:-2]
+out += "\n};"
+print(out)

+ 0 - 23
util/wav_parser.py

@@ -1,23 +0,0 @@
-#! /bin/python
-
-import wave, struct, sys
-
-waveFile = wave.open(sys.argv[1], 'r')
-
-length = waveFile.getnframes()
-out = "static const dacsample_t dac_buffer_custom[" + str(int(length / 256)) + "][256] = {"
-for i in range(0,length):
-    if (i % 8 == 0):
-        out += "\n    "
-    if (i % 256 == 0):
-        out = out[:-2]
-        out += "{\n    "
-    waveData = waveFile.readframes(1)
-    data = struct.unpack("<h", waveData)
-    out += str(int((int(data[0]) + 0x8000) / 16)) + ", "
-    if (i % 256 == 255):
-        out = out[:-2]
-        out += "\n  },"
-out = out[:-1]
-out += "\n};"
-print(out)

+ 40 - 0
util/wavetable_parser.py

@@ -0,0 +1,40 @@
+#! /bin/python
+#
+# Copyright 2019 Jack Humbert
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import wave, struct, sys
+
+waveFile = wave.open(sys.argv[1], 'r')
+
+length = waveFile.getnframes()
+out = "#define DAC_WAVETABLE_CUSTOM_LENGTH " + str(int(length / 256)) + "\n\n"
+out += "static const dacsample_t dac_wavetable_custom[" + str(int(length / 256)) + "][256] = {"
+for i in range(0,length):
+    if (i % 8 == 0):
+        out += "\n    "
+    if (i % 256 == 0):
+        out = out[:-2]
+        out += "{\n    "
+    waveData = waveFile.readframes(1)
+    data = struct.unpack("<h", waveData)
+    out += str(int((int(data[0]) + 0x8000) / 16)) + ", "
+    if (i % 256 == 255):
+        out = out[:-2]
+        out += "\n  },"
+out = out[:-1]
+out += "\n};"
+print(out)