From b409732ddd0dce89178399b53158e6a7f54e3f0e Mon Sep 17 00:00:00 2001 From: George Belmont Date: Fri, 6 Sep 2019 07:13:58 -0400 Subject: [PATCH] Added support for KY-040 rotary encoder to replace browse up/down/select buttons; all code changes were annotated with //ROTARY: for easy review; --- Makefile | 2 +- options.txt | 21 ++++ src/dmRotary.cpp | 285 +++++++++++++++++++++++++++++++++++++++++++++++ src/dmRotary.h | 250 +++++++++++++++++++++++++++++++++++++++++ src/iec_bus.cpp | 59 +++++++++- src/iec_bus.h | 62 +++++++++++ src/main.cpp | 3 + src/options.cpp | 2 + src/options.h | 7 ++ 9 files changed, 687 insertions(+), 4 deletions(-) create mode 100644 src/dmRotary.cpp create mode 100644 src/dmRotary.h diff --git a/Makefile b/Makefile index 72ee0c9..af90028 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ OBJS = armc-start.o armc-cstartup.o armc-cstubs.o armc-cppstubs.o \ exception.o main.o rpi-aux.o rpi-i2c.o rpi-mailbox-interface.o rpi-mailbox.o \ - rpi-gpio.o rpi-interrupts.o cache.o ff.o interrupt.o Keyboard.o performance.o \ + rpi-gpio.o rpi-interrupts.o dmRotary.o cache.o ff.o interrupt.o Keyboard.o performance.o \ Drive.o Pi1541.o DiskImage.o iec_bus.o iec_commands.o m6502.o m6522.o \ gcr.o prot.o lz.o emmc.o diskio.o options.o Screen.o SSD1306.o ScreenLCD.o \ Timer.o FileBrowser.o DiskCaddy.o ROMs.o InputMappings.o xga_font_data.o m8520.o wd177x.o Pi1581.o SpinLock.o diff --git a/options.txt b/options.txt index 607a10f..c06f7f5 100644 --- a/options.txt +++ b/options.txt @@ -107,3 +107,24 @@ GraphIEC = 1 //buttonDown = 3 //buttonBack = 4 //buttonInsert = 5 + +//ROTARY: +// +// KY-040 Rotary Encoder Support +// +// If you would like to use a KY-040 Rotary Encoder for browse menu up/down +// and select, you can enable it here. Connect as follows: +// +// GPIO 22 - Menu up - Encoder pin A (CLK) +// GPIO 23 - Menu down - Encoder pin B (DT) +// GPIO 27 - Enter/Select - Encoder pushbutton (SW) +// +// ** Using an encoder is incompatible with the button remapping. You must +// use the default values of Enter=1, Up=2, Down=3, Back=4 and Insert=5. +// +// ** This has only been tested using a Raspberry Pi 3. Earlier models may +// or may not work as expected! +// +// Please see dmRotary.h for full implementation details. +// +//RotaryEncoderEnable = 1 diff --git a/src/dmRotary.cpp b/src/dmRotary.cpp new file mode 100644 index 0000000..84f066f --- /dev/null +++ b/src/dmRotary.cpp @@ -0,0 +1,285 @@ +/* + * dmRotary.cpp - A simple decoder to use a KY-040 rotary encoder for browse + * naviation in Pi1541. + * + * Copyright © 2019 devMash.com + * + * https://devMash.com + * https://github.com/devMashHub + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the “Software”), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "dmRotary.h" + + +//------------------------------------------------------------------------------ +// Initialize +// +void RotaryEncoder::Initialize(rpi_gpio_pin_t clockGpioPin, rpi_gpio_pin_t dataGpioPin, rpi_gpio_pin_t switchGpioPin) +{ + + #ifdef DM_ROTARY_DEBUG + + char message[1024] = ""; + + WriteToMiniUart("##########\r\n\r\n"); + + WriteToMiniUart("RotaryEncoder::Initialize()\r\n"); + + sprintf(message, " clockGpioPin = %d dataGpioPin = %d switchGpioPin = %d\r\n\r\n", clockGpioPin, dataGpioPin, switchGpioPin); + WriteToMiniUart(message); + + #endif + + //Store specified pins for polling method + _clockPin.SetGpioPin(clockGpioPin); + _dataPin.SetGpioPin(dataGpioPin); + _switchPin.SetGpioPin(switchGpioPin); + + //Set pins for input + RPI_SetGpioInput(clockGpioPin); + RPI_SetGpioInput(dataGpioPin); + RPI_SetGpioInput(switchGpioPin); + + //Enable pull-ups + unsigned controlSignal = 2; + unsigned gpioPinMask = _clockPin.GetGpioPinMask() | _dataPin.GetGpioPinMask() | _switchPin.GetGpioPinMask(); + SetGpioPullUpDown(controlSignal, gpioPinMask); + +} + + +//------------------------------------------------------------------------------ +// Poll +// +rotary_result_t RotaryEncoder::Poll() +{ + + //Read physical pin levels (GPLEV0 is pins 0 to 31) + unsigned gplev0 = read32(ARM_GPIO_GPLEV0); + + return Poll(gplev0); + +} + +//------------------------------------------------------------------------------ +// Poll +// +rotary_result_t RotaryEncoder::Poll(unsigned gplev0) +{ + + rotary_result_t result = NoChange; + + #ifdef DM_ROTARY_DEBUG + + char message[1024] = ""; + + #endif + + //Decode switch + if (result == NoChange) + { + + //Debounce switch and determine state + _switchPin.Update((gplev0 & _switchPin.GetGpioPinMask()) == 0); + bool switchState = _switchPin.GetState(); + + //Detect switch state change + if (switchState != _currentSwitchState) + { + + //Determine result + result = switchState ? ButtonDown : ButtonUp; + + //Update switch state + _currentSwitchState = switchState; + + } + + } + + //Decode rotation + if (result == NoChange) + { + + //Debounce clock and determine state + _clockPin.Update((gplev0 & _clockPin.GetGpioPinMask()) == 0); + bool clockState = _clockPin.GetState(); + + //Debounce data and determine state + _dataPin.Update((gplev0 & _dataPin.GetGpioPinMask()) == 0); + bool dataState = _dataPin.GetState(); + + //Detect rotary state change + int rotaryState = (clockState << 1) | dataState; + if (rotaryState != _currentRotaryState) + { + + //Update rotary sequence + _currentRotarySequence = (_currentRotarySequence << 2) | rotaryState; + + if (rotaryState == 0) + { + + switch (_currentRotarySequence) + { + + //Detect positive (clockwise) rotation + // + // 0xb4 - 00 10 11 01 00 - Received and decoded perfect sequence + // 0x2c - 00 10 11 00 - Missed data but decoded unique sequence + // 0x34 - 00 11 01 00 - Missed data but decoded unique sequence + // 0xb8 - 00 10 11 10 00 - Invalid sequence, using best guess + // + case 0xb4: + case 0x2c: + case 0x34: + case 0xb8: + result = RotatePositive; + break; + + //Detect negative (counter-clockwise) rotation + // + // 0x78 - 00 01 11 10 00 - Received and decoded perfect sequence + // 0x1c - 00 01 11 00 - Missed data but decoded unique sequence + // 0x38 - 00 11 10 00 - Missed data but decoded unique sequence + // 0x74 - 00 01 11 01 00 - Invalid sequence, using best guess + // + case 0x78: + case 0x1c: + case 0x38: + case 0x74: + result = RotateNegative; + break; + + #ifdef DM_ROTARY_DEBUG + + //Unable to decode sequence + // + // 0x0c - 00 11 00 - No way to determine rotation direction + // + default: + if (_currentRotarySequence != 0x0c) + { + sprintf(message, "decode failed: %x\r\n", _currentRotarySequence); + WriteToMiniUart(message); + } + break; + + #endif + + } + + //Clear rotary sequence + _currentRotarySequence = 0; + + } + + //Update rotary state + _currentRotaryState = rotaryState; + + } + + } + + #ifdef DM_ROTARY_DEBUG + + switch (result) + { + + case NoChange: + break; + + case ButtonDown: + WriteToMiniUart("Button Down\r\n"); + break; + + case ButtonUp: + WriteToMiniUart("Button Up\r\n"); + break; + + case RotatePositive: + WriteToMiniUart("Clockwise\r\n"); + break; + + case RotateNegative: + WriteToMiniUart("Counter-Clockwise\r\n"); + break; + + } + + #endif + + return result; + +} + + +//------------------------------------------------------------------------------ +// SetGpioPullUpDown +// +void RotaryEncoder::SetGpioPullUpDown(unsigned controlSignal, unsigned gpioPinMask) +{ + + volatile int i; + int delayCycles = 150; + + // Write to GPPUD to set the required control signal + // + // 01 = Enable Pull-Down 00 = Off (disable pull-up/down) + // 10 = Enable Pull-Up 11 = Reserved + // + write32(ARM_GPIO_GPPUD, controlSignal); + + // Delay cycles (to provide the required set-up time for the control signal) + for (i = 0; i < delayCycles; i++) { } + + // Write to GPPUDCLK0/1 to clock the control signal into the GPIO pads + // + // Note: Only the pads which receive a clock will be modified, all others will + // retain their previous state. + // + write32(ARM_GPIO_GPPUDCLK0, gpioPinMask); + + // Delay cycles (to provide the required hold time for the control signal) + for (i = 0; i < delayCycles; i++) { } + + // Write to GPPUD to remove the control signal + write32(ARM_GPIO_GPPUD, 0); + + //Write to GPPUDCLK0/1 to remove the clock + write32(ARM_GPIO_GPPUDCLK0, 0); + +} + + +#ifdef DM_ROTARY_DEBUG + +//------------------------------------------------------------------------------ +// WriteToMiniUart +// +void RotaryEncoder::WriteToMiniUart(char* pMessage) +{ + while(*pMessage) + { + RPI_AuxMiniUartWrite(*pMessage++); + } +} + +#endif \ No newline at end of file diff --git a/src/dmRotary.h b/src/dmRotary.h new file mode 100644 index 0000000..fee6126 --- /dev/null +++ b/src/dmRotary.h @@ -0,0 +1,250 @@ +/* + * dmRrotary.h - A simple decoder to use a KY-040 rotary encoder for browse + * naviation in Pi1541. + * + * Copyright © 2019 devMash.com + * + * https://devMash.com + * https://github.com/devMashHub + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this + * software and associated documentation files (the “Software”), to deal in the Software + * without restriction, including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#ifndef DM_ROTARY_H +#define DM_ROTARY_H + +extern "C" +{ + #include "rpi-aux.h" + #include "rpiHardware.h" +} + +//Enable debugging messages on the mini uart +//#define DM_ROTARY_DEBUG + + +//------------------------------------------------------------------------------ +// rotary_result_t +// +typedef enum { + NoChange = 0, + ButtonDown = 1, + ButtonUp = 2, + RotatePositive = 3, // clockwise rotation + RotateNegative = 4 // counter-clockwise rotation +} rotary_result_t; + + +//------------------------------------------------------------------------------ +// RotaryPin +// +// NOTES: +// +// This helper class represents a single rotary encoder pin to encapsulate +// debouncing and state engine logic. +// +class RotaryPin +{ + +private: + + rpi_gpio_pin_t _gpioPin = RPI_GPIO0; + + int _count = 0; + int _threshold = 256; // I just like powers of two + + bool _currentState = false; + +public: + + rpi_gpio_pin_t GetGpioPin() const { return _gpioPin; } + void SetGpioPin(rpi_gpio_pin_t value) { _gpioPin = value; } + + unsigned GetGpioPinMask() { return (1 << _gpioPin); } + + bool GetState() const { return _currentState; } + + void Update(bool state) + { + + _count += state ? 1 : -1; + + bool newState = _currentState; + + if (_count <= 0) + { + _count = 0; + newState = false; + } + else if (_count >= _threshold) + { + _count = _threshold; + newState = true; + } + + _currentState = newState; + + } + +}; + + +//------------------------------------------------------------------------------ +// RotaryEncoder +// +// NOTES: +// +// The KY-040 rotary encoder has the following pins: +// +// CLK - Encoder pin A +// DT - Encoder pin B +// SW - Pushbutton switch +// VCC - Supply voltage +// GND - Ground +// +// +// Decoding the KY-040 +// +// Determining which encoder pin changes state first is how the direction +// of rotation is determined. If CLK changes state first, the encoder +// is rotating in a positive (clockwise) direction. If DT changes state +// first, the encoder is rotating in a negative (counter-clockwise) direction. +// +// The entire rotation sequence can be represented as a predictable bit +// pattern by mapping the CLK state in the higher bit and mapping the DT +// state in the lower bit: +// +// Positive rotation - 00 -> 10 -> 11 -> 01 -> 00 (0xb4) +// Negative rotation - 00 -> 01 -> 11 -> 10 -> 00 (0x78) +// +// To decode, we simply monitor the CLK and DT and watch for one of these +// two patterns. +// +// However, in the real world, some pin transitions can be missed due to +// lag during the polling interval or contact bounce - resulting in less +// than perfect decode sequences. To combat against this, the code will +// also accept several permutations that are 'close enough': +// +// Positive (clockwise) rotation: +// +// 0xb4 - 00 10 11 01 00 - Received and decoded perfect sequence +// 0x2c - 00 10 11 00 - Missed data but decoded unique sequence +// 0x34 - 00 11 01 00 - Missed data but decoded unique sequence +// 0xb8 - 00 10 11 10 00 - Invalid but usually denotes positive +// +// Detect negative (counter-clockwise) rotation: +// +// 0x78 - 00 01 11 10 00 - Received and decoded perfect sequence +// 0x1c - 00 01 11 00 - Missed data but decoded unique sequence +// 0x38 - 00 11 10 00 - Missed data but decoded unique sequence +// 0x74 - 00 01 11 01 00 - Invalid but usually denotes negative +// +// +// Wiring the KY-040 +// +// The GPIO pins used for the rotary encoder are specified when initializing +// the class. However, it is probably a good idea to reuse the same pins as +// the original Pi1541 pushbuttons: +// +// GPIO 22 - Menu up - Encoder pin A (CLK) +// GPIO 23 - Menu down - Encoder pin B (DT) +// GPIO 27 - Enter/Select - Encoder pushbutton (SW) +// +// +// USAGE: +// +// *** Please Note! I have only tried this with a Raspberry Pi 3. I have no +// reason to believe this wouldn't also work on an earlier model, but your +// results may vary! +// +// To use the RotaryEncoder, instance the class and initialize with the desired +// GPIO pins like this: +// +// //Initialize using CLK on GPIO22, DT on GPIO32 and SW on GPIO27 +// RotaryEncoder rotaryEncoder; +// rotaryEncoder.Initialize(RPI_GPIO22, RPI_GPIO23, RPI_GPIO27); +// +// Monitor the encoder by calling the Poll() method during your main processing +// loop. The polling logic is constrained by only evaluating GPLEV0, which +// restricts usable pins to GPIO00 through GPIO31. An overloaded version of +// Poll() exists to accept a value representing GPLEV0 without having to +// perform a re-read (providing a small optimization when the current value of +// GPLEV0 is already available). +// +// // Read GPLEV0 and decode the rotary state +// rotary_result_t result = rotaryEncoder.Poll(); +// +// or +// +// // Read GPLEV0 locally and decode the rotary state +// unsigned gplev0 = read32(ARM_GPIO_GPLEV0); +// { some other logic here } +// rotary_result_t result = rotaryEncoder.Poll(gplev0); +// +// Note, the Poll() logic depends on frequent polling of the encoder. Calling +// Poll() as often as possible/permissable will yield better decode results. +// +// Any event detected by the polling logic will be returned as the result +// from the polling method as a rotary_result_t. The controlling logic can +// then take whatever action is appropriate based on the result. +// +// +// HISTORY: +// +// 09/03/2019 - Initial implementation and notes +// 09/04/2019 - Integration into Pi1541 with shim logic to simulate 'original style' button presses +// 09/05/2019 - Code cleanup, improved documentation, options.txt logic, dynamic button indexes +// +class RotaryEncoder { + +private: + + // Switch data + + RotaryPin _switchPin; + + bool _currentSwitchState = false; + + // Rotation data + + RotaryPin _clockPin; + RotaryPin _dataPin; + + int _currentRotaryState = 0; + int _currentRotarySequence = 0; + + // Private methods + + void SetGpioPullUpDown(unsigned controlSignal, unsigned gpioPinMask); + + #ifdef DM_ROTARY_DEBUG + void WriteToMiniUart(char* pMessage); + #endif + +public: + + // Public methods + + void Initialize(rpi_gpio_pin_t clkGpioPin, rpi_gpio_pin_t dtGpioPin, rpi_gpio_pin_t swGpioPin); + + rotary_result_t Poll(); + rotary_result_t Poll(unsigned gplev0); + +}; + +#endif \ No newline at end of file diff --git a/src/iec_bus.cpp b/src/iec_bus.cpp index e77c468..fca5b5a 100644 --- a/src/iec_bus.cpp +++ b/src/iec_bus.cpp @@ -73,15 +73,68 @@ u32 IEC_Bus::emulationModeCheckButtonIndex = 0; unsigned IEC_Bus::gplev0; +//ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... +RotaryEncoder IEC_Bus::rotaryEncoder; +bool IEC_Bus::rotaryEncoderEnable; +//ROTARY: Modified for rotary encoder support - 09/05/2019 by Geo... void IEC_Bus::ReadBrowseMode(void) { gplev0 = read32(ARM_GPIO_GPLEV0); - int index; - for (index = 0; index < buttonCount; ++index) + if (IEC_Bus::rotaryEncoderEnable == true) { - UpdateButton(index, gplev0); + + int indexEnter = 0; + int indexUp = 1; + int indexDown = 2; + int indexBack = 3; + int indexInsert = 4; + + //Poll the rotary encoder + // + // Note: If the rotary encoder returns any value other than 'NoChange' an + // event has been detected. We force the button state of the original + // input button registers to reflect the desired action, and allow the + // original processing logic to do it's work. + // + rotary_result_t rotaryResult = IEC_Bus::rotaryEncoder.Poll(gplev0); + switch (rotaryResult) + { + + case ButtonDown: + SetButtonState(indexEnter, true); + break; + + case RotateNegative: + SetButtonState(indexUp, true); + break; + + case RotatePositive: + SetButtonState(indexDown, true); + break; + + default: + SetButtonState(indexEnter, false); + SetButtonState(indexUp, false); + SetButtonState(indexDown, false); + break; + + } + + UpdateButton(indexBack, gplev0); + UpdateButton(indexInsert, gplev0); + + } + else // Unmolested original logic + { + + int index; + for (index = 0; index < buttonCount; ++index) + { + UpdateButton(index, gplev0); + } + } bool ATNIn = (gplev0 & PIGPIO_MASK_IN_ATN) == (invertIECInputs ? PIGPIO_MASK_IN_ATN : 0); diff --git a/src/iec_bus.h b/src/iec_bus.h index 76f2a98..d2f3b13 100644 --- a/src/iec_bus.h +++ b/src/iec_bus.h @@ -26,6 +26,9 @@ #include "rpi-gpio.h" #include "rpiHardware.h" +//ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... +#include "dmRotary.h" + #define INPUT_BUTTON_DEBOUNCE_THRESHOLD 20000 #define INPUT_BUTTON_REPEAT_THRESHOLD 460000 @@ -308,6 +311,13 @@ public: } RPI_GpioBase->GPPUD = 0; RPI_GpioBase->GPPUDCLK0 = 0; + + //ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... + if (IEC_Bus::rotaryEncoderEnable == true) + { + IEC_Bus::rotaryEncoder.Initialize(RPI_GPIO22, RPI_GPIO23, RPI_GPIO27); + } + } static inline void LetSRQBePulledHigh() @@ -349,6 +359,47 @@ public: } } + + //ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... + // + // Note: This method serves as a shim to allow the rotary encoder + // logic to set a specific input button state (fooling the + // original logic into thinking a button was pressed or + // released). + // + static inline void SetButtonState(int index, bool state) + { + + InputButtonPrev[index] = InputButton[index]; + inputRepeatPrev[index] = inputRepeat[index]; + + if (state == true) + { + + InputButton[index] = true; + validInputCount[index] = INPUT_BUTTON_DEBOUNCE_THRESHOLD; + inputRepeatThreshold[index] = INPUT_BUTTON_DEBOUNCE_THRESHOLD + INPUT_BUTTON_REPEAT_THRESHOLD; + inputRepeat[index]++; + + validInputCount[index] = inputRepeatThreshold[index]; + inputRepeat[index]++; + inputRepeatThreshold[index] += INPUT_BUTTON_REPEAT_THRESHOLD / inputRepeat[index]; + + } + else + { + + InputButton[index] = false; + validInputCount[index] = 0; + inputRepeatThreshold[index] = INPUT_BUTTON_REPEAT_THRESHOLD; + inputRepeat[index] = 0; + inputRepeatPrev[index] = 0; + + } + + } + + static void ReadBrowseMode(void); static void ReadEmulationMode1541(void); static void ReadButtonsEmulationMode(void); @@ -544,6 +595,12 @@ public: ignoreReset = value; } + //ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... + static inline void SetRotaryEncoderEnable(bool value) + { + rotaryEncoderEnable = value; + } + // CA1 input ATN // If CA1 is ever set to output // - CA1 will start to drive pb7 @@ -607,5 +664,10 @@ private: static u32 inputRepeatThreshold[5]; static u32 inputRepeat[5]; static u32 inputRepeatPrev[5]; + + //ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... + static RotaryEncoder rotaryEncoder; + static bool rotaryEncoderEnable; + }; #endif diff --git a/src/main.cpp b/src/main.cpp index c5bcd9b..999b4d7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1763,6 +1763,9 @@ extern "C" IEC_Bus::SetInvertIECOutputs(options.InvertIECOutputs()); IEC_Bus::SetIgnoreReset(options.IgnoreReset()); + //ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... + IEC_Bus::SetRotaryEncoderEnable(options.RotaryEncoderEnable()); + if (!options.SoundOnGPIO()) { dmaSound = (u32*)malloc(Sample_bin_size * 4); diff --git a/src/options.cpp b/src/options.cpp index 27f4fce..43fc279 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -156,6 +156,7 @@ Options::Options(void) , buttonDown(3) , buttonBack(4) , buttonInsert(5) + , rotaryEncoderEnable(0) //ROTARY: { autoMountImageName[0] = 0; @@ -245,6 +246,7 @@ void Options::Process(char* buffer) ELSE_CHECK_DECIMAL_OPTION(buttonDown) ELSE_CHECK_DECIMAL_OPTION(buttonBack) ELSE_CHECK_DECIMAL_OPTION(buttonInsert) + ELSE_CHECK_DECIMAL_OPTION(rotaryEncoderEnable) //ROTARY: else if ((strcasecmp(pOption, "AutoBaseName") == 0)) { strncpy(autoBaseName, pValue, 255); diff --git a/src/options.h b/src/options.h index 0aa41fb..d37ddd9 100644 --- a/src/options.h +++ b/src/options.h @@ -100,6 +100,9 @@ public: inline unsigned int GetButtonBack() const { return buttonBack - 1; } inline unsigned int GetButtonInsert() const { return buttonInsert - 1; } + //ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... + inline unsigned int RotaryEncoderEnable() const { return rotaryEncoderEnable; } + // Page up and down will jump a different amount based on the maximum number rows displayed. // Perhaps we should use some keyboard modifier to the the other screen? inline unsigned int KeyboardBrowseLCDScreen() const { return keyboardBrowseLCDScreen; } @@ -175,5 +178,9 @@ private: char ROMName1581[256]; char newDiskType[32]; + + //ROTARY: Added for rotary encoder support - 09/05/2019 by Geo... + unsigned int rotaryEncoderEnable; + }; #endif