mirror of https://github.com/probonopd/MiniDexed
parent
0a5ec7d529
commit
bdae61102a
@ -0,0 +1 @@ |
|||||||
|
{"buildTargets":[],"launchTargets":[],"customConfigurationProvider":{"workspaceBrowse":{"browsePath":[],"compilerArgs":[]},"fileIndex":[]}} |
@ -0,0 +1,4 @@ |
|||||||
|
make.exe --dry-run --keep-going --print-directory |
||||||
|
'make.exe' is not recognized as an internal or external command, |
||||||
|
operable program or batch file. |
||||||
|
|
@ -0,0 +1,3 @@ |
|||||||
|
{ |
||||||
|
"makefile.extensionOutputFolder": "./.vscode" |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
make.exe all --print-data-base --no-builtin-variables --no-builtin-rules --question |
||||||
|
'make.exe' is not recognized as an internal or external command, |
||||||
|
operable program or batch file. |
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 183 KiB |
@ -0,0 +1,49 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
set -e |
||||||
|
set -x |
||||||
|
|
||||||
|
if [ -z "${RPI}" ] ; then |
||||||
|
# echo "\$RPI missing, exting" |
||||||
|
# exit 1 |
||||||
|
export RPI=4 |
||||||
|
fi |
||||||
|
|
||||||
|
if [ "${RPI}" -gt "2" ]; then |
||||||
|
export TOOLCHAIN_PREFIX="aarch64-none-elf-" |
||||||
|
else |
||||||
|
export TOOLCHAIN_PREFIX="arm-none-eabi-" |
||||||
|
fi |
||||||
|
|
||||||
|
# Define system options |
||||||
|
OPTIONS="-o USE_PWM_AUDIO_ON_ZERO -o SAVE_VFP_REGS_ON_IRQ -o REALTIME -o SCREEN_DMA_BURST_LENGTH=1" |
||||||
|
if [ "${RPI}" -gt "1" ]; then |
||||||
|
OPTIONS="${OPTIONS} -o ARM_ALLOW_MULTI_CORE" |
||||||
|
fi |
||||||
|
|
||||||
|
# Build circle-stdlib library |
||||||
|
# cd circle-stdlib/ |
||||||
|
# make mrproper || true |
||||||
|
# ./configure -r ${RPI} --prefix "${TOOLCHAIN_PREFIX}" ${OPTIONS} -o KERNEL_MAX_SIZE=0x400000 |
||||||
|
# make -j |
||||||
|
|
||||||
|
# Build additional libraries |
||||||
|
# cd libs/circle/addon/display/ |
||||||
|
# make clean || true |
||||||
|
# make -j |
||||||
|
# cd ../sensor/ |
||||||
|
# make clean || true |
||||||
|
# make -j |
||||||
|
# cd ../Properties/ |
||||||
|
# make clean || true |
||||||
|
# make -j |
||||||
|
# cd ../../../.. |
||||||
|
|
||||||
|
# cd .. |
||||||
|
|
||||||
|
# Build MiniDexed |
||||||
|
cd src |
||||||
|
# make clean || true |
||||||
|
make -j |
||||||
|
ls *.img |
||||||
|
cd .. |
@ -0,0 +1,23 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
set -e |
||||||
|
set -x |
||||||
|
|
||||||
|
export RPI=4 |
||||||
|
|
||||||
|
export PATH=$(readlink -f ./gcc-*/bin/):$PATH |
||||||
|
|
||||||
|
./incrementalBuild.sh |
||||||
|
cp ./src/kernel*.img ./kernels/ |
||||||
|
|
||||||
|
# Make zip that contains Raspberry Pi 4 boot files. The contents can be copied to a FAT32 formatted partition on a microSD card |
||||||
|
cp -r ./circle-stdlib/libs/circle/boot/* sdcard |
||||||
|
rm -rf sdcard/config*.txt sdcard/README sdcard/Makefile sdcard/armstub sdcard/COPYING.linux |
||||||
|
cp ./src/config.txt ./src/minidexed.ini ./src/*img ./src/performance.ini sdcard/ |
||||||
|
echo "usbspeed=full" > sdcard/cmdline.txt |
||||||
|
cd sdcard |
||||||
|
cp ../kernels/* . || true |
||||||
|
zip -r ../MiniDexed_$GITHUB_RUN_NUMBER_$(date +%Y-%m-%d).zip * |
||||||
|
cd - |
||||||
|
|
||||||
|
echo "DONE!!!" |
@ -0,0 +1,72 @@ |
|||||||
|
#!/bin/bash |
||||||
|
|
||||||
|
# this script install the dev environment and assume that the repositorw is alreadw cloned |
||||||
|
|
||||||
|
# Choose your RPi |
||||||
|
export RPI=4 |
||||||
|
|
||||||
|
#git clone https://github.com/probonopd/MiniDexed |
||||||
|
#cd MiniDexed |
||||||
|
mkdir -p kernels sdcard |
||||||
|
|
||||||
|
# Get develop branch of circle |
||||||
|
cd circle-stdlib/libs/circle |
||||||
|
git checkout ae22928 # develop |
||||||
|
cd - |
||||||
|
|
||||||
|
# Recursively pull git submodules |
||||||
|
git submodule update --init --recursive |
||||||
|
|
||||||
|
# Install toolchain |
||||||
|
if [ "${RPI}" -gt 2 ] |
||||||
|
then |
||||||
|
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf.tar.xz |
||||||
|
else |
||||||
|
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-eabi.tar.xz |
||||||
|
fi |
||||||
|
tar xvf gcc-arm-*-*.tar.xz |
||||||
|
export PATH=$(readlink -f ./gcc-*/bin/):$PATH |
||||||
|
|
||||||
|
# Build dependencies and MiniDexed |
||||||
|
./build.sh |
||||||
|
cp ./src/kernel*.img ./kernels/ |
||||||
|
|
||||||
|
# Get Raspberry Pi boot files |
||||||
|
cd ./circle-stdlib/libs/circle/boot |
||||||
|
make |
||||||
|
if [ "${RPI}" -gt 2 ] |
||||||
|
then |
||||||
|
make armstub64 |
||||||
|
fi |
||||||
|
cd - |
||||||
|
|
||||||
|
# Make zip that contains Raspberry Pi 4 boot files. The contents can be copied to a FAT32 formatted partition on a microSD card |
||||||
|
cd sdcard |
||||||
|
../getsysex.sh |
||||||
|
cd .. |
||||||
|
cp -r ./circle-stdlib/libs/circle/boot/* sdcard |
||||||
|
rm -rf sdcard/config*.txt sdcard/README sdcard/Makefile sdcard/armstub sdcard/COPYING.linux |
||||||
|
cp ./src/config.txt ./src/minidexed.ini ./src/*img ./src/performance.ini sdcard/ |
||||||
|
echo "usbspeed=full" > sdcard/cmdline.txt |
||||||
|
cd sdcard |
||||||
|
cp ../kernels/* . || true |
||||||
|
zip -r ../MaxiDexed_$GITHUB_RUN_NUMBER_$(date +%Y-%m-%d).zip * |
||||||
|
cd - |
||||||
|
|
||||||
|
# # Optionally, create a RPi image. This can be written to a microSD card using tools like Etcher or dd |
||||||
|
# sudo apt install --yes mount parted |
||||||
|
# IMG="`date +%Y-%m-%d`_minidexed-RPi${RPI}.img" |
||||||
|
# dd of="${IMG}" seek=50MiB bs=1 count=0 |
||||||
|
# sudo parted "${IMG}" mktable msdos |
||||||
|
# sudo parted "${IMG}" mkpart primary fat32 2048s 100% |
||||||
|
# DEV=`sudo losetup --find --partscan --show "${IMG}"` |
||||||
|
# sudo mkfs.vfat -F 32 -n BOOT "${DEV}p1" |
||||||
|
# mkdir boot |
||||||
|
# sudo mount "${DEV}p1" boot |
||||||
|
# sudo cp -R sdcard/* boot |
||||||
|
# sudo umount boot |
||||||
|
# sudo losetup -d "${DEV}" |
||||||
|
# rm -r boot |
||||||
|
|
||||||
|
# # Write to SD card |
||||||
|
# sudo dd if="${IMG}" of=/dev/mmcblk0 bs=512k status=progress && sync |
@ -0,0 +1,64 @@ |
|||||||
|
#include "screens.h" |
||||||
|
|
||||||
|
CPerformanceScreen::CPerformanceScreen() :
|
||||||
|
CScreen(PerformanceScreen, "Performance", PerformanceScreenPageCount) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CPerformanceScreen::~CPerformanceScreen() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CPerformanceEditScreen::CPerformanceEditScreen() : |
||||||
|
CScreen(PerformanceEditScreen, "Perf. edit", PerformanceEditScreenPageCount) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CPerformanceEditScreen::~CPerformanceEditScreen() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CVoiceScreen::CVoiceScreen() :
|
||||||
|
CScreen(VoiceScreen, "Voice", VoiceScreenPageCount) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CVoiceScreen::~CVoiceScreen() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CVoiceEditScreen::CVoiceEditScreen() :
|
||||||
|
CScreen(VoiceEditScreen, "Voice edit", VoiceEditScreenPageCount) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CVoiceEditScreen::~CVoiceEditScreen() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
COperatorScreen::COperatorScreen() :
|
||||||
|
CScreen(OperatorScreen, "Op. edit", OperatorScreenPageCount) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
COperatorScreen::~COperatorScreen() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CFxScreen::CFxScreen() : |
||||||
|
CScreen(FxScreen, "FX", FxScreenPageCount) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CFxScreen::~CFxScreen() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CNameEditScreen::CNameEditScreen(const char* pszScreenName) : |
||||||
|
CScreen(NameEditScreen, pszScreenName, NameEditScreenPageCount) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CNameEditScreen::~CNameEditScreen() |
||||||
|
{ |
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
//
|
||||||
|
// minidexed.h
|
||||||
|
//
|
||||||
|
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
|
||||||
|
// Copyright (C) 2022 The MiniDexed Team
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#ifndef _screens_h |
||||||
|
#define _screens_h |
||||||
|
|
||||||
|
#include <ui.h> |
||||||
|
#include <minidexed.h> |
||||||
|
|
||||||
|
enum ScreenID |
||||||
|
{ |
||||||
|
PerformanceScreen = 0, |
||||||
|
PerformanceEditScreen, |
||||||
|
VoiceScreen, |
||||||
|
VoiceEditScreen, |
||||||
|
OperatorScreen, |
||||||
|
FxScreen, |
||||||
|
NameEditScreen |
||||||
|
}; |
||||||
|
|
||||||
|
enum ScreenPageCount |
||||||
|
{ |
||||||
|
PerformanceScreenPageCount = 1, |
||||||
|
PerformanceEditScreenPageCount = 3, |
||||||
|
VoiceScreenPageCount = 1, |
||||||
|
VoiceEditScreenPageCount = 3, |
||||||
|
OperatorScreenPageCount = 1, |
||||||
|
FxScreenPageCount = 1, |
||||||
|
NameEditScreen = 1 |
||||||
|
}; |
||||||
|
|
||||||
|
class CPerformanceScreen : public CScreen
|
||||||
|
{ |
||||||
|
public: |
||||||
|
CPerformanceScreen(); |
||||||
|
virtual ~CPerformanceScreen(); |
||||||
|
}; |
||||||
|
|
||||||
|
class CPerformanceEditScreen : public CScreen
|
||||||
|
{ |
||||||
|
public: |
||||||
|
CPerformanceEditScreen(); |
||||||
|
virtual ~CPerformanceEditScreen(); |
||||||
|
}; |
||||||
|
|
||||||
|
class CVoiceScreen : public CScreen
|
||||||
|
{ |
||||||
|
public: |
||||||
|
CVoiceScreen(); |
||||||
|
virtual ~CVoiceScreen(); |
||||||
|
}; |
||||||
|
|
||||||
|
class CVoiceEditScreen : public CScreen
|
||||||
|
{ |
||||||
|
public: |
||||||
|
CVoiceEditScreen(); |
||||||
|
virtual ~CVoiceEditScreen(); |
||||||
|
}; |
||||||
|
|
||||||
|
class COperatorScreen : public CScreen
|
||||||
|
{ |
||||||
|
public: |
||||||
|
COperatorScreen(); |
||||||
|
virtual ~COperatorScreen(); |
||||||
|
}; |
||||||
|
|
||||||
|
class CFxScreen : public CScreen |
||||||
|
{ |
||||||
|
public: |
||||||
|
CFxScreen(); |
||||||
|
~CFxScreen(); |
||||||
|
}; |
||||||
|
|
||||||
|
class CNameEditScreen : public CScreen |
||||||
|
{ |
||||||
|
public: |
||||||
|
CNameEditScreen(); |
||||||
|
~CNameEditScreen(); |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,614 @@ |
|||||||
|
#include "ui.h" |
||||||
|
|
||||||
|
#include <assert.h> |
||||||
|
|
||||||
|
LOGMODULE ("ui"); |
||||||
|
|
||||||
|
/* CPaint */ |
||||||
|
CPaint::CPaint(uint8_t sdi, uint8_t sda, uint8_t reset) : m_display(U8G2_R0, reset, sdi, sda) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CPaint::~CPaint() |
||||||
|
{ |
||||||
|
this->m_display.clearDisplay(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::Initialize() |
||||||
|
{ |
||||||
|
this->m_display.initDisplay(); |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t CPaint::GetBusClock() |
||||||
|
{ |
||||||
|
return this->m_display.getBusClock(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetBusClock(uint32_t clock_speed) |
||||||
|
{ |
||||||
|
this->m_display.setBusClock(clock_speed); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetI2CAddress(uint8_t adr) |
||||||
|
{ |
||||||
|
this->m_display.setI2CAddress(adr); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::EnableUTF8Print() |
||||||
|
{ |
||||||
|
this->m_display.enableUTF8Print(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DisableUTF8Print() |
||||||
|
{ |
||||||
|
this->m_display.disableUTF8Print(); |
||||||
|
} |
||||||
|
|
||||||
|
unsigned CPaint::Width() |
||||||
|
{ |
||||||
|
return this->m_display.getDisplayWidth(); |
||||||
|
} |
||||||
|
|
||||||
|
unsigned CPaint::Height() |
||||||
|
{ |
||||||
|
return this->m_display.getDisplayHeight(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::Clear() |
||||||
|
{ |
||||||
|
this->m_display.clearDisplay(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetPowerSave(uint8_t is_enable) |
||||||
|
{ |
||||||
|
this->m_display.setPowerSave(is_enable); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFlipMode(uint8_t mode) |
||||||
|
{ |
||||||
|
this->m_display.setFlipMode(mode); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetContrast(uint8_t value) |
||||||
|
{ |
||||||
|
this->m_display.setContrast(value); |
||||||
|
} |
||||||
|
|
||||||
|
bool CPaint::Begin() |
||||||
|
{ |
||||||
|
this->m_display.begin(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::BeginSimple() |
||||||
|
{ |
||||||
|
this->m_display.beginSimple(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetMaxClipWindow() |
||||||
|
{ |
||||||
|
this->m_display.setMaxClipWindow(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetClipWindow(uint8_t clip_x0, uint8_t clip_y0, uint8_t clip_x1, uint8_t clip_y1) |
||||||
|
{ |
||||||
|
this->m_display.setClipWindow(clip_x0, clip_y0, clip_x1, clip_y1); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SendBuffer() |
||||||
|
{ |
||||||
|
this->m_display.sendBuffer(); |
||||||
|
} |
||||||
|
void CPaint::ClearBuffer() |
||||||
|
{ |
||||||
|
this->m_display.clearBuffer(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::FirstPage() |
||||||
|
{ |
||||||
|
this->m_display.firstPage(); |
||||||
|
} |
||||||
|
uint8_t CPaint::NextPage() |
||||||
|
{ |
||||||
|
this->m_display.nextPage(); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t* CPaint::GetBufferPtr() |
||||||
|
{ |
||||||
|
return this->m_display.getBufferPtr(); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::GetBufferTileHeight() |
||||||
|
{ |
||||||
|
return this->m_display.getBufferTileHeight(); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::GetBufferTileWidth() |
||||||
|
{ |
||||||
|
return this->m_display.getBufferTileWidth(); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::GetPageCurrTileRow() |
||||||
|
{ |
||||||
|
return this->m_display.getPageCurrTileRow(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetPageCurrTileRow(uint8_t row) |
||||||
|
{ |
||||||
|
this->m_display.setPageCurrTileRow(row); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::GetBufferCurrTileRow() |
||||||
|
{ |
||||||
|
return this->m_display.getBufferCurrTileRow(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetBufferCurrTileRow(uint8_t row) |
||||||
|
{ |
||||||
|
this->m_display.setBufferCurrTileRow(row); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetBufferAutoClear(uint8_t mode) |
||||||
|
{ |
||||||
|
this->m_display.setAutoPageClear(mode); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::UpdateDisplayArea(uint8_t tx, uint8_t ty, uint8_t tw, uint8_t th) |
||||||
|
{ |
||||||
|
this->m_display.updateDisplayArea(tx, ty, tw, th); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::UpdateDisplay() |
||||||
|
{ |
||||||
|
this->m_display.updateDisplay(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::RefreshDisplay() |
||||||
|
{ |
||||||
|
this->m_display.refreshDisplay(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetDrawColor(uint8_t color_index) |
||||||
|
{ |
||||||
|
this->m_display.setDrawColor(color_index); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::GetDrawColor() |
||||||
|
{ |
||||||
|
this->m_display.getDrawColor(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawPixel(uint8_t x, uint8_t y) |
||||||
|
{ |
||||||
|
this->m_display.drawPixel(x, y); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawHLine(uint8_t x, uint8_t y, uint8_t w) |
||||||
|
{ |
||||||
|
this->m_display.drawHLine(x, y, w); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawVLine(uint8_t x, uint8_t y, uint8_t h) |
||||||
|
{ |
||||||
|
this->m_display.drawVLine(x, y, h); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawHVLine(uint8_t x, uint8_t y, uint8_t len, uint8_t dir) |
||||||
|
{ |
||||||
|
this->m_display.drawHVLine(x, y, len, dir); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h) |
||||||
|
{ |
||||||
|
this->m_display.drawFrame(x, y, w, h); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawRFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r) |
||||||
|
{ |
||||||
|
this->m_display.drawRFrame(x, y, w, h, r); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h) |
||||||
|
{ |
||||||
|
this->m_display.drawBox(x, y, w, h); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawRBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r) |
||||||
|
{ |
||||||
|
this->m_display.drawRBox(x, y, w, h, r); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawButtonUTF8(uint8_t x, uint8_t y, uint8_t flags, uint8_t width, uint8_t padding_h, uint8_t padding_v, const char* text) |
||||||
|
{ |
||||||
|
this->m_display.drawButtonUTF8(x, y, flags, width, padding_h, padding_v, text); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawCircle(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt) |
||||||
|
{ |
||||||
|
this->m_display.drawCircle(x0, y0, rad, opt); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawDisc(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt) |
||||||
|
{ |
||||||
|
this->m_display.drawDisc(x0, y0, rad, opt); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt) |
||||||
|
{ |
||||||
|
this->m_display.drawEllipse(x0, y0, rx, ry, opt); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawFilledEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt) |
||||||
|
{ |
||||||
|
this->m_display.drawFilledEllipse(x0, y0, rx, ry, opt); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) |
||||||
|
{ |
||||||
|
this->m_display.drawLine(x1, y1, x2, y2); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetBitmapMode(uint8_t is_transparent) |
||||||
|
{ |
||||||
|
this->m_display.setBitmapMode(is_transparent); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawBitmap(uint8_t x, uint8_t y, uint8_t cnt, uint8_t h, const uint8_t* bitmap) |
||||||
|
{ |
||||||
|
this->m_display.drawBitmap(x, y, cnt, h, bitmap); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawXBM(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap) |
||||||
|
{ |
||||||
|
this->m_display.drawXBM(x, y, w, h, bitmap); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawXBMP(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap) |
||||||
|
{ |
||||||
|
this->m_display.drawXBMP(x, y, w, h, bitmap); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::DrawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2) |
||||||
|
{ |
||||||
|
this->m_display.drawTriangle(x0, y0, x1, y1, x2, y2); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFont(const uint8_t* font) |
||||||
|
{ |
||||||
|
this->m_display.setFont(font); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontMode(uint8_t is_transparent) |
||||||
|
{ |
||||||
|
this->m_display.setFontMode(is_transparent); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontDirection(uint8_t dir) |
||||||
|
{ |
||||||
|
this->m_display.setFontDirection(dir); |
||||||
|
} |
||||||
|
|
||||||
|
int8_t CPaint::GetAscent() |
||||||
|
{ |
||||||
|
return this->m_display.getAscent(); |
||||||
|
} |
||||||
|
|
||||||
|
int8_t CPaint::GetDescent() |
||||||
|
{ |
||||||
|
return this->m_display.getDescent(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontPosBaseline() |
||||||
|
{ |
||||||
|
this->m_display.setFontPosBaseline(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontPosBottom() |
||||||
|
{ |
||||||
|
this->m_display.setFontPosBottom(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontPosTop() |
||||||
|
{ |
||||||
|
this->m_display.setFontPosTop(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontPosCenter() |
||||||
|
{ |
||||||
|
this->m_display.setFontPosCenter(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontRefHeightText() |
||||||
|
{ |
||||||
|
this->m_display.setFontRefHeightText(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontRefHeightExtendedText() |
||||||
|
{ |
||||||
|
this->m_display.setFontRefHeightExtendedText(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetFontRefHeightAll() |
||||||
|
{ |
||||||
|
this->m_display.setFontRefHeightAll(); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::DrawGlyph(uint8_t x, uint8_t y, uint16_t encoding) |
||||||
|
{ |
||||||
|
this->m_display.drawGlyph(x, y, encoding); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::DrawStr(uint8_t x, uint8_t y, const char* s) |
||||||
|
{ |
||||||
|
this->m_display.drawStr(x, y, s); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::DrawUTF8(uint8_t x, uint8_t y, const char* s) |
||||||
|
{ |
||||||
|
this->m_display.drawUTF8(x, y, s); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::DrawExtUTF8(uint8_t x, uint8_t y, uint8_t to_left, const uint16_t *kerning_table, const char* s) |
||||||
|
{ |
||||||
|
this->m_display.drawExtUTF8(x, y, to_left, kerning_table, s); |
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CPaint::GetStrWidth(const char* s) |
||||||
|
{ |
||||||
|
return this->m_display.getStrWidth(s); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::GetUTF8Width(const char* s) |
||||||
|
{ |
||||||
|
return this->m_display.getUTF8Width(s); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::UISelectionList(const char* title, uint8_t start_pos, const char* sl) |
||||||
|
{ |
||||||
|
this->m_display.userInterfaceSelectionList(title, start_pos, sl); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::UIMessage(const char* title1, const char* title2, const char* title3, const char* buttons) |
||||||
|
{ |
||||||
|
this->m_display.userInterfaceMessage(title1, title2, title3, buttons); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::UIInputValue(const char* title, const char* pre, uint8_t* value, uint8_t lo, uint8_t hi, uint8_t digits, const char* post) |
||||||
|
{ |
||||||
|
return this->m_display.userInterfaceInputValue(title, pre, value, lo, hi, digits, post); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::LCDHome() |
||||||
|
{ |
||||||
|
this->m_display.home(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::LCDClear() |
||||||
|
{ |
||||||
|
this->m_display.clear(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::LCDNoDisplay() |
||||||
|
{ |
||||||
|
this->m_display.noDisplay(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::LCDDisplay() |
||||||
|
{ |
||||||
|
this->m_display.display(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::LCDSetCursor(uint8_t x, uint8_t y) |
||||||
|
{ |
||||||
|
this->m_display.setCursor(x, y); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::LCDGetCursorX() |
||||||
|
{ |
||||||
|
this->m_display.getCursorX(); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::LCDGetCursorY() |
||||||
|
{ |
||||||
|
this->m_display.getCursorY(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SleepOn() |
||||||
|
{ |
||||||
|
this->m_display.sleepOn(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SleepOff() |
||||||
|
{ |
||||||
|
this->m_display.sleepOff(); |
||||||
|
} |
||||||
|
|
||||||
|
void CPaint::SetColorIndex(uint8_t color_index) |
||||||
|
{ |
||||||
|
this->m_display.setColorIndex(color_index); |
||||||
|
} |
||||||
|
|
||||||
|
uint8_t CPaint::GetColorIndex() |
||||||
|
{ |
||||||
|
this->m_display.getColorIndex(); |
||||||
|
} |
||||||
|
|
||||||
|
int8_t CPaint::GetFontAscent() |
||||||
|
{ |
||||||
|
this->m_display.getFontAscent(); |
||||||
|
} |
||||||
|
|
||||||
|
int8_t CPaint::GetFontDescent() |
||||||
|
{ |
||||||
|
this->m_display.getFontDescent(); |
||||||
|
} |
||||||
|
|
||||||
|
int8_t CPaint::GetMaxCharHeight() |
||||||
|
{ |
||||||
|
this->m_display.getMaxCharHeight(); |
||||||
|
} |
||||||
|
|
||||||
|
int8_t CPaint::GetMaxCharWidth() |
||||||
|
{ |
||||||
|
this->m_display.getMaxCharWidth(); |
||||||
|
} |
||||||
|
|
||||||
|
/* CControl */ |
||||||
|
CControl::CControl(CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig) :
|
||||||
|
m_pMiniDexed(pMiniDexed), |
||||||
|
m_pGPIOManager(pGPIOManager), |
||||||
|
m_pConfig(pConfig), |
||||||
|
m_ppRotaryEncoders(nullptr) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CControl::~CControl() |
||||||
|
{ |
||||||
|
if(this->m_ppRotaryEncoders) |
||||||
|
{ |
||||||
|
for(int i = 0; i < NUM_CONTROLS; i++) |
||||||
|
{ |
||||||
|
delete this->m_ppRotaryEncoders[i]; |
||||||
|
} |
||||||
|
|
||||||
|
delete []this->m_ppRotaryEncoders; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool CControl::Initialize() |
||||||
|
{ |
||||||
|
assert(this->m_pConfig); |
||||||
|
|
||||||
|
if(this->m_pConfig->GetEncoderEnabled())
|
||||||
|
{ |
||||||
|
this->m_ppRotaryEncoders = new CKY040*[4]; |
||||||
|
for(int i = 0; i < NUM_CONTROLS; i++) { |
||||||
|
this->m_ppRotaryEncoders[i] = new CKY040( |
||||||
|
this->m_pConfig->GetEncoderPinClock(), |
||||||
|
this->m_pConfig->GetEncoderPinData(), |
||||||
|
this->m_pConfig->GetEncoderPinSwitch(), |
||||||
|
this->m_pGPIOManager |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
CKY040& CControl::operator[](size_t index) |
||||||
|
{ |
||||||
|
return *this->m_ppRotaryEncoders[index % NUM_CONTROLS]; |
||||||
|
} |
||||||
|
|
||||||
|
/* CScreen */ |
||||||
|
CScreen::CScreen(unsigned id, const char* name, unsigned nPages) :
|
||||||
|
m_id(id),
|
||||||
|
m_name(name), |
||||||
|
m_nPages(nPages),
|
||||||
|
m_currentScrollPage(0), |
||||||
|
m_isDirty(false) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CScreen::~CScreen() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void CScreen::Activate(CScreen& nxtScreen) |
||||||
|
{ |
||||||
|
nxtScreen.SetDirty(true); |
||||||
|
} |
||||||
|
|
||||||
|
void CScreen::Activate() |
||||||
|
{ |
||||||
|
CScreen::Activate(*this); |
||||||
|
} |
||||||
|
|
||||||
|
unsigned CScreen::ScrollLeftPage() |
||||||
|
{ |
||||||
|
unsigned nxPage = (this->m_currentScrollPage + 1) % this->m_nPages; |
||||||
|
this->Dirty(this->m_currentScrollPage != nxPage); |
||||||
|
this->m_currentScrollPage = nxPage; |
||||||
|
|
||||||
|
return this->m_currentScrollPage; |
||||||
|
} |
||||||
|
|
||||||
|
unsigned CScreen::ScrollRightPage() |
||||||
|
{ |
||||||
|
unsigned nxPage = (this->m_currentScrollPage + this->m_nPages - 1) % this->m_nPages; |
||||||
|
this->Dirty(this->m_currentScrollPage != nxPage); |
||||||
|
this->m_currentScrollPage = nxPage; |
||||||
|
|
||||||
|
return this->m_currentScrollPage; |
||||||
|
} |
||||||
|
|
||||||
|
unsigned CScreen::CurrentScrollPage() |
||||||
|
{ |
||||||
|
return this->m_currentScrollPage; |
||||||
|
} |
||||||
|
|
||||||
|
unsigned CScreen::ScrollToPage(unsigned pageNum) |
||||||
|
{ |
||||||
|
unsigned nxPage = pageNum % this->m_nPages; |
||||||
|
this->Dirty(this->m_currentScrollPage != nxPage); |
||||||
|
this->m_currentScrollPage = nxPage; |
||||||
|
|
||||||
|
return this->m_currentScrollPage; |
||||||
|
} |
||||||
|
|
||||||
|
void CScreen::SetDirty(bool isDirty) |
||||||
|
{ |
||||||
|
this->m_isDirty = isDirty; |
||||||
|
} |
||||||
|
|
||||||
|
void CScreen::Dirty(bool isDirty) |
||||||
|
{ |
||||||
|
this->m_isDirty |= isDirty; |
||||||
|
} |
||||||
|
|
||||||
|
bool CScreen::IsDirty() |
||||||
|
{ |
||||||
|
return this->m_isDirty; |
||||||
|
} |
||||||
|
|
||||||
|
void CScreen::Display(CPaint& paint) |
||||||
|
{ |
||||||
|
if(this->IsDirty()) |
||||||
|
{ |
||||||
|
this->Paint(paint); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
CScreenManager& CScreenManager::GetInstance() |
||||||
|
{ |
||||||
|
static CScreenManager inst; |
||||||
|
|
||||||
|
return inst; |
||||||
|
} |
||||||
|
|
||||||
|
CScreenManager::CScreenManager() :
|
||||||
|
m_screenMap() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CScreenManager::~CScreenManager() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void CScreenManager::Register(CScreen* pScreen) |
||||||
|
{ |
||||||
|
this->m_screenMap[pScreen->m_id] = pScreen; |
||||||
|
} |
||||||
|
|
||||||
|
CScreen& CScreenManager::operator[](unsigned index) |
||||||
|
{ |
||||||
|
return *(this->m_screenMap[index]); |
||||||
|
} |
||||||
|
|
||||||
|
CScreen& CScreenManager::Activate(unsigned screenId) |
||||||
|
{ |
||||||
|
CScreen& nxtScreen = (*this)[screenId]; |
||||||
|
CScreen::Activate(nxtScreen); |
||||||
|
|
||||||
|
return nxtScreen; |
||||||
|
} |
@ -0,0 +1,242 @@ |
|||||||
|
//
|
||||||
|
// minidexed.h
|
||||||
|
//
|
||||||
|
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
|
||||||
|
// Copyright (C) 2022 The MiniDexed Team
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#ifndef _ui_h |
||||||
|
#define _ui_h |
||||||
|
|
||||||
|
#define U8X8_USE_PINS 1 |
||||||
|
|
||||||
|
#include <map> |
||||||
|
|
||||||
|
#include "minidexed.h" |
||||||
|
#include "config.h" |
||||||
|
#include <circle/gpiomanager.h> |
||||||
|
|
||||||
|
#include <U8g2lib.h> |
||||||
|
#include <sensor/ky040.h> |
||||||
|
|
||||||
|
class CPaint |
||||||
|
{ |
||||||
|
public: |
||||||
|
CPaint(uint8_t sdi, uint8_t sda, uint8_t reset); |
||||||
|
~CPaint(); |
||||||
|
|
||||||
|
void Initialize(); |
||||||
|
|
||||||
|
uint32_t GetBusClock(); |
||||||
|
void SetBusClock(uint32_t clock_speed); |
||||||
|
|
||||||
|
void SetI2CAddress(uint8_t adr); |
||||||
|
|
||||||
|
void EnableUTF8Print(); |
||||||
|
void DisableUTF8Print(); |
||||||
|
|
||||||
|
unsigned Width(); |
||||||
|
unsigned Height(); |
||||||
|
|
||||||
|
void Clear(); |
||||||
|
|
||||||
|
void SetPowerSave(uint8_t is_enable); |
||||||
|
|
||||||
|
void SetFlipMode(uint8_t mode); |
||||||
|
|
||||||
|
void SetContrast(uint8_t value); |
||||||
|
|
||||||
|
bool Begin(); |
||||||
|
void BeginSimple(); |
||||||
|
|
||||||
|
void SetMaxClipWindow(); |
||||||
|
void SetClipWindow(uint8_t clip_x0, uint8_t clip_y0, uint8_t clip_x1, uint8_t clip_y1); |
||||||
|
|
||||||
|
void SendBuffer(); |
||||||
|
void ClearBuffer(); |
||||||
|
|
||||||
|
void FirstPage(); |
||||||
|
uint8_t NextPage(); |
||||||
|
|
||||||
|
uint8_t* GetBufferPtr(); |
||||||
|
uint8_t GetBufferTileHeight(); |
||||||
|
uint8_t GetBufferTileWidth(); |
||||||
|
uint8_t GetPageCurrTileRow(); |
||||||
|
void SetPageCurrTileRow(uint8_t row); |
||||||
|
uint8_t GetBufferCurrTileRow(); |
||||||
|
void SetBufferCurrTileRow(uint8_t row); |
||||||
|
|
||||||
|
void SetBufferAutoClear(uint8_t mode); |
||||||
|
|
||||||
|
void UpdateDisplayArea(uint8_t tx, uint8_t ty, uint8_t tw, uint8_t th); |
||||||
|
|
||||||
|
void UpdateDisplay(); |
||||||
|
|
||||||
|
void RefreshDisplay(); |
||||||
|
|
||||||
|
void SetDrawColor(uint8_t color_index); |
||||||
|
uint8_t GetDrawColor(); |
||||||
|
void DrawPixel(uint8_t x, uint8_t y); |
||||||
|
void DrawHLine(uint8_t x, uint8_t y, uint8_t w); |
||||||
|
void DrawVLine(uint8_t x, uint8_t y, uint8_t h); |
||||||
|
void DrawHVLine(uint8_t x, uint8_t y, uint8_t len, uint8_t dir); |
||||||
|
|
||||||
|
void DrawFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h); |
||||||
|
void DrawRFrame(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r); |
||||||
|
void DrawBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h); |
||||||
|
void DrawRBox(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t r); |
||||||
|
|
||||||
|
void DrawButtonUTF8(uint8_t x, uint8_t y, uint8_t flags, uint8_t width, uint8_t padding_h, uint8_t padding_v, const char* text); |
||||||
|
|
||||||
|
void DrawCircle(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt = U8G2_DRAW_ALL); |
||||||
|
void DrawDisc(uint8_t x0, uint8_t y0, uint8_t rad, uint8_t opt = U8G2_DRAW_ALL); |
||||||
|
void DrawEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt = U8G2_DRAW_ALL); |
||||||
|
void DrawFilledEllipse(uint8_t x0, uint8_t y0, uint8_t rx, uint8_t ry, uint8_t opt = U8G2_DRAW_ALL); |
||||||
|
|
||||||
|
void DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); |
||||||
|
|
||||||
|
void SetBitmapMode(uint8_t is_transparent); |
||||||
|
void DrawBitmap(uint8_t x, uint8_t y, uint8_t cnt, uint8_t h, const uint8_t* bitmap); |
||||||
|
void DrawXBM(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap); |
||||||
|
void DrawXBMP(uint8_t x, uint8_t y, uint8_t w, uint8_t h, const uint8_t* bitmap); |
||||||
|
|
||||||
|
void DrawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1, int16_t x2, int16_t y2); |
||||||
|
|
||||||
|
void SetFont(const uint8_t* font); |
||||||
|
void SetFontMode(uint8_t is_transparent); |
||||||
|
void SetFontDirection(uint8_t dir); |
||||||
|
|
||||||
|
int8_t GetAscent(); |
||||||
|
int8_t GetDescent(); |
||||||
|
|
||||||
|
void SetFontPosBaseline(); |
||||||
|
void SetFontPosBottom(); |
||||||
|
void SetFontPosTop(); |
||||||
|
void SetFontPosCenter(); |
||||||
|
|
||||||
|
void SetFontRefHeightText(); |
||||||
|
void SetFontRefHeightExtendedText(); |
||||||
|
void SetFontRefHeightAll(); |
||||||
|
|
||||||
|
uint8_t DrawGlyph(uint8_t x, uint8_t y, uint16_t encoding); |
||||||
|
uint8_t DrawStr(uint8_t x, uint8_t y, const char* s); |
||||||
|
uint8_t DrawUTF8(uint8_t x, uint8_t y, const char* s); |
||||||
|
uint8_t DrawExtUTF8(uint8_t x, uint8_t y, uint8_t to_left, const uint16_t *kerning_table, const char* s);
|
||||||
|
|
||||||
|
uint8_t GetStrWidth(const char* s); |
||||||
|
uint8_t GetUTF8Width(const char* s); |
||||||
|
|
||||||
|
uint8_t UISelectionList(const char* title, uint8_t start_pos, const char* sl); |
||||||
|
uint8_t UIMessage(const char* title1, const char* title2, const char* title3, const char* buttons); |
||||||
|
uint8_t UIInputValue(const char* title, const char* pre, uint8_t* value, uint8_t lo, uint8_t hi, uint8_t digits, const char* post); |
||||||
|
|
||||||
|
void LCDHome(); |
||||||
|
void LCDClear(); |
||||||
|
void LCDNoDisplay(); |
||||||
|
void LCDDisplay(); |
||||||
|
void LCDSetCursor(uint8_t x, uint8_t y); |
||||||
|
uint8_t LCDGetCursorX(); |
||||||
|
uint8_t LCDGetCursorY(); |
||||||
|
|
||||||
|
void SleepOn(); |
||||||
|
void SleepOff(); |
||||||
|
void SetColorIndex(uint8_t color_index); |
||||||
|
uint8_t GetColorIndex(); |
||||||
|
int8_t GetFontAscent(); |
||||||
|
int8_t GetFontDescent(); |
||||||
|
int8_t GetMaxCharHeight(); |
||||||
|
int8_t GetMaxCharWidth(); |
||||||
|
|
||||||
|
private: |
||||||
|
U8G2_SH1122_256X64_F_HW_I2C m_display; |
||||||
|
}; |
||||||
|
|
||||||
|
#define NUM_CONTROLS 4 |
||||||
|
|
||||||
|
class CControl |
||||||
|
{ |
||||||
|
public: |
||||||
|
CControl(CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig); |
||||||
|
~CControl(); |
||||||
|
|
||||||
|
bool Initialize(); |
||||||
|
|
||||||
|
CKY040& operator[](size_t index); |
||||||
|
|
||||||
|
private: |
||||||
|
CMiniDexed* m_pMiniDexed; |
||||||
|
CGPIOManager* m_pGPIOManager; |
||||||
|
CConfig* m_pConfig; |
||||||
|
CKY040** m_ppRotaryEncoders; |
||||||
|
}; |
||||||
|
|
||||||
|
class CScreenManager; |
||||||
|
|
||||||
|
class CScreen |
||||||
|
{ |
||||||
|
friend class CScreenManager; |
||||||
|
|
||||||
|
public: |
||||||
|
CScreen(unsigned id, const char* name, unsigned nPages = 1); |
||||||
|
virtual ~CScreen(); |
||||||
|
|
||||||
|
static void Activate(CScreen& nxtScreen); |
||||||
|
void Activate(); |
||||||
|
|
||||||
|
unsigned ScrollLeftPage(); |
||||||
|
unsigned ScrollRightPage(); |
||||||
|
unsigned CurrentScrollPage(); |
||||||
|
unsigned ScrollToPage(unsigned pageNum); |
||||||
|
|
||||||
|
void SetDirty(bool isDirty); |
||||||
|
void Dirty(bool isDirty); |
||||||
|
bool IsDirty(); |
||||||
|
|
||||||
|
void Display(CPaint& paint); |
||||||
|
|
||||||
|
protected: |
||||||
|
virtual void Paint(CPaint& paint) = 0; |
||||||
|
|
||||||
|
private: |
||||||
|
const unsigned m_id; |
||||||
|
const char* m_name; |
||||||
|
const unsigned m_nPages; |
||||||
|
unsigned m_currentScrollPage; |
||||||
|
bool m_isDirty; |
||||||
|
}; |
||||||
|
|
||||||
|
class CScreenManager |
||||||
|
{ |
||||||
|
private: |
||||||
|
std::map<unsigned, CScreen*> m_screenMap; |
||||||
|
|
||||||
|
CScreenManager(); |
||||||
|
|
||||||
|
public: |
||||||
|
static CScreenManager& GetInstance(); |
||||||
|
|
||||||
|
CScreenManager(CScreenManager const&) = delete; |
||||||
|
void operator=(CScreenManager const&) = delete; |
||||||
|
|
||||||
|
~CScreenManager(); |
||||||
|
|
||||||
|
void Register(CScreen* pScreen); |
||||||
|
|
||||||
|
CScreen& operator[](unsigned index); |
||||||
|
|
||||||
|
CScreen& Activate(unsigned screenId); |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1,237 @@ |
|||||||
|
//
|
||||||
|
// userinterface.cpp
|
||||||
|
//
|
||||||
|
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
|
||||||
|
// Copyright (C) 2022 The MiniDexed Team
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#include "userinterfaceext.h" |
||||||
|
#include "minidexed.h" |
||||||
|
#include <circle/logger.h> |
||||||
|
#include <circle/string.h> |
||||||
|
#include <circle/startup.h> |
||||||
|
#include <string.h> |
||||||
|
#include <assert.h> |
||||||
|
|
||||||
|
LOGMODULE ("uiext"); |
||||||
|
|
||||||
|
CUserInterfaceExt::CUserInterfaceExt (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig) |
||||||
|
: m_pMiniDexed (pMiniDexed), |
||||||
|
m_pGPIOManager (pGPIOManager), |
||||||
|
m_pConfig (pConfig), |
||||||
|
m_pLCD (0), |
||||||
|
m_pLCDBuffered (0), |
||||||
|
m_pRotaryEncoder (0), |
||||||
|
m_bSwitchPressed (false), |
||||||
|
m_Menu (this, pMiniDexed) |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
CUserInterfaceExt::~CUserInterfaceExt (void) |
||||||
|
{ |
||||||
|
delete m_pRotaryEncoder; |
||||||
|
delete m_pLCDBuffered; |
||||||
|
delete m_pLCD; |
||||||
|
} |
||||||
|
|
||||||
|
bool CUserInterfaceExt::Initialize (void) |
||||||
|
{ |
||||||
|
assert (m_pConfig); |
||||||
|
|
||||||
|
if (m_pConfig->GetLCDEnabled ()) |
||||||
|
{ |
||||||
|
m_pLCD = new CHD44780Device (CConfig::LCDColumns, CConfig::LCDRows, |
||||||
|
m_pConfig->GetLCDPinData4 (), |
||||||
|
m_pConfig->GetLCDPinData5 (), |
||||||
|
m_pConfig->GetLCDPinData6 (), |
||||||
|
m_pConfig->GetLCDPinData7 (), |
||||||
|
m_pConfig->GetLCDPinEnable (), |
||||||
|
m_pConfig->GetLCDPinRegisterSelect (), |
||||||
|
m_pConfig->GetLCDPinReadWrite ()); |
||||||
|
assert (m_pLCD); |
||||||
|
|
||||||
|
if (!m_pLCD->Initialize ()) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
m_pLCDBuffered = new CWriteBufferDevice (m_pLCD); |
||||||
|
assert (m_pLCDBuffered); |
||||||
|
|
||||||
|
LCDWrite ("\x1B[?25l\x1B""d+"); // cursor off, autopage mode
|
||||||
|
|
||||||
|
LOGDBG ("LCD initialized"); |
||||||
|
} |
||||||
|
|
||||||
|
if (m_pConfig->GetEncoderEnabled ()) |
||||||
|
{ |
||||||
|
m_pRotaryEncoder = new CKY040 (m_pConfig->GetEncoderPinClock (), |
||||||
|
m_pConfig->GetEncoderPinData (), |
||||||
|
m_pConfig->GetEncoderPinSwitch (), |
||||||
|
m_pGPIOManager); |
||||||
|
assert (m_pRotaryEncoder); |
||||||
|
|
||||||
|
if (!m_pRotaryEncoder->Initialize ()) |
||||||
|
{ |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
m_pRotaryEncoder->RegisterEventHandler (EncoderEventStub, this); |
||||||
|
|
||||||
|
LOGDBG ("Rotary encoder initialized"); |
||||||
|
} |
||||||
|
|
||||||
|
m_Menu.EventHandler (CUIMenu::MenuEventUpdate); |
||||||
|
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
void CUserInterfaceExt::Process (void) |
||||||
|
{ |
||||||
|
if (m_pLCDBuffered) |
||||||
|
{ |
||||||
|
m_pLCDBuffered->Update (); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CUserInterfaceExt::ParameterChanged (void) |
||||||
|
{ |
||||||
|
m_Menu.EventHandler (CUIMenu::MenuEventUpdate); |
||||||
|
} |
||||||
|
|
||||||
|
void CUserInterfaceExt::DisplayWrite (const char *pMenu, const char *pParam, const char *pValue, |
||||||
|
bool bArrowDown, bool bArrowUp) |
||||||
|
{ |
||||||
|
assert (pMenu); |
||||||
|
assert (pParam); |
||||||
|
assert (pValue); |
||||||
|
|
||||||
|
CString Msg ("\x1B[H"); // cursor home
|
||||||
|
|
||||||
|
// first line
|
||||||
|
Msg.Append (pParam); |
||||||
|
|
||||||
|
size_t nLen = strlen (pParam) + strlen (pMenu); |
||||||
|
if (nLen < CConfig::LCDColumns) |
||||||
|
{ |
||||||
|
for (unsigned i = CConfig::LCDColumns-nLen; i > 0; i--) |
||||||
|
{ |
||||||
|
Msg.Append (" "); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Msg.Append (pMenu); |
||||||
|
|
||||||
|
// second line
|
||||||
|
CString Value (" "); |
||||||
|
if (bArrowDown) |
||||||
|
{ |
||||||
|
Value = "\x7F"; // arrow left character
|
||||||
|
} |
||||||
|
|
||||||
|
Value.Append (pValue); |
||||||
|
|
||||||
|
if (bArrowUp) |
||||||
|
{ |
||||||
|
if (Value.GetLength () < CConfig::LCDColumns-1) |
||||||
|
{ |
||||||
|
for (unsigned i = CConfig::LCDColumns-Value.GetLength ()-1; i > 0; i--) |
||||||
|
{ |
||||||
|
Value.Append (" "); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Value.Append ("\x7E"); // arrow right character
|
||||||
|
} |
||||||
|
|
||||||
|
Msg.Append (Value); |
||||||
|
|
||||||
|
if (Value.GetLength () < CConfig::LCDColumns) |
||||||
|
{ |
||||||
|
Msg.Append ("\x1B[K"); // clear end of line
|
||||||
|
} |
||||||
|
|
||||||
|
LCDWrite (Msg); |
||||||
|
} |
||||||
|
|
||||||
|
void CUserInterfaceExt::ImmediateLCDWrite (const char *pString) |
||||||
|
{ |
||||||
|
this->LCDWrite(pString); |
||||||
|
this->Process(); |
||||||
|
} |
||||||
|
|
||||||
|
void CUserInterfaceExt::LCDWrite (const char *pString) |
||||||
|
{ |
||||||
|
if (m_pLCDBuffered) |
||||||
|
{ |
||||||
|
m_pLCDBuffered->Write (pString, strlen (pString)); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CUserInterfaceExt::EncoderEventHandler (CKY040::TEvent Event) |
||||||
|
{ |
||||||
|
switch (Event) |
||||||
|
{ |
||||||
|
case CKY040::EventSwitchDown: |
||||||
|
m_bSwitchPressed = true; |
||||||
|
break; |
||||||
|
|
||||||
|
case CKY040::EventSwitchUp: |
||||||
|
m_bSwitchPressed = false; |
||||||
|
break; |
||||||
|
|
||||||
|
case CKY040::EventClockwise: |
||||||
|
m_Menu.EventHandler (m_bSwitchPressed ? CUIMenu::MenuEventPressAndStepUp |
||||||
|
: CUIMenu::MenuEventStepUp); |
||||||
|
break; |
||||||
|
|
||||||
|
case CKY040::EventCounterclockwise: |
||||||
|
m_Menu.EventHandler (m_bSwitchPressed ? CUIMenu::MenuEventPressAndStepDown |
||||||
|
: CUIMenu::MenuEventStepDown); |
||||||
|
break; |
||||||
|
|
||||||
|
case CKY040::EventSwitchClick: |
||||||
|
m_Menu.EventHandler (CUIMenu::MenuEventBack); |
||||||
|
break; |
||||||
|
|
||||||
|
case CKY040::EventSwitchDoubleClick: |
||||||
|
m_Menu.EventHandler (CUIMenu::MenuEventSelect); |
||||||
|
break; |
||||||
|
|
||||||
|
case CKY040::EventSwitchTripleClick: |
||||||
|
m_Menu.EventHandler (CUIMenu::MenuEventHome); |
||||||
|
break; |
||||||
|
|
||||||
|
case CKY040::EventSwitchHold: |
||||||
|
if (m_pRotaryEncoder->GetHoldSeconds () >= 10) |
||||||
|
{ |
||||||
|
delete m_pLCD; // reset LCD
|
||||||
|
|
||||||
|
reboot (); |
||||||
|
} |
||||||
|
break; |
||||||
|
|
||||||
|
default: |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
void CUserInterfaceExt::EncoderEventStub (CKY040::TEvent Event, void *pParam) |
||||||
|
{ |
||||||
|
CUserInterfaceExt *pThis = static_cast<CUserInterfaceExt *> (pParam); |
||||||
|
assert (pThis != 0); |
||||||
|
|
||||||
|
pThis->EncoderEventHandler (Event); |
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
//
|
||||||
|
// userinterface.h
|
||||||
|
//
|
||||||
|
// MiniDexed - Dexed FM synthesizer for bare metal Raspberry Pi
|
||||||
|
// Copyright (C) 2022 The MiniDexed Team
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
#ifndef _userinterface_h |
||||||
|
#define _userinterface_h |
||||||
|
|
||||||
|
#include "config.h" |
||||||
|
#include "uimenu.h" |
||||||
|
#include <sensor/ky040.h> |
||||||
|
#include <display/hd44780device.h> |
||||||
|
#include <circle/gpiomanager.h> |
||||||
|
#include <circle/writebuffer.h> |
||||||
|
|
||||||
|
class CMiniDexed; |
||||||
|
|
||||||
|
class CUserInterfaceExt |
||||||
|
{ |
||||||
|
public: |
||||||
|
CUserInterfaceExt (CMiniDexed *pMiniDexed, CGPIOManager *pGPIOManager, CConfig *pConfig); |
||||||
|
~CUserInterfaceExt (void); |
||||||
|
|
||||||
|
bool Initialize (void); |
||||||
|
|
||||||
|
void Process (void); |
||||||
|
|
||||||
|
void ParameterChanged (void); |
||||||
|
|
||||||
|
// Write to display in this format:
|
||||||
|
// +----------------+
|
||||||
|
// |PARAM MENU|
|
||||||
|
// |[<]VALUE [>]|
|
||||||
|
// +----------------+
|
||||||
|
void DisplayWrite (const char *pMenu, const char *pParam, const char *pValue, |
||||||
|
bool bArrowDown, bool bArrowUp); |
||||||
|
|
||||||
|
void ImmediateLCDWrite (const char *pString); |
||||||
|
|
||||||
|
private: |
||||||
|
void LCDWrite (const char *pString); // Print to optional HD44780 display
|
||||||
|
void EncoderEventHandler (CKY040::TEvent Event); |
||||||
|
static void EncoderEventStub (CKY040::TEvent Event, void *pParam); |
||||||
|
|
||||||
|
private: |
||||||
|
CMiniDexed *m_pMiniDexed; |
||||||
|
CGPIOManager *m_pGPIOManager; |
||||||
|
CConfig *m_pConfig; |
||||||
|
|
||||||
|
CHD44780Device *m_pLCD; |
||||||
|
CWriteBufferDevice *m_pLCDBuffered; |
||||||
|
|
||||||
|
CKY040 *m_pRotaryEncoder; |
||||||
|
bool m_bSwitchPressed; |
||||||
|
|
||||||
|
CUIMenu m_Menu; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif |
@ -0,0 +1 @@ |
|||||||
|
Subproject commit 1ccf4cb051c9fe84d455e3cdcf18267c4f90388f |
Loading…
Reference in new issue