Skip to content

Commit

Permalink
display: refactor text output and show preset
Browse files Browse the repository at this point in the history
  • Loading branch information
paradajz committed Mar 13, 2024
1 parent 3ab7714 commit 729130b
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 71 deletions.
106 changes: 60 additions & 46 deletions src/firmware/application/io/i2c/peripherals/display/Display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,15 @@ Display::Display(I2C::Peripheral::HWA& hwa,
}
});

MIDIDispatcher.listen(messaging::eventType_t::SYSTEM,
[this](const messaging::event_t& event)
{
if (event.systemMessage == messaging::systemMessage_t::PRESET_CHANGED)
{
displayPreset(event.index + 1);
}
});

ConfigHandler.registerConfig(
sys::Config::block_t::I2C,
// read
Expand Down Expand Up @@ -113,14 +122,14 @@ bool Display::init()
_resolution = resolution;

// init char arrays
for (int i = 0; i < LCD_HEIGHT_MAX; i++)
for (int i = 0; i < MAX_ROWS; i++)
{
for (int j = 0; j < LCD_STRING_BUFFER_SIZE - 2; j++)
for (int j = 0; j < MAX_COLUMNS - 2; j++)
{
_lcdRowText[i][j] = ' ';
}

_lcdRowText[i][LCD_STRING_BUFFER_SIZE - 1] = '\0';
_lcdRowText[i][MAX_COLUMNS - 1] = '\0';
}

_initialized = true;
Expand All @@ -137,6 +146,7 @@ bool Display::init()

clearEvent(eventType_t::IN);
clearEvent(eventType_t::OUT);
displayPreset(_database.getPreset() + 1);
}
else
{
Expand Down Expand Up @@ -261,34 +271,24 @@ void Display::update()
return; // we don't need to update lcd in real time
}

// use char pointer to point to line we're going to print
char* charPointer;

for (int i = 0; i < LCD_HEIGHT_MAX; i++)
for (int i = 0; i < MAX_ROWS; i++)
{
charPointer = _lcdRowText[i];

if (!_charChange[i])
{
continue;
}

int8_t stringLen = strlen(charPointer) > LCD_WIDTH_MAX ? LCD_WIDTH_MAX : strlen(charPointer);
auto& row = _lcdRowText[i];
const int strSize = strlen(&row[0]);

for (int j = 0; j < stringLen; j++)
for (int j = 0; j < strSize; j++)
{
if (core::util::BIT_READ(_charChange[i], j))
{
u8x8_DrawGlyph(&_u8x8, j, ROW_MAP[_resolution][i], charPointer[j]);
u8x8_DrawGlyph(&_u8x8, j, ROW_MAP[_resolution][i], row[j]);
}
}

// now fill remaining columns with spaces
for (uint16_t j = stringLen; j < LCD_WIDTH_MAX; j++)
{
u8x8_DrawGlyph(&_u8x8, j, ROW_MAP[_resolution][i], ' ');
}

_charChange[i] = 0;
}

Expand All @@ -312,8 +312,7 @@ void Display::update()
/// This function only updates internal buffers with received text, actual updating is done in update() function.
/// Text isn't passed directly, instead, value from string builder is used.
/// param [in]: row Row which is being updated.
/// param [in]: startIndex Index on which received text should on specified row.
void Display::updateText(uint8_t row, uint8_t startIndex)
void Display::updateText(uint8_t row)
{
if (!_initialized)
{
Expand All @@ -323,19 +322,14 @@ void Display::updateText(uint8_t row, uint8_t startIndex)
auto string = _stringBuilder.string();
auto size = strlen(string);

if ((size + startIndex) >= (LCD_STRING_BUFFER_SIZE - 2))
{
size = LCD_STRING_BUFFER_SIZE - 2 - startIndex; // trim string
}

for (size_t i = 0; i < size; i++)
{
if (_lcdRowText[row][startIndex + i] != string[i])
if (_lcdRowText[row][i] != string[i])
{
core::util::BIT_SET(_charChange[row], startIndex + i);
core::util::BIT_SET(_charChange[row], i);
}

_lcdRowText[row][startIndex + i] = string[i];
_lcdRowText[row][i] = string[i];
}
}

Expand Down Expand Up @@ -431,19 +425,39 @@ void Display::displayWelcomeMessage()
core::mcu::timing::waitMs(2000);
}

void Display::displayPreset(int preset)
{
if (!_initialized)
{
return;
}

_lcdRowText.at(ROW_START_PRESET).at(COLUMN_START_PRESET) = '\0';
_stringBuilder.overwrite(_lcdRowText[ROW_START_PRESET].data());
_stringBuilder.append(" P%d", preset);
_stringBuilder.fillUntil(MAX_COLUMNS);

updateText(ROW_START_PRESET);
}

