frac32.positive LED brightness
bool32.rising calibrate
frac32.positive press
frac32.positive F1
frac32.positive F2
frac32.positive F3
frac32.positive F4
frac32.positive F5
frac32.u.map L0
frac32.u.map L1
frac32.u.map LNoteOn
uint8array128.vbar vf
frac32.vbar tempco
bool calibrate = false;
uint32_t vol = 80;
uint32_t vol_cpt = 0;
// tempco
int32_t tempco = 0;
int32_t scan = -12; // first cycle
uint8_t adcNotes[12] = {12, 11, 10, 9, 8, 7, 6, 4, 3, 2, 1, 0};
int32_t v[6 * 12];
int32_t cal[6 * 12];
int32_t vrs[6 * 12];
int32_t gate[6 * 12];
int32_t press[6 * 12];
const int32_t COEF_INC = 0x10000000; // slow
const int32_t COEF_DEC = 0x70000000; // fast
float _L0_L1;
uint8_t oct = 3;
uint8_t an[5 * 12]; // assignated note
uint32_t timeCnt = 0;
uint8_t KBmode = 0;
uint8_t LEDmode = 0;
uint16_t modeCntDown = 0; // modes back to 0 when 0
bool octM = false;
bool octP = false;
int32_t bend = 8192, abend = 8192;
// -----\
// \
// \____
// 0 L1 L0
int32_t revScale(int32_t x, int32_t L0, int32_t L1) {
if (x < L1)
return (1 << 27) - 1;
else if (x > L0)
return 0;
else
// return 1-(x-L1)/(L0-L1); //
return (1 << 27) - (int32_t)((x - L1) * _L0_L1);
}
void LED(int32_t pwm) {
pwmEnableChannel(&PWMD8, 0, (pwmcnt_t)(pwm >= 0 ? pwm >> (27 - 12) : 0));
}
void LEDOn(void) { pwmEnableChannel(&PWMD8, 0, (pwmcnt_t)(1 << 11)); }
void LEDBright(void) { pwmEnableChannel(&PWMD8, 0, (pwmcnt_t)(1 << 12)); }
void LEDOff(void) { pwmEnableChannel(&PWMD8, 0, (pwmcnt_t)(0)); }
static const PWMConfig pwmcfg = {400000, /* 400kHz PWM clock frequency. */
4096, /* PWM period is 128 cycles. */
NULL,
{{PWM_OUTPUT_ACTIVE_HIGH, NULL},
{PWM_OUTPUT_ACTIVE_HIGH, NULL},
{PWM_OUTPUT_ACTIVE_HIGH, NULL},
{PWM_OUTPUT_ACTIVE_HIGH, NULL}},
/* HW dependent part.*/
0};
pwmStart(&PWMD8, &pwmcfg);
palSetPadMode(GPIOA, 5, PAL_MODE_ALTERNATE(3));
PWMD8.tim->CCER |= STM32_TIM_CCER_CC1NE | STM32_TIM_CCER_CC1NP;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
palSetPadMode(GPIOC, 4, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOC, 5, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOB, 6, PAL_MODE_OUTPUT_PUSHPULL); // low row
palSetPadMode(GPIOB, 7, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL);
palSetPadMode(GPIOB, 9, PAL_MODE_OUTPUT_PUSHPULL);
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
for (int k = 0; k < 5 * 12; k++) {
an[k] = -1;
}
for (int i = 0; i < 6 * 12; i++) {
v[i] = 1 << 27; // assym lp filtered
cal[i] = 0;
vrs[i] = -10; // reverse scaled
gate[i] = 0;
press[i] = 0;
}
disp_tempco = tempco =
___SMMLA(0x01000000, (adcvalues[13] << 15) - tempco, tempco);
// _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
if (scan >= 0) {
// LPF input
int32_t *v12 = v + scan * 12;
for (int i = 0; i < 12; i++) { // PA0..PA7
int32_t in = (adcvalues[adcNotes[i]] << 15) - tempco;
v12[i] = __SMMLA(in > v12[i] ? COEF_INC : COEF_DEC, in - v12[i], v12[i]);
}
// reverse and scale
_L0_L1 = ((float)(1 << 27)) / (float)(param_L0 - param_L1);
for (int i = scan * 12; i < 12 + scan * 12; i++) {
vrs[i] = revScale(v12[i - scan * 12] + cal[i], param_L0, param_L1);
// Threshold and Basic internal MIDI
}
//______________________________________________________________________
// lateral inhib
{
int32_t sub[12];
int32_t *vrs12 = vrs + scan * 12;
for (int k = 1; k < 11; k++) {
sub[k] = (vrs12[k - 1] + vrs12[k + 1]) >> 3;
}
sub[0] = vrs12[1] >> 3;
sub[11] = vrs12[10] >> 3;
for (int k = 0; k < 12; k++) {
vrs12[k] -= sub[k];
if (vrs12[k] < 0)
vrs12[k] = 0;
}
}
for (int i = scan * 12; i < 12 + scan * 12; i++) {
if (gate[i] == 0) {
if (vrs[i] > param_LNoteOn) {
if (scan <= 4 && KBmode == 0) {
an[i] = i + 12 * oct;
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_NOTE_ON, an[i], 100);
}
gate[i] = 1;
}
} else {
if (vrs[i] <= 0) {
if (scan <= 4 && KBmode == 0) {
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_NOTE_OFF, an[i], 0);
an[i] = -1;
}
if (scan <= 4 && KBmode == 1) {
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_PROGRAM_CHANGE, i,
0);
// MidiSend2((midi_device_t) attr_device , MIDI_PROGRAM_CHANGE +
// (attr_channel-1),inlet_pgm&0x7F);
KBmode = 0;
LEDmode = 0;
}
gate[i] = 0;
}
}
int32_t newPress = __USAT(vrs[i] >> 20, 7);
if (abs(press[i] - newPress) >= 1) {
press[i] = newPress;
if (scan <= 4 && KBmode == 0)
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_POLY_PRESSURE, an[i],
newPress);
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/* if(KBmode == 1 && scan <= 4) { //pc
for(int k = 0; k < 60; k++){
if(vrs[k] > (60 << 20)){
// PC k
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_PROGRAM_CHANGE, k,0);
//MidiSend2((midi_device_t) attr_device , MIDI_PROGRAM_CHANGE +
(attr_channel-1),inlet_pgm&0x7F);
KBmode = 0;
LEDmode = 0;
break;
}
}
}*/
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// control keys
if (scan == 5) {
bool vol_minus = vrs[69] > (32 << 21);
bool vol_plus = vrs[70] > (32 << 21);
if (!vol_plus && !vol_minus) {
vol_cpt == 0;
} else {
if ((vol_cpt % 128) == 0) {
if (vol_plus && vol < 127)
vol++;
if (vol_minus && vol > 0)
vol--;
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_CONTROL_CHANGE, 7,
vol); // <-------------vol CC
LEDmode = 10;
modeCntDown = 3 * 3000;
}
vol_cpt++;
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
if (vrs[71] > (60 << 20) && KBmode == 0) {
// all notes off
for (int k = 0; k < 60; k++) {
if (an[k] >= 0) {
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_NOTE_OFF, an[k],
0);
an[k] = -1;
gate[k] = 0;
}
}
KBmode = 1;
LEDmode = 1;
modeCntDown = 10 * 3000; // 10s
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
if (vrs[67] == 0)
octM = false;
if (vrs[67] > (60 << 20) && octM == false) {
octM = true;
if (oct > 1)
oct--;
LEDmode = oct + 1;
modeCntDown = 3 * 3000;
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
if (vrs[68] == 0)
octP = false;
if (vrs[68] > (60 << 20) && octP == false) {
octP = true;
if (oct < 5)
oct++;
LEDmode = 1 + oct;
modeCntDown = 3 * 3000;
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// bend
if (vrs[61] > 0 || vrs[60] > 0) {
bend = ((vrs[61] - vrs[60]) >> (27 - 14)) + 8192;
if (bend >= (1 << 14))
bend = (1 << 14) - 1;
if (bend < 0)
bend = 0;
if (abs(bend - abend) > 5) {
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_PITCH_BEND,
bend & 0x7F, bend >> 7);
LEDmode = 11;
modeCntDown = 30000;
}
} else if (bend != 8192) {
bend = 8192;
PatchMidiInHandler(MIDI_DEVICE_INTERNAL, 0, MIDI_PITCH_BEND,
bend & 0x7F, bend >> 7);
LEDmode = 0;
modeCntDown = 0;
}
abend = bend;
}
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
// max press output (reinject in LED input if needed)
if (KBmode == 0) {
int32_t maxVrs = 0;
for (int k = 0; k < 60; k++) {
if (vrs[k] > maxVrs)
maxVrs = vrs[k];
}
outlet_press = maxVrs;
} else {
outlet_press = 0;
}
for (int i = 0; i < 72; i++) {
// disp_vf[i] = (uint8_t)(v[i]>>20);
disp_vf[i] = (uint8_t)(vrs[i] >> 20);
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
switch (LEDmode) {
case 0:
LED(inlet_LED);
break;
case 1: {
int t = timeCnt % 3000;
if (t < 750)
LEDOff();
else if (t < 1500)
LEDOn();
else if (t < 1750)
LEDOff();
else if (t < 2000)
LEDBright();
else if (t < 2500)
LEDOff();
else if (t < 2750)
LEDBright();
else
LEDOff();
} break;
case 2:
if ((timeCnt % 325) < 200)
LEDOff();
else
LEDOn();
break;
case 3:
if ((timeCnt % 750) < 500)
LEDOff();
else
LEDOn();
break;
case 4:
LEDOn();
break;
case 5:
if ((timeCnt % 750) < 500)
LEDOff();
else
LEDOn();
break;
case 6:
if ((timeCnt % 325) < 200)
LEDOff();
else
LEDOn();
break;
case 10:
LED(vol << 18);
break;
case 11:
if ((timeCnt % 325) < 100)
LEDOff();
else
LED(abs(bend - 8192) << 13);
break;
default:
LED(inlet_LED);
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
timeCnt++;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
if (modeCntDown > 0)
modeCntDown--;
else {
LEDmode = 0;
KBmode = 0;
}
outlet_F1 = vrs[62];
outlet_F2 = vrs[63];
outlet_F3 = vrs[64];
outlet_F4 = vrs[65];
outlet_F5 = vrs[66];
}
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
if (inlet_calibrate && !calibrate) {
int32_t m = v[0];
for (int k = 1; k < 60; k++) {
if (v[k] < m)
m = v[k];
}
for (int k = 0; k < 60; k++) {
cal[k] = m - v[k];
}
}
calibrate = inlet_calibrate;
//_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
scan++;
if (scan >= 6)
scan = 0;
palWritePad(GPIOC, 4, (scan == 0)); // PC4 low
palWritePad(GPIOC, 5, (scan == 1)); // PC5
palWritePad(GPIOB, 6, (scan == 2)); // PB6
palWritePad(GPIOB, 7, (scan == 3)); // PB7
palWritePad(GPIOB, 8, (scan == 4)); // PB8
palWritePad(GPIOB, 9, (scan == 5)); // PB9
pwmStop(&PWMD8);