forked from rogerlinndesign/linnstrument-firmware
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ls_faders.ino
128 lines (114 loc) · 4.76 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
/******************************* ls_faders: LinnStrument CC Faders ********************************
This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/
or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
***************************************************************************************************
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;
}