void Display::displayEvent(eventType_t type, const messaging::event_t& event)
{
if (!_initialized)
{
return;
}

uint8_t startRow = (type == Display::eventType_t::IN) ? ROW_START_IN_MESSAGE : ROW_START_OUT_MESSAGE;
uint8_t startColumn = (type == Display::eventType_t::IN) ? COLUMN_START_IN_MESSAGE : COLUMN_START_OUT_MESSAGE;
uint8_t startRow = (type == Display::eventType_t::IN) ? ROW_START_IN_MESSAGE : ROW_START_OUT_MESSAGE;

_stringBuilder.overwrite("%s", Strings::MIDI_MESSAGE(event.message));
_stringBuilder.fillUntil(MAX_COLUMNS - startColumn - strlen(_stringBuilder.string()));
updateText(startRow, startColumn);
_stringBuilder.overwrite("%s%s",
(type == Display::eventType_t::IN)
? Strings::IN_EVENT_STRING
: Strings::OUT_EVENT_STRING,
Strings::MIDI_MESSAGE(event.message));
_stringBuilder.fillUntil((type == Display::eventType_t::IN)
? MAX_COLUMNS_IN_MESSAGE
: MAX_COLUMNS_OUT_MESSAGE);
updateText(startRow);

switch (event.message)
{
Expand All @@ -462,16 +476,16 @@ void Display::displayEvent(eventType_t type, const messaging::event_t& event)
}

_stringBuilder.append(" v%d CH%d", event.value, event.channel);
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(startRow + 1, 0);
_stringBuilder.fillUntil(MAX_COLUMNS);
updateText(startRow + 1);
}
break;

case MIDI::messageType_t::PROGRAM_CHANGE:
{
_stringBuilder.overwrite("%d CH%d", event.index, event.channel);
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(startRow + 1, 0);
_stringBuilder.fillUntil(MAX_COLUMNS);
updateText(startRow + 1);
}
break;

Expand All @@ -481,8 +495,8 @@ void Display::displayEvent(eventType_t type, const messaging::event_t& event)
case MIDI::messageType_t::NRPN_14BIT:
{
_stringBuilder.overwrite("%d %d CH%d", event.index, event.value, event.channel);
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(startRow + 1, 0);
_stringBuilder.fillUntil(MAX_COLUMNS);
updateText(startRow + 1);
}
break;

Expand All @@ -493,8 +507,8 @@ void Display::displayEvent(eventType_t type, const messaging::event_t& event)
case MIDI::messageType_t::MMC_PAUSE:
{
_stringBuilder.overwrite("CH%d", event.index);
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(startRow + 1, 0);
_stringBuilder.fillUntil(MAX_COLUMNS);
updateText(startRow + 1);
}
break;

Expand All @@ -508,7 +522,7 @@ void Display::displayEvent(eventType_t type, const messaging::event_t& event)
{
_stringBuilder.overwrite("");
_stringBuilder.fillUntil(MAX_COLUMNS);
updateText(startRow + 1, 0);
updateText(startRow + 1);
}
break;

Expand All @@ -534,11 +548,11 @@ void Display::clearEvent(eventType_t type)
// first row
_stringBuilder.overwrite(Strings::IN_EVENT_STRING);
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(ROW_START_IN_MESSAGE, 0);
updateText(ROW_START_IN_MESSAGE);
// second row
_stringBuilder.overwrite("");
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(ROW_START_IN_MESSAGE + 1, 0);
updateText(ROW_START_IN_MESSAGE + 1);
}
break;

Expand All @@ -547,11 +561,11 @@ void Display::clearEvent(eventType_t type)
// first row
_stringBuilder.overwrite(Strings::OUT_EVENT_STRING);
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(ROW_START_OUT_MESSAGE, 0);
updateText(ROW_START_OUT_MESSAGE);
// second row
_stringBuilder.overwrite("");
_stringBuilder.fillUntil(MAX_COLUMNS - strlen(_stringBuilder.string()));
updateText(ROW_START_OUT_MESSAGE + 1, 0);
updateText(ROW_START_OUT_MESSAGE + 1);
}
break;

