Control Surface master
MIDI Control Surface library for Arduino
LCD.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <AH/Debug/Debug.hpp>
6#include <string.h> // memcpy
7
8#ifndef ARDUINO
9#include <cassert>
10#endif
11
13
14using AH::max;
15using AH::min;
16
17namespace MCU {
18
23 public:
26
27 static uint8_t getInstances() { return instances; }
28
29 private:
30 static uint8_t instances;
31};
50template <uint8_t BufferSize = 112>
51class LCD : public MIDIInputElementSysEx, private LCDCounter {
52 public:
62 LCD(uint8_t offset = 0, Cable cable = CABLE_1)
64 // Null-terminate the buffer
65 buffer[BufferSize] = '\0';
66 // Fill the buffer with spaces
67 for (uint8_t i = 0; i < BufferSize; i++)
68 buffer[i] = ' ';
69 }
70
71 protected:
72 bool updateWith(SysExMessage midimsg) override {
73 // If this message is meant for a different cable than ours, return:
74 if (midimsg.getCable() != this->cable)
75 return false;
76
77 // We can't handle chunked SysEx data (yet), and it wouldn't make a ton
78 // of sense, since the default SysEx buffer size is the same size as the
79 // SysEx message we expect, so it shouldn't arrive in chunks.
80 if (!midimsg.isCompleteMessage())
81 return false;
82
83 // Format:
84 // F0 mm mm mm nn 12 oo yy... F7
85 // mm = manufacturer ID (00 00 66 for Mackie)
86 // nn = model number (10 for Logic Control, 11 for Logic Control XT)
87 // oo = offset [0x00, 0x6F]
88 // yy... = ASCII data
89 if (midimsg.data[5] != 0x12)
90 return false;
91
92 const uint8_t midiOffset = midimsg.data[6];
93 const uint8_t midiLength = midimsg.length - 8;
94 const uint8_t *text = midimsg.data + 7;
95 const uint8_t midiBufferEnd = midiOffset + midiLength;
96
97 const uint8_t bufferEnd = this->offset + BufferSize;
98
99 // If there's no overlap between incoming range and the range that we're
100 // listening for, return:
101 if (midiOffset >= bufferEnd || this->offset >= midiBufferEnd)
102 // If there are other instances, maybe it'll match one of those,
103 // otherwise, stop handling this message:
104 return getInstances() == 1;
105
106 // Find the ranges that overlap between the text data in the message
107 // (src) and the range of characters we're listening for (dst):
108 uint8_t srcStart = max(0, this->offset - midiOffset);
109 uint8_t dstStart = max(0, midiOffset - this->offset);
110 uint8_t length = midiBufferEnd - midiOffset -
111 max(0, this->offset - midiOffset) -
112 max(0, midiBufferEnd - bufferEnd);
113
114 // Copy the interesting part to our buffer:
115#ifdef ARDUINO
116 memcpy(&buffer[dstStart], &text[srcStart], length);
117#else // Tests
118 for (uint8_t i = 0; i < length; ++i) {
119 buffer[dstStart + i] = text[srcStart + i];
120 assert(dstStart + i < BufferSize);
121 assert(srcStart + i < midiLength);
122 }
123#endif
124
125 dirty = true;
126
127 // If this is the only instance, the others don't have to be updated
128 // anymore, so we return true to break the loop:
129 return getInstances() == 1;
130 }
131
132 public:
135
137 const char *getText() const { return buffer.data; }
138
140
143
146 bool getDirty() const { return dirty; }
148 void clearDirty() { dirty = false; }
149
151
152 private:
154 uint8_t offset;
156 bool dirty = true;
157};
158
159} // namespace MCU
160
constexpr Cable CABLE_1
Definition: Cable.hpp:118
#define END_CS_NAMESPACE
#define BEGIN_CS_NAMESPACE
A type-safe class for MIDI USB Cable numbers.
Definition: Cable.hpp:13
Counts the number of instances of the LCD class.
Definition: LCD.hpp:22
static uint8_t getInstances()
Definition: LCD.hpp:27
static uint8_t instances
Definition: LCD.hpp:30
A class that represents the Mackie Control Universal LCD display and saves the text it receives.
Definition: LCD.hpp:51
const char * getText() const
Get a pointer to the null-terminated display text.
Definition: LCD.hpp:137
LCD(uint8_t offset=0, Cable cable=CABLE_1)
Definition: LCD.hpp:62
bool getDirty() const
Check if the text was updated since the last time the dirty flag was cleared.
Definition: LCD.hpp:146
Cable cable
Definition: LCD.hpp:155
uint8_t offset
Definition: LCD.hpp:154
Array< char, BufferSize+1 > buffer
Definition: LCD.hpp:153
bool dirty
Definition: LCD.hpp:156
bool updateWith(SysExMessage midimsg) override
Definition: LCD.hpp:72
void clearDirty()
Clear the dirty flag.
Definition: LCD.hpp:148
A class for objects that listen for incoming MIDI events.
constexpr auto min(const T &a, const U &b) -> decltype(b< a ? b :a)
Return the smaller of two numbers/objects.
Definition: MinMaxFix.hpp:15
constexpr auto max(const T &a, const U &b) -> decltype(a< b ? b :a)
Return the larger of two numbers/objects.
Definition: MinMaxFix.hpp:22
An array wrapper for easy copying, comparing, and iterating.
Definition: Array.hpp:36
const uint8_t * data
Cable getCable() const
Get the MIDI USB cable number of the message.
bool isCompleteMessage() const