#!/usr/bin/env python3
def write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits):
ada_conn = [".ADA%d(%s)" % (i, ada_bits[i]) for i in range(len(ada_bits))]
adb_conn = [".ADB%d(%s)" % (i, adb_bits[i]) for i in range(len(adb_bits))]
dia_conn = [".DIA%d(%s)" % (i, dia_bits[i])pre { line-height: 125%; margin: 0; }
td.linenos pre { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
span.linenos { color: #000000; background-color: #f0f0f0; padding: 0 5px 0 5px; }
td.linenos pre.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding: 0 5px 0 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long *//* Copyright 2016 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 "process_midi.h"
#ifdef MIDI_ENABLE
#include <LUFA/Drivers/USB/USB.h>
#include "midi.h"
#include "qmk_midi.h"
#ifdef MIDI_BASIC
void process_midi_basic_noteon(uint8_t note)
{
midi_send_noteon(&midi_device, 0, note, 128);
}
void process_midi_basic_noteoff(uint8_t note)
{
midi_send_noteoff(&midi_device, 0, note, 0);
}
void process_midi_all_notes_off(void)
{
midi_send_cc(&midi_device, 0, 0x7B, 0);
}
#endif // MIDI_BASIC
#ifdef MIDI_ADVANCED
#include "timer.h"
static uint8_t tone_status[MIDI_TONE_COUNT];
static uint8_t midi_modulation;
static int8_t midi_modulation_step;
static uint16_t midi_modulation_timer;
midi_config_t midi_config;
inline uint8_t compute_velocity(uint8_t setting)
{
return (setting + 1) * (128 / (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN + 1));
}
void midi_init(void)
{
midi_config.octave = MI_OCT_2 - MIDI_OCTAVE_MIN;
midi_config.transpose = 0;
midi_config.velocity = (MIDI_VELOCITY_MAX - MIDI_VELOCITY_MIN);
midi_config.channel = 0;
midi_config.modulation_interval = 8;
for (uint8_t i = 0; i < MIDI_TONE_COUNT; i++)
{
tone_status[i] = MIDI_INVALID_NOTE;
}
midi_modulation = 0;
midi_modulation_step = 0;
midi_modulation_timer = 0;
}
uint8_t midi_compute_note(uint16_t keycode)
{
return 12 * midi_config.octave + (keycode - MIDI_TONE_MIN) + midi_config.transpose;
}
bool process_midi(uint16_t keycode, keyrecord_t *record)
{
switch (keycode) {
case MIDI_TONE_MIN ... MIDI_TONE_MAX:
{
uint8_t channel = midi_config.channel;
uint8_t tone = keycode - MIDI_TONE_MIN;
uint8_t velocity = compute_velocity(midi_config.velocity);
if (record->event.pressed) {
uint8_t note = midi_compute_note(keycode);
midi_send_noteon(&midi_device, channel, note, velocity);
dprintf("midi noteon channel:%d note:%d velocity:%d\n", channel, note, velocity);
tone_status[tone] = note;
}
else {
uint8_t note = tone_status[tone];
if (note != MIDI_INVALID_NOTE)
{
midi_send_noteoff(&midi_device, channel, note, velocity);
dprintf("midi noteoff channel:%d note:%d velocity:%d\n", channel, note, velocity);
}
tone_status[tone] = MIDI_INVALID_NOTE;
}
return false;
}
case MIDI_OCTAVE_MIN ... MIDI_OCTAVE_MAX:
if (record->event.pressed) {
midi_config.octave = keycode - MIDI_OCTAVE_MIN;
dprintf("midi octave %d\n", midi_config.octave);
}
return false;
case MI_OCTD:
if (record->event.pressed && midi_config.octave > 0) {
midi_config.octave--;
dprintf("midi octave %d\n", midi_config.octave);
}
return false;
case MI_OCTU:
if (record->event.pressed && midi_config.octave < (MIDI_OCTAVE_MAX - MIDI_OCTAVE_MIN)) {
midi_config.octave++;
dprintf("midi octave %d\n", midi_config.octave);
}
return false;
case MIDI_TRANSPOSE_MIN ... MIDI_TRANSPOSE_MAX:
if (record->event.pressed) {
midi_config.transpose = keycode - MI_TRNS_0;
dprintf("midi transpose %d\n", midi_config.transpose);
}
return false;
case MI_TRNSD:
if (record->event.pressed && midi_config.transpose > (MIDI_TRANSPOSE_MIN - MI_TRNS_0)) {
midi_config.transpose--;
dprintf("midi transpose %d\n", midi_config.transpose);
}
return false;
case MI_TRNSU:
if (record->event.pressed && midi_config.transpose < (MIDI_TRANSPOSE_MAX - MI_TRNS_0)) {
const bool positive = midi_config.transpose > 0;
midi_config.transpose++;
if (positive && midi_config.transpose < 0)
midi_config.transpose--;
dprintf("midi transpose %d\n", midi_config.transpose);
}
return false;
case MIDI_VELOCITY_MIN ... MIDI_VELOCITY_MAX:
if (record->event.pressed) {
midi_config.velocity = keycode - MIDI_VELOCITY_MIN;
dprintf("midi velocity %d\n", midi_config.velocity);
}
return false;
case MI_VELD:
if (record->event.pressed && midi_config.velocity > 0) {
midi_config.velocity--;
dprintf("midi velocity %d\n", midi_config.velocity);
}
return false;
case MI_VELU:
if (record->event.pressed) {
midi_config.velocity++;
dprintf("midi velocity %d\n", midi_config.velocity);
}
return false;
case MIDI_CHANNEL_MIN ... MIDI_CHANNEL_MAX:
if (record->event.pressed) {
midi_config.channel = keycode - MIDI_CHANNEL_MIN;
dprintf("midi channel %d\n", midi_config.channel);
}
return false;
case MI_CHD:
if (record->event.pressed) {
midi_config.channel--;
dprintf("midi channel %d\n", midi_config.channel);
}
return false;
case MI_CHU:
if (record->event.pressed) {
midi_config.channel++;
dprintf("midi channel %d\n", midi_config.channel);
}
return false;
case MI_ALLOFF:
if (record->event.pressed) {
midi_send_cc(&midi_device, midi_config.channel, 0x7B, 0);
dprintf("midi all notes off\n");
}
return false;
case MI_SUS:
midi_send_cc(&midi_device, midi_config.channel, 0x40, record->event.pressed ? 127 : 0);
dprintf("midi sustain %d\n", record->event.pressed);
return false;
case MI_PORT:
midi_send_cc(&midi_device, midi_config.channel, 0x41, record->event.pressed ? 127 : 0);
dprintf("midi portamento %d\n", record->event.pressed);
return false;
case MI_SOST:
midi_send_cc(&midi_device, midi_config.channel, 0x42, record->event.pressed ? 127 : 0);
dprintf("midi sostenuto %d\n", record->event.pressed);
return false;
case MI_SOFT:
midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
dprintf("midi soft %d\n", record->event.pressed);
return false;
case MI_LEG:
midi_send_cc(&midi_device, midi_config.channel, 0x43, record->event.pressed ? 127 : 0);
dprintf("midi legato %d\n", record->event.pressed);
return false;
case MI_MOD:
midi_modulation_step = record->event.pressed ? 1 : -1;
return false;
case MI_MODSD:
if (record->event.pressed) {
midi_config.modulation_interval++;
// prevent overflow
if (midi_config.modulation_interval == 0)
midi_config.modulation_interval--;
dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
}
return false;
case MI_MODSU:
if (record->event.pressed && midi_config.modulation_interval > 0) {
midi_config.modulation_interval--;
dprintf("midi modulation interval %d\n", midi_config.modulation_interval);
}
return false;
case MI_BENDD:
if (record->event.pressed) {
midi_send_pitchbend(&midi_device, midi_config.channel, -0x2000);
dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, -0x2000);
}
else {
midi_send_pitchbend(&midi_device, midi_config.channel, 0);
dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0);
}
return false;
case MI_BENDU:
if (record->event.pressed) {
midi_send_pitchbend(&midi_device, midi_config.channel, 0x1fff);
dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0x1fff);
}
else {
midi_send_pitchbend(&midi_device, midi_config.channel, 0);
dprintf("midi pitchbend channel:%d amount:%d\n", midi_config.channel, 0);
}
return false;
};
return true;
}
#endif // MIDI_ADVANCED
void midi_task(void)
{
midi_device_process(&midi_device);
#ifdef MIDI_ADVANCED
if (timer_elapsed(midi_modulation_timer) < midi_config.modulation_interval)
return;
midi_modulation_timer = timer_read();
if (midi_modulation_step != 0)
{
dprintf("midi modulation %d\n", midi_modulation);
midi_send_cc(&midi_device, midi_config.channel, 0x1, midi_modulation);
if (midi_modulation_step < 0 && midi_modulation < -midi_modulation_step) {
midi_modulation = 0;
midi_modulation_step = 0;
return;
}
midi_modulation += midi_modulation_step;
if (midi_modulation > 127)
midi_modulation = 127;
}
#endif
}
#endif // MIDI_ENABLE