Expand Down
44 changes: 19 additions & 25 deletions src/firmware/application/io/i2c/peripherals/display/Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,10 @@ namespace io
bool deInit();
void setAlternateNoteDisplay(bool state);
void setRetentionTime(uint32_t retentionTime);
void displayPreset(int preset);
void displayEvent(eventType_t type, const messaging::event_t& event);
void displayWelcomeMessage();
void updateText(uint8_t row, uint8_t startIndex);
void updateText(uint8_t row);
uint8_t getTextCenter(uint8_t textSize);
int8_t normalizeOctave(uint8_t octave, int8_t normalization);
void buildString(const char* text, ...);
Expand All @@ -97,32 +98,24 @@ namespace io
0x3D
};

/// Size of buffer used to build text string on display in bytes.
static constexpr uint8_t LCD_STRING_BUFFER_SIZE = 40;

/// Length of temporary (message) text on display in milliseconds.
static constexpr uint16_t LCD_MESSAGE_DURATION = 1500;

/// Time in milliseconds after text on display is being refreshed.
static constexpr uint16_t LCD_REFRESH_TIME = 30;

/// Maximum amount of characters displayed in single LCD row.
/// Real width is determined later based on display type.
static constexpr uint16_t LCD_WIDTH_MAX = 32;

/// Maximum number of LCD rows.
/// Real height is determined later based on display type.
static constexpr uint8_t LCD_HEIGHT_MAX = 4;

static constexpr auto MAX_COLUMNS = 16;
static constexpr auto COLUMN_START_IN_MESSAGE = std::char_traits<char>::length(Strings::IN_EVENT_STRING);
static constexpr auto COLUMN_START_OUT_MESSAGE = std::char_traits<char>::length(Strings::OUT_EVENT_STRING);

static constexpr uint8_t ROW_START_IN_MESSAGE = 0;
static constexpr uint8_t ROW_START_OUT_MESSAGE = 2;

// u8x8 lib doesn't send packets larger than 32 bytes
static constexpr size_t U8X8_BUFFER_SIZE = 32;
static constexpr uint8_t MAX_ROWS = 4;
static constexpr uint8_t MAX_COLUMNS = 16;
static constexpr uint8_t TEXT_BUFFER_SIZE = MAX_COLUMNS + 1;
static constexpr auto COLUMN_START_IN_MESSAGE = std::char_traits<char>::length(Strings::IN_EVENT_STRING);
static constexpr auto COLUMN_START_OUT_MESSAGE = std::char_traits<char>::length(Strings::OUT_EVENT_STRING);
static constexpr auto COLUMN_START_PRESET = 12;
static constexpr auto MAX_COLUMNS_IN_MESSAGE = COLUMN_START_PRESET;
static constexpr auto MAX_COLUMNS_OUT_MESSAGE = COLUMN_START_PRESET;
static constexpr uint8_t ROW_START_IN_MESSAGE = 0;
static constexpr uint8_t ROW_START_OUT_MESSAGE = 2;
static constexpr uint8_t ROW_START_PRESET = ROW_START_IN_MESSAGE;
static constexpr size_t U8X8_BUFFER_SIZE = 32;

uint8_t _u8x8Buffer[U8X8_BUFFER_SIZE] = {};
size_t _u8x8Counter = 0;
Expand All @@ -144,11 +137,12 @@ namespace io
uint32_t _lastLCDupdateTime = 0;

/// Array holding LCD text for each LCD row.
char _lcdRowText[LCD_HEIGHT_MAX][LCD_STRING_BUFFER_SIZE] = {};
using textArray_t = std::array<std::array<char, TEXT_BUFFER_SIZE>, MAX_ROWS>;
textArray_t _lcdRowText = {};

/// Array holding true of false value representing the change of character at specific location on LCD row.
/// \warning This variables assume there can be no more than 32 characters per LCD row.
uint32_t _charChange[LCD_HEIGHT_MAX] = {};
uint32_t _charChange[MAX_ROWS] = {};

/// Holds value by which actual octave is being subtracted when showing octave on display.
int8_t _octaveNormalization = 0;
Expand All @@ -160,12 +154,12 @@ namespace io
bool _initialized = false;

/// Object used for easier string manipulation on display.
core::util::StringBuilder<LCD_STRING_BUFFER_SIZE> _stringBuilder;
core::util::StringBuilder<TEXT_BUFFER_SIZE> _stringBuilder;

/// Array holding remapped values of LCD rows.
/// Used to increase readability.
/// Matched with displayResolution_t enum.
static constexpr uint8_t ROW_MAP[static_cast<uint8_t>(displayResolution_t::AMOUNT)][LCD_HEIGHT_MAX] = {
static constexpr uint8_t ROW_MAP[static_cast<uint8_t>(displayResolution_t::AMOUNT)][MAX_ROWS] = {
// 128x32
{
0,
Expand Down

0 comments on commit 729130b

Please sign in to comment.