-
Notifications
You must be signed in to change notification settings - Fork 82
/
ls_faders.ino
138 lines (121 loc) · 5.09 KB
/
ls_faders.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/******************************* ls_faders: LinnStrument CC Faders ********************************
Copyright 2023 Roger Linn Design (https://www.rogerlinndesign.com)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
***************************************************************************************************
These functions handle the CC faders for each split
**************************************************************************************************/
#define CC_FADER_NUMBER_OFFSET 1
void handleFaderTouch(boolean newVelocity) {
if (sensorCell->velocity) {
byte faderLeft, faderLength;
determineFaderBoundaries(sensorSplit, faderLeft, faderLength);
handleFaderTouch(newVelocity, faderLeft, faderLength);
}
}
void handleFaderTouch(boolean newVelocity, byte faderLeft, byte faderLength) {
if (sensorCell->velocity) {
unsigned short ccForFader = Split[sensorSplit].ccForFader[sensorRow];
if (ccForFader > 128) return;
// only proceed when this is the touch on the highest row in the same split when the CC numbers
// are the same, only one fader with the same cc number can be used at a time
for (byte r = 7; r > sensorRow; --r) {
if (Split[sensorSplit].ccForFader[r] == ccForFader && hasTouchInSplitOnRow(sensorSplit, r)) {
return;
}
}
short value = -1;
// when the fader only spans one cell, it acts as a toggle
if (faderLength == 0) {
if (newVelocity) {
if (ccFaderValues[sensorSplit][ccForFader] > 0) {
value = 0;
}
else {
value = 127;
}
}
}
// otherwise it's a real fader and we calculate the value based on its position
else {
// if a new touch happens on the same row that is further down the row, make it
// take over the touch
if (newVelocity) {
for (byte col = faderLength + faderLeft; col >= faderLeft; --col) {
if (col != sensorCol && cell(col, sensorRow).velocity) {
transferFromSameRowCell(col);
return;
}
}
}
// initialize the initial fader touch
value = calculateFaderValue(sensorCell->calibratedX(), faderLeft, faderLength);
}
if (value >= 0) {
ccFaderValues[sensorSplit][ccForFader] = value;
preSendControlChange(sensorSplit, ccForFader, value, false);
paintCCFaderDisplayRow(sensorSplit, sensorRow, faderLeft, faderLength);
// update other faders with the same CC number
for (byte f = 0; f < 8; ++f) {
if (f != sensorRow && Split[sensorSplit].ccForFader[f] == ccForFader) {
performContinuousTasks();
paintCCFaderDisplayRow(sensorSplit, f, faderLeft, faderLength);
}
}
}
}
}
void handleFaderRelease() {
byte faderLeft, faderLength;
determineFaderBoundaries(sensorSplit, faderLeft, faderLength);
handleFaderRelease(faderLeft, faderLength);
}
void handleFaderRelease(byte faderLeft, byte faderLength) {
// if another touch is already down on the same row, make it take over the touch
if (sensorCell->velocity) {
if (faderLength > 0) {
for (byte col = faderLength + faderLeft; col >= faderLeft; --col) {
if (col != sensorCol && cell(col, sensorRow).touched == touchedCell) {
transferToSameRowCell(col);
break;
}
}
}
}
}
void determineFaderBoundaries(byte split, byte& faderLeft, byte& faderLength) {
faderLeft = 1;
faderLength = NUMCOLS-2;
if (Global.splitActive || displayMode == displaySplitPoint) {
if (split == LEFT) {
faderLength = Global.splitPoint - 2;
}
else {
faderLeft = Global.splitPoint;
faderLength = NUMCOLS - Global.splitPoint - 1;
}
}
}
byte calculateFaderValue(short x, byte faderLeft, byte faderLength) {
int32_t fxdFaderRange = FXD_MUL(FXD_FROM_INT(faderLength), FXD_CALX_FULL_UNIT);
int32_t fxdFaderPosition = FXD_FROM_INT(x) - Device.calRows[faderLeft][0].fxdReferenceX;
int32_t fxdFaderRatio = FXD_DIV(fxdFaderPosition, fxdFaderRange);
int32_t fxdFaderValue = FXD_MUL(FXD_CONST_127, fxdFaderRatio);
return constrain(FXD_TO_INT(fxdFaderValue), 0, 127);
}
int32_t fxdCalculateFaderPosition(byte value, byte faderLeft, byte faderLength) {
return fxdCalculateFaderPosition(value, faderLeft, faderLength, FXD_CONST_127);
}
int32_t fxdCalculateFaderPosition(byte value, byte faderLeft, byte faderLength, int32_t fxdMaxValue) {
int32_t fxdFaderRange = FXD_MUL(FXD_FROM_INT(faderLength), FXD_CALX_FULL_UNIT);
int32_t fxdFaderRatio = FXD_DIV(FXD_FROM_INT(value), fxdMaxValue);
int32_t fxdFaderPosition = FXD_MUL(fxdFaderRange, fxdFaderRatio) + Device.calRows[faderLeft][0].fxdReferenceX;
return fxdFaderPosition;
}