From 555fc67e4af24d702c59ecec125e92ff4383bdc9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 31 Dec 2019 15:21:52 -0800 Subject: [PATCH 001/324] Remove duplicated color definition --- nano_gui.h | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/nano_gui.h b/nano_gui.h index 4ae4719..a66b1b0 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -405,27 +405,4 @@ const GFXfont ubitx_font PROGMEM = { // Approx. 3325 bytes -// Color definitions -#define DISPLAY_BLACK 0x0000 ///< 0, 0, 0 -#define DISPLAY_NAVY 0x000F ///< 0, 0, 123 -#define DISPLAY_DARKGREEN 0x03E0 ///< 0, 125, 0 -#define DISPLAY_DARKCYAN 0x03EF ///< 0, 125, 123 -#define DISPLAY_MAROON 0x7800 ///< 123, 0, 0 -#define DISPLAY_PURPLE 0x780F ///< 123, 0, 123 -#define DISPLAY_OLIVE 0x7BE0 ///< 123, 125, 0 -#define DISPLAY_LIGHTGREY 0xC618 ///< 198, 195, 198 -#define DISPLAY_DARKGREY 0x7BEF ///< 123, 125, 123 -#define DISPLAY_BLUE 0x001F ///< 0, 0, 255 -#define DISPLAY_GREEN 0x07E0 ///< 0, 255, 0 -#define DISPLAY_CYAN 0x07FF ///< 0, 255, 255 -#define DISPLAY_RED 0xF800 ///< 255, 0, 0 -#define DISPLAY_MAGENTA 0xF81F ///< 255, 0, 255 -#define DISPLAY_YELLOW 0xFFE0 ///< 255, 255, 0 -#define DISPLAY_WHITE 0xFFFF ///< 255, 255, 255 -#define DISPLAY_ORANGE 0xFD20 ///< 255, 165, 0 -#define DISPLAY_GREENYELLOW 0xAFE5 ///< 173, 255, 41 -#define DISPLAY_PINK 0xFC18 ///< 255, 130, 198 - #endif // _NANO_GUI_H_ - - From e0a963f9ede1786cb58b280f612b27addf470825 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 31 Dec 2019 17:31:05 -0800 Subject: [PATCH 002/324] PDQ driver is working, but renders a little funny --- PDQ_MinLib/PDQ_FastPin.h | 489 ++++++++++++++ PDQ_MinLib/PDQ_GFX.h | 1369 ++++++++++++++++++++++++++++++++++++++ PDQ_MinLib/PDQ_ILI9341.h | 1064 +++++++++++++++++++++++++++++ PDQ_MinLib/README.md | 51 ++ PDQ_MinLib/gfxfont.h | 29 + PDQ_MinLib/glcdfont.c | 278 ++++++++ glcdfont.c | 6 + nano_font.cpp | 337 ++++++++++ nano_font.h | 9 + nano_gui.cpp | 372 ++--------- nano_gui.h | 353 ---------- 11 files changed, 3673 insertions(+), 684 deletions(-) create mode 100644 PDQ_MinLib/PDQ_FastPin.h create mode 100644 PDQ_MinLib/PDQ_GFX.h create mode 100644 PDQ_MinLib/PDQ_ILI9341.h create mode 100644 PDQ_MinLib/README.md create mode 100644 PDQ_MinLib/gfxfont.h create mode 100644 PDQ_MinLib/glcdfont.c create mode 100644 glcdfont.c create mode 100644 nano_font.cpp create mode 100644 nano_font.h diff --git a/PDQ_MinLib/PDQ_FastPin.h b/PDQ_MinLib/PDQ_FastPin.h new file mode 100644 index 0000000..d96af0f --- /dev/null +++ b/PDQ_MinLib/PDQ_FastPin.h @@ -0,0 +1,489 @@ +// +// This excellent template library is from FastLED http://fastled.io +// +// I was considering writing something similar, but FastPin seemed perfect. +// +// Thanks FastLED people! Here is the license from FastLED followed by the +// header +// + +/* + +The MIT License (MIT) + +Copyright (c) 2013 FastLED + +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 __INC_FASTPIN_H +#define __INC_FASTPIN_H + +#include + +// Arduino.h needed for convinience functions digitalPinToPort/BitMask/portOutputRegister and the pinMode methods. +#include + +#define NO_PIN 255 + +// Class to ensure that a minimum amount of time has kicked since the last time run - and delay if not enough time has passed yet +// this should make sure that chipsets that have +template class CMinWait { + long mLastMicros; +public: + CMinWait() { mLastMicros = 0; } + + void wait() { + long diff = micros() - mLastMicros; + while(diff < WAIT) { + diff = micros() - mLastMicros; + } + } + + void mark() { mLastMicros = micros(); } +}; + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Pin access class - needs to tune for various platforms (naive fallback solution?) +// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +#define _CYCLES(_PIN) (((_PIN >= 62 ) || (_PIN>=42 && _PIN<=49) || (_PIN>=14 && _PIN <=17) || (_PIN>=6 && _PIN <=9)) ? 2 : 1) +#else +#define _CYCLES(_PIN) ((_PIN >= 24) ? 2 : 1) +#endif + +class Selectable { +public: + virtual void select() = 0; + virtual void release() = 0; + virtual bool isSelected() = 0; +}; + +class Pin : public Selectable { + uint8_t mPinMask; + uint8_t mPin; + volatile uint8_t *mPort; + + void _init() { + mPinMask = digitalPinToBitMask(mPin); + mPort = portOutputRegister(digitalPinToPort(mPin)); + } +public: + Pin(int pin) : mPin(pin) { _init(); } + + typedef volatile uint8_t * port_ptr_t; + typedef uint8_t port_t; + + inline void setOutput() { pinMode(mPin, OUTPUT); } + inline void setInput() { pinMode(mPin, INPUT); } + + inline void hi() __attribute__ ((always_inline)) { *mPort |= mPinMask; } + inline void lo() __attribute__ ((always_inline)) { *mPort &= ~mPinMask; } + + inline void strobe() __attribute__ ((always_inline)) { hi(); lo(); } + + inline void hi(register port_ptr_t port) __attribute__ ((always_inline)) { *port |= mPinMask; } + inline void lo(register port_ptr_t port) __attribute__ ((always_inline)) { *port &= ~mPinMask; } + inline void set(register port_t val) __attribute__ ((always_inline)) { *mPort = val; } + + inline void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; } + + port_t hival() __attribute__ ((always_inline)) { return *mPort | mPinMask; } + port_t loval() __attribute__ ((always_inline)) { return *mPort & ~mPinMask; } + port_ptr_t port() __attribute__ ((always_inline)) { return mPort; } + port_t mask() __attribute__ ((always_inline)) { return mPinMask; } + + virtual void select() { hi(); } + virtual void release() { lo(); } + virtual bool isSelected() { return (*mPort & mPinMask) == mPinMask; } +}; + +class OutputPin : public Pin { +public: + OutputPin(int pin) : Pin(pin) { setOutput(); } +}; + +class InputPin : public Pin { +public: + InputPin(int pin) : Pin(pin) { setInput(); } +}; + +/// The simplest level of Pin class. This relies on runtime functions durinig initialization to get the port/pin mask for the pin. Most +/// of the accesses involve references to these static globals that get set up. This won't be the fastest set of pin operations, but it +/// will provide pin level access on pretty much all arduino environments. In addition, it includes some methods to help optimize access in +/// various ways. Namely, the versions of hi, lo, and fastset that take the port register as a passed in register variable (saving a global +/// dereference), since these functions are aggressively inlined, that can help collapse out a lot of extraneous memory loads/dereferences. +/// +/// In addition, if, while writing a bunch of data to a pin, you know no other pins will be getting written to, you can get/cache a value of +/// the pin's port register and use that to do a full set to the register. This results in one being able to simply do a store to the register, +/// vs. the load, and/or, and store that would be done normally. +/// +/// There are platform specific instantiations of this class that provide direct i/o register access to pins for much higher speed pin twiddling. +/// +/// Note that these classes are all static functions. So the proper usage is Pin<13>::hi(); or such. Instantiating objects is not recommended, +/// as passing Pin objects around will likely -not- have the effect you're expecting. +template class FastPin { + static uint8_t sPinMask; + static volatile uint8_t *sPort; + static void _init() { + sPinMask = digitalPinToBitMask(PIN); + sPort = portOutputRegister(digitalPinToPort(PIN)); + } +public: + typedef volatile uint8_t * port_ptr_t; + typedef uint8_t port_t; + + inline static void setOutput() { _init(); pinMode(PIN, OUTPUT); } + inline static void setInput() { _init(); pinMode(PIN, INPUT); } + + inline static void hi() __attribute__ ((always_inline)) { *sPort |= sPinMask; } + inline static void lo() __attribute__ ((always_inline)) { *sPort &= ~sPinMask; } + + inline static void strobe() __attribute__ ((always_inline)) { hi(); lo(); } + + inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { *port |= sPinMask; } + inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { *port &= ~sPinMask; } + inline static void set(register port_t val) __attribute__ ((always_inline)) { *sPort = val; } + + inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; } + + static port_t hival() __attribute__ ((always_inline)) { return *sPort | sPinMask; } + static port_t loval() __attribute__ ((always_inline)) { return *sPort & ~sPinMask; } + static port_ptr_t port() __attribute__ ((always_inline)) { return sPort; } + static port_t mask() __attribute__ ((always_inline)) { return sPinMask; } +}; + +template uint8_t FastPin::sPinMask; +template volatile uint8_t *FastPin::sPort; + +/// Class definition for a Pin where we know the port registers at compile time for said pin. This allows us to make +/// a lot of optimizations, as the inlined hi/lo methods will devolve to a single io register write/bitset. +template class _AVRPIN { +public: + typedef volatile uint8_t * port_ptr_t; + typedef uint8_t port_t; + + inline static void setOutput() { _DDR::r() |= _MASK; } + inline static void setInput() { _DDR::r() &= ~_MASK; } + + inline static void hi() __attribute__ ((always_inline)) { _PORT::r() |= _MASK; } + inline static void lo() __attribute__ ((always_inline)) { _PORT::r() &= ~_MASK; } + inline static void set(register uint8_t val) __attribute__ ((always_inline)) { _PORT::r() = val; } + + inline static void strobe() __attribute__ ((always_inline)) { hi(); lo(); } + + inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); } + inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { lo(); } + inline static void fastset(register port_ptr_t port, register uint8_t val) __attribute__ ((always_inline)) { set(val); } + + inline static port_t hival() __attribute__ ((always_inline)) { return _PORT::r() | _MASK; } + inline static port_t loval() __attribute__ ((always_inline)) { return _PORT::r() & ~_MASK; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_PORT::r(); } + inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; } +}; + +/// Template definition for teensy 3.0 style ARM pins, providing direct access to the various GPIO registers. Note that this +/// uses the full port GPIO registers. In theory, in some way, bit-band register access -should- be faster, however I have found +/// that something about the way gcc does register allocation results in the bit-band code being slower. It will need more fine tuning. +template class _ARMPIN { +public: + typedef volatile uint32_t * port_ptr_t; + typedef uint32_t port_t; + + inline static void setOutput() { pinMode(PIN, OUTPUT); } // TODO: perform MUX config { _PDDR::r() |= _MASK; } + inline static void setInput() { pinMode(PIN, INPUT); } // TODO: preform MUX config { _PDDR::r() &= ~_MASK; } + + inline static void hi() __attribute__ ((always_inline)) { _PSOR::r() = _MASK; } + inline static void lo() __attribute__ ((always_inline)) { _PCOR::r() = _MASK; } + inline static void set(register port_t val) __attribute__ ((always_inline)) { _PDOR::r() = val; } + + inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); } + + inline static void toggle() __attribute__ ((always_inline)) { _PTOR::r() = _MASK; } + + inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { hi(); } + inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { lo(); } + inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; } + + inline static port_t hival() __attribute__ ((always_inline)) { return _PDOR::r() | _MASK; } + inline static port_t loval() __attribute__ ((always_inline)) { return _PDOR::r() & ~_MASK; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return &_PDOR::r(); } + inline static port_t mask() __attribute__ ((always_inline)) { return _MASK; } +}; + +/// Template definition for teensy 3.0 style ARM pins using bit banding, providing direct access to the various GPIO registers. GCC +/// does a poor job of optimizing around these accesses so they are not being used just yet. +template class _ARMPIN_BITBAND { +public: + typedef volatile uint32_t * port_ptr_t; + typedef uint32_t port_t; + + inline static void setOutput() { pinMode(PIN, OUTPUT); } // TODO: perform MUX config { _PDDR::r() |= _MASK; } + inline static void setInput() { pinMode(PIN, INPUT); } // TODO: preform MUX config { _PDDR::r() &= ~_MASK; } + + inline static void hi() __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() = 1; } + inline static void lo() __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() = 0; } + inline static void set(register port_t val) __attribute__ ((always_inline)) { *_PDOR::template rx<_BIT>() = val; } + + inline static void strobe() __attribute__ ((always_inline)) { toggle(); toggle(); } + + inline static void toggle() __attribute__ ((always_inline)) { *_PTOR::template rx<_BIT>() = 1; } + + inline static void hi(register port_ptr_t port) __attribute__ ((always_inline)) { *port = 1; } + inline static void lo(register port_ptr_t port) __attribute__ ((always_inline)) { *port = 0; } + inline static void fastset(register port_ptr_t port, register port_t val) __attribute__ ((always_inline)) { *port = val; } + + inline static port_t hival() __attribute__ ((always_inline)) { return 1; } + inline static port_t loval() __attribute__ ((always_inline)) { return 0; } + inline static port_ptr_t port() __attribute__ ((always_inline)) { return _PDOR::template rx<_BIT>(); } + inline static port_t mask() __attribute__ ((always_inline)) { return 1; } +}; + +/// AVR definitions for pins. Getting around the fact that I can't pass GPIO register addresses in as template arguments by instead creating +/// a custom type for each GPIO register with a single, static, aggressively inlined function that returns that specific GPIO register. A similar +/// trick is used a bit further below for the ARM GPIO registers (of which there are far more than on AVR!) +typedef volatile uint8_t & reg8_t; +#define _R(T) struct __gen_struct_ ## T +#define _RD8(T) struct __gen_struct_ ## T { static inline reg8_t r() { return T; }}; +#define _IO(L) _RD8(DDR ## L); _RD8(PORT ## L); _RD8(PIN ## L); +#define _DEFPIN_AVR(PIN, MASK, L) template<> class FastPin : public _AVRPIN {}; + +// ARM definitions +#define GPIO_BITBAND_ADDR(reg, bit) (((uint32_t)&(reg) - 0x40000000) * 32 + (bit) * 4 + 0x42000000) +#define GPIO_BITBAND_PTR(reg, bit) ((uint32_t *)GPIO_BITBAND_ADDR((reg), (bit))) + +typedef volatile uint32_t & reg32_t; +typedef volatile uint32_t * ptr_reg32_t; + +#define _RD32(T) struct __gen_struct_ ## T { static __attribute__((always_inline)) inline reg32_t r() { return T; } \ + template static __attribute__((always_inline)) inline ptr_reg32_t rx() { return GPIO_BITBAND_PTR(T, BIT); } }; +#define _IO32(L) _RD32(GPIO ## L ## _PDOR); _RD32(GPIO ## L ## _PSOR); _RD32(GPIO ## L ## _PCOR); _RD32(GPIO ## L ## _PTOR); _RD32(GPIO ## L ## _PDIR); _RD32(GPIO ## L ## _PDDR); + +#define _DEFPIN_ARM(PIN, BIT, L) template<> class FastPin : public _ARMPIN {}; + +// Don't use bit band'd pins for now, the compiler generates far less efficient code around them +// #define _DEFPIN_ARM(PIN, BIT, L) template<> class Pin : public _ARMPIN_BITBAND {}; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Pin definitions for AVR and ARM. If there are pin definitions supplied below for the platform being +// built on, then much higher speed access will be possible, namely with direct GPIO register accesses. +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////// +#if defined(FORCE_SOFTWARE_PINS) +#warning "Softwrae pin support forced pin access will be slightly slower. See fastpin.h for info." +#define NO_HARDWARE_PIN_SUPPORT + +#elif defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny45__) +_IO(B); + +_DEFPIN_AVR(0, 0x01, B); _DEFPIN_AVR(1, 0x02, B); _DEFPIN_AVR(2, 0x04, B); _DEFPIN_AVR(3, 0x08, B); +_DEFPIN_AVR(4, 0x10, B); _DEFPIN_AVR(5, 0x20, B); + +#elif(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny25__) +_IO(A); _IO(B); + +_DEFPIN_AVR(0, 0x01, A); _DEFPIN_AVR(1, 0x02, A); _DEFPIN_AVR(2, 0x04, A); _DEFPIN_AVR(3, 0x08, A); +_DEFPIN_AVR(4, 0x10, A); _DEFPIN_AVR(5, 0x20, A); _DEFPIN_AVR(6, 0x40, A); _DEFPIN_AVR(7, 0x80, A); +_DEFPIN_AVR(8, 0x04, B); _DEFPIN_AVR(9, 0x02, B); _DEFPIN_AVR(10, 0x01, B); + +#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) +// Accelerated port definitions for arduino avrs +_IO(D); _IO(B); _IO(C); +_DEFPIN_AVR( 0, 0x01, D); _DEFPIN_AVR( 1, 0x02, D); _DEFPIN_AVR( 2, 0x04, D); _DEFPIN_AVR( 3, 0x08, D); +_DEFPIN_AVR( 4, 0x10, D); _DEFPIN_AVR( 5, 0x20, D); _DEFPIN_AVR( 6, 0x40, D); _DEFPIN_AVR( 7, 0x80, D); +_DEFPIN_AVR( 8, 0x01, B); _DEFPIN_AVR( 9, 0x02, B); _DEFPIN_AVR(10, 0x04, B); _DEFPIN_AVR(11, 0x08, B); +_DEFPIN_AVR(12, 0x10, B); _DEFPIN_AVR(13, 0x20, B); _DEFPIN_AVR(14, 0x01, C); _DEFPIN_AVR(15, 0x02, C); +_DEFPIN_AVR(16, 0x04, C); _DEFPIN_AVR(17, 0x08, C); _DEFPIN_AVR(18, 0x10, C); _DEFPIN_AVR(19, 0x20, C); + +#define SPI_DATA 11 +#define SPI_CLOCK 13 +#define SPI_SELECT 10 +#define AVR_HARDWARE_SPI + +#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) +// megas + +_IO(A); _IO(B); _IO(C); _IO(D); _IO(E); _IO(F); _IO(G); _IO(H); _IO(J); _IO(K); _IO(L); + +_DEFPIN_AVR(0, 1, E); _DEFPIN_AVR(1, 2, E); _DEFPIN_AVR(2, 16, E); _DEFPIN_AVR(3, 32, E); +_DEFPIN_AVR(4, 32, G); _DEFPIN_AVR(5, 8, E); _DEFPIN_AVR(6, 8, H); _DEFPIN_AVR(7, 16, H); +_DEFPIN_AVR(8, 32, H); _DEFPIN_AVR(9, 64, H); _DEFPIN_AVR(10, 16, B); _DEFPIN_AVR(11, 32, B); +_DEFPIN_AVR(12, 64, B); _DEFPIN_AVR(13, 128, B); _DEFPIN_AVR(14, 2, J); _DEFPIN_AVR(15, 1, J); +_DEFPIN_AVR(16, 2, H); _DEFPIN_AVR(17, 1, H); _DEFPIN_AVR(18, 8, D); _DEFPIN_AVR(19, 4, D); +_DEFPIN_AVR(20, 2, D); _DEFPIN_AVR(21, 1, D); _DEFPIN_AVR(22, 1, A); _DEFPIN_AVR(23, 2, A); +_DEFPIN_AVR(24, 4, A); _DEFPIN_AVR(25, 8, A); _DEFPIN_AVR(26, 16, A); _DEFPIN_AVR(27, 32, A); +_DEFPIN_AVR(28, 64, A); _DEFPIN_AVR(29, 128, A); _DEFPIN_AVR(30, 128, C); _DEFPIN_AVR(31, 64, C); +_DEFPIN_AVR(32, 32, C); _DEFPIN_AVR(33, 16, C); _DEFPIN_AVR(34, 8, C); _DEFPIN_AVR(35, 4, C); +_DEFPIN_AVR(36, 2, C); _DEFPIN_AVR(37, 1, C); _DEFPIN_AVR(38, 128, D); _DEFPIN_AVR(39, 4, G); +_DEFPIN_AVR(40, 2, G); _DEFPIN_AVR(41, 1, G); _DEFPIN_AVR(42, 128, L); _DEFPIN_AVR(43, 64, L); +_DEFPIN_AVR(44, 32, L); _DEFPIN_AVR(45, 16, L); _DEFPIN_AVR(46, 8, L); _DEFPIN_AVR(47, 4, L); +_DEFPIN_AVR(48, 2, L); _DEFPIN_AVR(49, 1, L); _DEFPIN_AVR(50, 8, B); _DEFPIN_AVR(51, 4, B); +_DEFPIN_AVR(52, 2, B); _DEFPIN_AVR(53, 1, B); _DEFPIN_AVR(54, 1, F); _DEFPIN_AVR(55, 2, F); +_DEFPIN_AVR(56, 4, F); _DEFPIN_AVR(57, 8, F); _DEFPIN_AVR(58, 16, F); _DEFPIN_AVR(59, 32, F); +_DEFPIN_AVR(60, 64, F); _DEFPIN_AVR(61, 128, F); _DEFPIN_AVR(62, 1, K); _DEFPIN_AVR(63, 2, K); +_DEFPIN_AVR(64, 4, K); _DEFPIN_AVR(65, 8, K); _DEFPIN_AVR(66, 16, K); _DEFPIN_AVR(67, 32, K); +_DEFPIN_AVR(68, 64, K); _DEFPIN_AVR(69, 128, K); + +#define SPI_DATA 51 +#define SPI_CLOCK 52 +#define SPI_SELECT 53 +#define AVR_HARDWARE_SPI + +#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) +// Xark: Add ATMega644,644P,1284 and 1284P (using pinout from http://maniacbug.wordpress.com/2011/11/27/arduino-on-atmega1284p-4/) + +_IO(A); _IO(B); _IO(C); _IO(D); + +_DEFPIN_AVR( 0, (1<<0), B); _DEFPIN_AVR( 1, (1<<1), B); _DEFPIN_AVR( 2, (1<<2), B); _DEFPIN_AVR( 3, (1<<3), B); +_DEFPIN_AVR( 4, (1<<4), B); _DEFPIN_AVR( 5, (1<<5), B); _DEFPIN_AVR( 6, (1<<6), B); _DEFPIN_AVR( 7, (1<<7), B); + +_DEFPIN_AVR( 8, (1<<0), D); _DEFPIN_AVR( 9, (1<<1), D); _DEFPIN_AVR(10, (1<<2), D); _DEFPIN_AVR(11, (1<<3), D); +_DEFPIN_AVR(12, (1<<4), D); _DEFPIN_AVR(13, (1<<5), D); _DEFPIN_AVR(14, (1<<6), D); _DEFPIN_AVR(15, (1<<7), D); + +_DEFPIN_AVR(16, (1<<0), C); _DEFPIN_AVR(17, (1<<1), C); _DEFPIN_AVR(18, (1<<2), C); _DEFPIN_AVR(19, (1<<3), C); +_DEFPIN_AVR(20, (1<<4), C); _DEFPIN_AVR(21, (1<<5), C); _DEFPIN_AVR(22, (1<<6), C); _DEFPIN_AVR(23, (1<<7), C); + +_DEFPIN_AVR(24, (1<<0), A); _DEFPIN_AVR(25, (1<<1), A); _DEFPIN_AVR(26, (1<<2), A); _DEFPIN_AVR(27, (1<<3), A); +_DEFPIN_AVR(28, (1<<4), A); _DEFPIN_AVR(29, (1<<5), A); _DEFPIN_AVR(30, (1<<6), A); _DEFPIN_AVR(31, (1<<7), A); + +#define SPI_DATA 5 +#define SPI_CLOCK 7 +#define SPI_SELECT 4 +#define AVR_HARDWARE_SPI + +// Leonardo, teensy, blinkm +#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) +// Leonardo, teensy, blinkm +#elif defined(__AVR_ATmega32U4__) && defined(CORE_TEENSY) + +// teensy defs +_IO(B); _IO(C); _IO(D); _IO(E); _IO(F); + +_DEFPIN_AVR(0, 1, B); _DEFPIN_AVR(1, 2, B); _DEFPIN_AVR(2, 4, B); _DEFPIN_AVR(3, 8, B); +_DEFPIN_AVR(4, 128, B); _DEFPIN_AVR(5, 1, D); _DEFPIN_AVR(6, 2, D); _DEFPIN_AVR(7, 4, D); +_DEFPIN_AVR(8, 8, D); _DEFPIN_AVR(9, 64, C); _DEFPIN_AVR(10, 128, C); _DEFPIN_AVR(11, 64, D); +_DEFPIN_AVR(12, 128, D); _DEFPIN_AVR(13, 16, B); _DEFPIN_AVR(14, 32, B); _DEFPIN_AVR(15, 64, B); +_DEFPIN_AVR(16, 128, F); _DEFPIN_AVR(17, 64, F); _DEFPIN_AVR(18, 32, F); _DEFPIN_AVR(19, 16, F); +_DEFPIN_AVR(20, 2, F); _DEFPIN_AVR(21, 1, F); _DEFPIN_AVR(22, 16, D); _DEFPIN_AVR(23, 32, D); + +#define SPI_DATA 2 +#define SPI_CLOCK 1 +#define SPI_SELECT 3 +#define AVR_HARDWARE_SPI + +#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) +// teensy++ 2 defs + +_IO(A); _IO(B); _IO(C); _IO(D); _IO(E); _IO(F); + +_DEFPIN_AVR(0, 1, D); _DEFPIN_AVR(1, 2, D); _DEFPIN_AVR(2, 4, D); _DEFPIN_AVR(3, 8, D); +_DEFPIN_AVR(4, 16, D); _DEFPIN_AVR(5, 32, D); _DEFPIN_AVR(6, 64, D); _DEFPIN_AVR(7, 128, D); +_DEFPIN_AVR(8, 1, E); _DEFPIN_AVR(9, 2, E); _DEFPIN_AVR(10, 1, C); _DEFPIN_AVR(11, 2, C); +_DEFPIN_AVR(12, 4, C); _DEFPIN_AVR(13, 8, C); _DEFPIN_AVR(14, 16, C); _DEFPIN_AVR(15, 32, C); +_DEFPIN_AVR(16, 64, C); _DEFPIN_AVR(17, 128, C); _DEFPIN_AVR(18, 64, E); _DEFPIN_AVR(19, 128, E); +_DEFPIN_AVR(20, 1, B); _DEFPIN_AVR(21, 2, B); _DEFPIN_AVR(22, 4, B); _DEFPIN_AVR(23, 8, B); +_DEFPIN_AVR(24, 16, B); _DEFPIN_AVR(25, 32, B); _DEFPIN_AVR(26, 64, B); _DEFPIN_AVR(27, 128, B); +_DEFPIN_AVR(28, 1, A); _DEFPIN_AVR(29, 2, A); _DEFPIN_AVR(30, 4, A); _DEFPIN_AVR(31, 8, A); +_DEFPIN_AVR(32, 16, A); _DEFPIN_AVR(33, 32, A); _DEFPIN_AVR(34, 64, A); _DEFPIN_AVR(35, 128, A); +_DEFPIN_AVR(36, 16, E); _DEFPIN_AVR(37, 32, E); _DEFPIN_AVR(38, 1, F); _DEFPIN_AVR(39, 2, F); +_DEFPIN_AVR(40, 4, F); _DEFPIN_AVR(41, 8, F); _DEFPIN_AVR(42, 16, F); _DEFPIN_AVR(43, 32, F); +_DEFPIN_AVR(44, 64, F); _DEFPIN_AVR(45, 128, F); + +#define SPI_DATA 22 +#define SPI_CLOCK 21 +#define SPI_SELECT 20 +#define AVR_HARDWARE_SPI + +#elif defined(__AVR_ATmega32U4__) + +// leonard defs +_IO(B); _IO(C); _IO(D); _IO(E); _IO(F); + +_DEFPIN_AVR(0, 4, D); _DEFPIN_AVR(1, 8, D); _DEFPIN_AVR(2, 2, D); _DEFPIN_AVR(3, 1, D); +_DEFPIN_AVR(4, 16, D); _DEFPIN_AVR(5, 64, C); _DEFPIN_AVR(6, 128, D); _DEFPIN_AVR(7, 64, E); +_DEFPIN_AVR(8, 16, B); _DEFPIN_AVR(9, 32, B); _DEFPIN_AVR(10, 64, B); _DEFPIN_AVR(11, 128, B); +_DEFPIN_AVR(12, 64, D); _DEFPIN_AVR(13, 128, C); _DEFPIN_AVR(14, 8, B); _DEFPIN_AVR(15, 2, B); +_DEFPIN_AVR(16, 4, B); _DEFPIN_AVR(17, 1, B); _DEFPIN_AVR(18, 128, F); _DEFPIN_AVR(19, 64, F); +_DEFPIN_AVR(20, 32, F); _DEFPIN_AVR(21, 16, F); _DEFPIN_AVR(22, 2, F); _DEFPIN_AVR(23, 0, F); + +#define SPI_DATA 16 +#define SPI_CLOCK 15 +#define AVR_HARDWARE_SPI + +#elif defined(__MK20DX128__) && defined(CORE_TEENSY) + +_IO32(A); _IO32(B); _IO32(C); _IO32(D); _IO32(E); + +_DEFPIN_ARM(0, 16, B); _DEFPIN_ARM(1, 17, B); _DEFPIN_ARM(2, 0, D); _DEFPIN_ARM(3, 12, A); +_DEFPIN_ARM(4, 13, A); _DEFPIN_ARM(5, 7, D); _DEFPIN_ARM(6, 4, D); _DEFPIN_ARM(7, 2, D); +_DEFPIN_ARM(8, 3, D); _DEFPIN_ARM(9, 3, C); _DEFPIN_ARM(10, 4, C); _DEFPIN_ARM(11, 6, C); +_DEFPIN_ARM(12, 7, C); _DEFPIN_ARM(13, 5, C); _DEFPIN_ARM(14, 1, D); _DEFPIN_ARM(15, 0, C); +_DEFPIN_ARM(16, 0, B); _DEFPIN_ARM(17, 1, B); _DEFPIN_ARM(18, 3, B); _DEFPIN_ARM(19, 2, B); +_DEFPIN_ARM(20, 5, D); _DEFPIN_ARM(21, 6, D); _DEFPIN_ARM(22, 1, C); _DEFPIN_ARM(23, 2, C); +_DEFPIN_ARM(24, 5, A); _DEFPIN_ARM(25, 19, B); _DEFPIN_ARM(26, 1, E); _DEFPIN_ARM(27, 9, C); +_DEFPIN_ARM(28, 8, C); _DEFPIN_ARM(29, 10, C); _DEFPIN_ARM(30, 11, C); _DEFPIN_ARM(31, 0, E); +_DEFPIN_ARM(32, 18, B); _DEFPIN_ARM(33, 4, A); + +#define SPI_DATA 11 +#define SPI_CLOCK 13 +#define ARM_HARDWARE_SPI + +#elif defined(__SAM3X8E__) + +DUE_IO32(A); +DUE_IO32(B); +DUE_IO32(C); +DUE_IO32(D); + +_DEFPIN_DUE(0, 8, A); _DEFPIN_DUE(1, 9, A); _DEFPIN_DUE(2, 25, B); _DEFPIN_DUE(3, 28, C); +_DEFPIN_DUE(4, 26, C); _DEFPIN_DUE(5, 25, C); _DEFPIN_DUE(6, 24, C); _DEFPIN_DUE(7, 23, C); +_DEFPIN_DUE(8, 22, C); _DEFPIN_DUE(9, 21, C); _DEFPIN_DUE(10, 29, C); _DEFPIN_DUE(11, 7, D); +_DEFPIN_DUE(12, 8, D); _DEFPIN_DUE(13, 27, B); _DEFPIN_DUE(14, 4, D); _DEFPIN_DUE(15, 5, D); +_DEFPIN_DUE(16, 13, A); _DEFPIN_DUE(17, 12, A); _DEFPIN_DUE(18, 11, A); _DEFPIN_DUE(19, 10, A); +_DEFPIN_DUE(20, 12, B); _DEFPIN_DUE(21, 13, B); _DEFPIN_DUE(22, 26, B); _DEFPIN_DUE(23, 14, A); +_DEFPIN_DUE(24, 15, A); _DEFPIN_DUE(25, 0, D); _DEFPIN_DUE(26, 1, D); _DEFPIN_DUE(27, 2, D); +_DEFPIN_DUE(28, 3, D); _DEFPIN_DUE(29, 6, D); _DEFPIN_DUE(30, 9, D); _DEFPIN_DUE(31, 7, A); +_DEFPIN_DUE(32, 10, D); _DEFPIN_DUE(33, 1, C); _DEFPIN_DUE(34, 2, C); _DEFPIN_DUE(35, 3, C); +_DEFPIN_DUE(36, 4, C); _DEFPIN_DUE(37, 5, C); _DEFPIN_DUE(38, 6, C); _DEFPIN_DUE(39, 7, C); +_DEFPIN_DUE(40, 8, C); _DEFPIN_DUE(41, 9, C); _DEFPIN_DUE(42, 19, A); _DEFPIN_DUE(43, 20, A); +_DEFPIN_DUE(44, 19, C); _DEFPIN_DUE(45, 18, C); _DEFPIN_DUE(46, 17, C); _DEFPIN_DUE(47, 16, C); +_DEFPIN_DUE(48, 15, C); _DEFPIN_DUE(49, 14, C); _DEFPIN_DUE(50, 13, C); _DEFPIN_DUE(51, 12, C); +_DEFPIN_DUE(52, 21, B); _DEFPIN_DUE(53, 14, B); _DEFPIN_DUE(54, 16, A); _DEFPIN_DUE(55, 24, A); +_DEFPIN_DUE(56, 23, A); _DEFPIN_DUE(57, 22, A); _DEFPIN_DUE(58, 6, A); _DEFPIN_DUE(59, 4, A); +_DEFPIN_DUE(60, 3, A); _DEFPIN_DUE(61, 2, A); _DEFPIN_DUE(62, 17, B); _DEFPIN_DUE(63, 18, B); +_DEFPIN_DUE(64, 19, B); _DEFPIN_DUE(65, 20, B); _DEFPIN_DUE(66, 15, B); _DEFPIN_DUE(67, 16, B); +_DEFPIN_DUE(68, 1, A); _DEFPIN_DUE(69, 0, A); _DEFPIN_DUE(70, 17, A); _DEFPIN_DUE(71, 18, A); +_DEFPIN_DUE(72, 30, C); _DEFPIN_DUE(73, 21, A); _DEFPIN_DUE(74, 25, A); _DEFPIN_DUE(75, 26, A); +_DEFPIN_DUE(76, 27, A); _DEFPIN_DUE(77, 28, A); _DEFPIN_DUE(78, 23, B); + +#else + +#warning "No pin/port mappings found, pin access will be slightly slower. See fastpin.h for info." +#define NO_HARDWARE_PIN_SUPPORT + +#endif + +#endif diff --git a/PDQ_MinLib/PDQ_GFX.h b/PDQ_MinLib/PDQ_GFX.h new file mode 100644 index 0000000..5b225ef --- /dev/null +++ b/PDQ_MinLib/PDQ_GFX.h @@ -0,0 +1,1369 @@ +// This is the PDQ re-mixed version of Adafruit's library from Xark +// here is the original copyright notice and license: + +/* +This is the core graphics library for all our displays, providing a common +set of graphics primitives (points, lines, circles, etc.). It needs to be +paired with a hardware-specific library for each display device we carry +(to handle the lower-level functions). + +Adafruit invests time and resources providing this open source code, please +support Adafruit & open-source hardware by purchasing products from Adafruit! + +Copyright (c) 2013 Adafruit Industries. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +// This PDQ optimized version is by Xark +// +// Inspiration from Paul Stoffregen and the Teensy 3.1 community. +// +// GOALS: +// 1) Maintain "sketch" compatibility with original Adafruit libraries. +// 2) Be as much faster as is reasonably possible honoring goal 1. :-) +// 3) Be at least as small as Adafruit libraries. +// +// I believe all three of these have largely been achieved: +// 1) Near full compatibility. Only minor initialization changes in original sketch. +// 2) Between ~2.5 and ~12 times faster (fillRect ~2.5x, drawLine ~12x). +// An average of ~4x faster over entire "graphictest.ino" benchmark. +// +// Even if this library is faster, it was based on the Adafruit original. +// Adafruit deserves your support for making their library open-source (and +// for having some nice LCD modules and all kinds of other great parts too). +// Consider giving them your support if possible! + +#ifndef _PDQ_GFX_H +#define _PDQ_GFX_H + +#include "Arduino.h" +#include "Print.h" + +#ifndef pgm_read_byte + #define pgm_read_byte(addr) (*(const unsigned char *)(addr)) +#endif +#ifndef pgm_read_word + #define pgm_read_word(addr) (*(const unsigned short *)(addr)) +#endif +#ifndef pgm_read_dword + #define pgm_read_dword(addr) (*(const unsigned long *)(addr)) +#endif +#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFFL) + #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr)) +#else + #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) +#endif + +#include "gfxfont.h" + +#define GFX_FONT_PACKED + +typedef int coord_t; // type used for coordinates (signed) for parameters (int16_t used for storage) +typedef uint16_t color_t; // type used for colors (unsigned) + +// swap any type +template +static inline void swapValue(T& x, T& y) +{ + T tmp = x; + x = y; + y = tmp; +} + +// minimum value for any type +template +static inline T minValue(T& x, T& y) +{ + return x < y ? x : y; +} + +// maximum value for any type +template +static inline T maxValue(T& x, T& y) +{ + return x >= y ? x : y; +} + +template +class PDQ_GFX : public Print { + +public: + PDQ_GFX(coord_t w, coord_t h); // Constructor (called by HW driver) + + // Graphic primitives + // drawPixel MUST be defined by the driver subclass (and has no generic fall-back): + + // These are generic versions of routines for drivers that don't provide device-optimized code. + // Drivers are required to have these functions (without "_" postfix), but can fall back to using + // these if needed (they should not be called directly with "_" postfix or it will bypass any + // device-optimized implementations). + static void drawLine_(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color); + static void drawFastVLine_(coord_t x, coord_t y, coord_t h, color_t color); + static void drawFastHLine_(coord_t x, coord_t y, coord_t w, color_t color); + static void fillRect_(coord_t x, coord_t y, coord_t w, coord_t h, color_t color); + static void fillScreen_(color_t color); + + // These are usually overridden in the driver subclass to be useful (but not internally referenced) + static void setRotation(uint8_t r); // only swaps width/height if not supported by driver + static void invertDisplay(boolean i); // only if supported by driver + + // These exist in PDQ_GFX (and generally have no subclass override) + static void drawRect(coord_t x, coord_t y, coord_t w, coord_t h, color_t color); + static void drawCircle(coord_t x0, coord_t y0, coord_t r, color_t color); + static void drawCircleHelper(coord_t x0, coord_t y0, coord_t r, uint8_t cornername, color_t color); + static void fillCircle(coord_t x0, coord_t y0, coord_t r, color_t color); + static void fillCircleHelper(coord_t x0, coord_t y0, coord_t r, uint8_t cornername, coord_t delta, color_t color); + static void drawTriangle(coord_t x0, coord_t y0, coord_t x1, coord_t y1, coord_t x2, coord_t y2, color_t color); + static void fillTriangle(coord_t x0, coord_t y0, coord_t x1, coord_t y1, coord_t x2, coord_t y2, color_t color); + static void drawRoundRect(coord_t x0, coord_t y0, coord_t w, coord_t h, coord_t radius, color_t color); + static void fillRoundRect(coord_t x0, coord_t y0, coord_t w, coord_t h, coord_t radius, color_t color); + static void drawBitmap(coord_t x, coord_t y, const uint8_t *bitmap, coord_t w, coord_t h, color_t color); + static void drawBitmap(coord_t x, coord_t y, const uint8_t *bitmap, coord_t w, coord_t h, color_t color, color_t bg); + static void drawBitmap(coord_t x, coord_t y, uint8_t *bitmap, coord_t w, coord_t h, color_t color); + static void drawBitmap(coord_t x, coord_t y, uint8_t *bitmap, coord_t w, coord_t h, color_t color, color_t bg); + static void drawXBitmap(coord_t x, coord_t y, const uint8_t *bitmap, coord_t w, coord_t h, color_t color); + static void drawChar(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size); + static void drawCharGFX(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size); + static inline void setCursor(coord_t x, coord_t y); + static inline void setTextColor(color_t c); + static inline void setTextColor(color_t c, color_t bg); + static inline void setTextSize(uint8_t s); + static inline void setTextWrap(boolean w); + static inline void cp437(boolean x=true); + static inline void setFont(const GFXfont *f = NULL); + + static inline coord_t width() __attribute__ ((always_inline)) { return _width; } + static inline coord_t height() __attribute__ ((always_inline)) { return _height; } + static inline uint8_t getRotation() __attribute__ ((always_inline)) { return rotation; } + static inline coord_t getCursorX() __attribute__ ((always_inline)) { return cursor_x; } + static inline coord_t getCursorY() __attribute__ ((always_inline)) { return cursor_y; } + static inline void getTextBounds(char *string, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); + static inline void getTextBounds(const __FlashStringHelper *s, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); + + virtual size_t write(uint8_t); // used by Arduino "Print.h" (and the one required virtual function) + +protected: + static GFXfont* gfxFont; + static coord_t WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes + static coord_t _width, _height; // Display w/h as modified by current rotation + static coord_t cursor_x, cursor_y; + static color_t textcolor, textbgcolor; + static uint8_t textsize; + static uint8_t rotation; + static boolean wrap; // If set, 'wrap' text at right edge of display + static boolean _cp437; // If set, use correct CP437 charset (default is off) +}; + + +template +class PDQ_GFX_Button_ +{ +public: + PDQ_GFX_Button_(); + void initButton(PDQ_GFX *gfx, coord_t x, coord_t y, coord_t w, coord_t h, color_t outline, color_t fill, color_t textcolor, const char *label, uint8_t textsize); + void drawButton(boolean inverted = false); + boolean contains(coord_t x, coord_t y); + + void press(boolean p); + boolean isPressed(); + boolean justPressed(); + boolean justReleased(); + +private: + PDQ_GFX *_gfx; + int16_t _x, _y; + int16_t _w, _h; + uint8_t _textsize; + color_t _outlinecolor, _fillcolor, _textcolor; + char _label[10]; + + boolean currstate, laststate; +}; + +// ----------------------------------------------- +extern const unsigned char glcdfont[] PROGMEM; + +template +int16_t PDQ_GFX::WIDTH; // This is the 'raw' display w/h - never changes +template +int16_t PDQ_GFX::HEIGHT; +template +int16_t PDQ_GFX::_width; // Display w/h as modified by current rotation +template +int16_t PDQ_GFX::_height; +template +int16_t PDQ_GFX::cursor_x; +template +int16_t PDQ_GFX::cursor_y; +template +color_t PDQ_GFX::textcolor; +template +color_t PDQ_GFX::textbgcolor; +template +uint8_t PDQ_GFX::textsize; +template +uint8_t PDQ_GFX::rotation; +template +boolean PDQ_GFX::wrap; // If set, 'wrap' text at right edge of display +template +boolean PDQ_GFX::_cp437; // If set, use correct CP437 charset (default is off) +template +GFXfont *PDQ_GFX::gfxFont; + +template +PDQ_GFX::PDQ_GFX(coord_t w, coord_t h) +{ + WIDTH = (int16_t)w; + HEIGHT = (int16_t)h; + _width = (int16_t)w; + _height = (int16_t)h; + cursor_x = 0; + cursor_y = 0; + rotation = 0; + textsize = 1; + textcolor = 0xffff; + textbgcolor = 0xffff; + wrap = true; + _cp437 = false; + gfxFont = NULL; +} + +// Draw a circle outline +template +void PDQ_GFX::drawCircle(coord_t x0, coord_t y0, coord_t r, color_t color) +{ + coord_t f = 1 - r; + coord_t ddF_x = 1; + coord_t ddF_y = -2 * r; + coord_t x = 0; + coord_t y = r; + + HW::drawPixel(x0 , y0+r, color); + HW::drawPixel(x0 , y0-r, color); + HW::drawPixel(x0+r, y0 , color); + HW::drawPixel(x0-r, y0 , color); + + while (x < y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + HW::drawPixel(x0 + x, y0 + y, color); + HW::drawPixel(x0 - x, y0 + y, color); + HW::drawPixel(x0 + x, y0 - y, color); + HW::drawPixel(x0 - x, y0 - y, color); + HW::drawPixel(x0 + y, y0 + x, color); + HW::drawPixel(x0 - y, y0 + x, color); + HW::drawPixel(x0 + y, y0 - x, color); + HW::drawPixel(x0 - y, y0 - x, color); + } +} + +template +void PDQ_GFX::drawCircleHelper( coord_t x0, coord_t y0, coord_t r, uint8_t cornername, color_t color) +{ + coord_t f = 1 - r; + coord_t ddF_x = 1; + coord_t ddF_y = -2 * r; + coord_t x = 0; + coord_t y = r; + + while (x < y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + if (cornername & 0x4) + { + HW::drawPixel(x0 + x, y0 + y, color); + HW::drawPixel(x0 + y, y0 + x, color); + } + if (cornername & 0x2) + { + HW::drawPixel(x0 + x, y0 - y, color); + HW::drawPixel(x0 + y, y0 - x, color); + } + if (cornername & 0x8) + { + HW::drawPixel(x0 - y, y0 + x, color); + HW::drawPixel(x0 - x, y0 + y, color); + } + if (cornername & 0x1) + { + HW::drawPixel(x0 - y, y0 - x, color); + HW::drawPixel(x0 - x, y0 - y, color); + } + } +} + +template +void PDQ_GFX::fillCircle(coord_t x0, coord_t y0, coord_t r, color_t color) +{ + HW::drawFastVLine(x0, y0-r, 2*r+1, color); + fillCircleHelper(x0, y0, r, 3, 0, color); +} + +// Used to do circles and roundrects +template +void PDQ_GFX::fillCircleHelper(coord_t x0, coord_t y0, coord_t r, uint8_t cornername, coord_t delta, color_t color) +{ + coord_t f = 1 - r; + coord_t ddF_x = 1; + coord_t ddF_y = -2 * r; + coord_t x = 0; + coord_t y = r; + + while (x < y) + { + if (f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + + if (cornername & 0x1) + { + HW::drawFastVLine(x0+x, y0-y, 2*y+1+delta, color); + HW::drawFastVLine(x0+y, y0-x, 2*x+1+delta, color); + } + if (cornername & 0x2) + { + HW::drawFastVLine(x0-x, y0-y, 2*y+1+delta, color); + HW::drawFastVLine(x0-y, y0-x, 2*x+1+delta, color); + } + } +} + +// Bresenham's algorithm - thx Wikipedia +template +void PDQ_GFX::drawLine_(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) +{ + int8_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) + { + swapValue(x0, y0); + swapValue(x1, y1); + } + + if (x0 > x1) + { + swapValue(x0, x1); + swapValue(y0, y1); + } + + coord_t dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + coord_t err = dx / 2; + coord_t ystep; + + if (y0 < y1) + { + ystep = 1; + } + else + { + ystep = -1; + } + + for (; x0<=x1; x0++) + { + if (steep) + { + HW::drawPixel(y0, x0, color); + } + else + { + HW::drawPixel(x0, y0, color); + } + err -= dy; + if (err < 0) + { + y0 += ystep; + err += dx; + } + } +} + +// Draw a rectangle +template +void PDQ_GFX::drawRect(coord_t x, coord_t y, coord_t w, coord_t h, color_t color) +{ + HW::drawFastHLine(x , y , w, color); + HW::drawFastHLine(x , y+h-1, w, color); + HW::drawFastVLine(x , y , h, color); + HW::drawFastVLine(x+w-1, y , h, color); +} + +template +void PDQ_GFX::drawFastVLine_(coord_t x, coord_t y, coord_t h, color_t color) +{ + // Used by driver when it has no special support + HW::drawLine(x, y, x, y+h-1, color); +} + +template +void PDQ_GFX::drawFastHLine_(coord_t x, coord_t y, coord_t w, color_t color) +{ + // Used by driver when it has no special support + HW::drawLine(x, y, x+w-1, y, color); +} + +template +void PDQ_GFX::fillRect_(coord_t x, coord_t y, coord_t w, coord_t h, color_t color) +{ + // Used by driver when it has no special support + for (coord_t i=x; i +void PDQ_GFX::fillScreen_(color_t color) +{ + // Used by driver when it has no special support + HW::fillRect(0, 0, _width, _height, color); +} + +// Draw a rounded rectangle +template +void PDQ_GFX::drawRoundRect(coord_t x, coord_t y, coord_t w, coord_t h, coord_t r, color_t color) +{ + // smarter version + HW::drawFastHLine(x+r , y , w-2*r, color); // Top + HW::drawFastHLine(x+r , y+h-1, w-2*r, color); // Bottom + HW::drawFastVLine(x , y+r , h-2*r, color); // Left + HW::drawFastVLine(x+w-1, y+r , h-2*r, color); // Right + // draw four corners + drawCircleHelper(x+r , y+r , r, 1, color); + drawCircleHelper(x+w-r-1, y+r , r, 2, color); + drawCircleHelper(x+w-r-1, y+h-r-1, r, 4, color); + drawCircleHelper(x+r , y+h-r-1, r, 8, color); +} + +// Fill a rounded rectangle +template +void PDQ_GFX::fillRoundRect(coord_t x, coord_t y, coord_t w, coord_t h, coord_t r, color_t color) +{ + // smarter version + HW::fillRect(x+r, y, w-2*r, h, color); + + // draw four corners + fillCircleHelper(x+w-r-1, y+r, r, 1, h-2*r-1, color); + fillCircleHelper(x+r , y+r, r, 2, h-2*r-1, color); +} + +// Draw a triangle +template +void PDQ_GFX::drawTriangle(coord_t x0, coord_t y0, coord_t x1, coord_t y1, coord_t x2, coord_t y2, color_t color) +{ + HW::drawLine(x0, y0, x1, y1, color); + HW::drawLine(x1, y1, x2, y2, color); + HW::drawLine(x2, y2, x0, y0, color); +} + +// Fill a triangle +template +void PDQ_GFX::fillTriangle( coord_t x0, coord_t y0, coord_t x1, coord_t y1, coord_t x2, coord_t y2, color_t color) +{ + coord_t a, b, y, last; + + // Sort coordinates by Y order (y2 >= y1 >= y0) + if (y0 > y1) + { + swapValue(y0, y1); + swapValue(x0, x1); + } + if (y1 > y2) + { + swapValue(y2, y1); + swapValue(x2, x1); + } + if (y0 > y1) + { + swapValue(y0, y1); + swapValue(x0, x1); + } + + if (y0 == y2) // Handle awkward all-on-same-line case as its own thing + { + a = b = x0; + if (x1 < a) + a = x1; + else if (x1 > b) + b = x1; + if (x2 < a) + a = x2; + else if (x2 > b) + b = x2; + HW::drawFastHLine(a, y0, b-a+1, color); + return; + } + + coord_t dx01 = x1 - x0; + coord_t dy01 = y1 - y0; + coord_t dx02 = x2 - x0; + coord_t dy02 = y2 - y0; + coord_t dx12 = x2 - x1; + coord_t dy12 = y2 - y1; + int32_t sa = 0; + int32_t sb = 0; + + // For upper part of triangle, find scanline crossings for segments + // 0-1 and 0-2. If y1=y2 (flat-bottomed triangle), the scanline y1 + // is included here (and second loop will be skipped, avoiding a /0 + // error there), otherwise scanline y1 is skipped here and handled + // in the second loop...which also avoids a /0 error here if y0=y1 + // (flat-topped triangle). + if (y1 == y2) + last = y1; // Include y1 scanline + else + last = y1-1; // Skip it + + for (y = y0; y <= last; y++) + { + a = x0 + sa / dy01; + b = x0 + sb / dy02; + sa += dx01; + sb += dx02; + /* longhand: + a = x0 + (x1 - x0) * (y - y0) / (y1 - y0); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if (a > b) + swapValue(a, b); + HW::drawFastHLine(a, y, b-a+1, color); + } + + // For lower part of triangle, find scanline crossings for segments + // 0-2 and 1-2. This loop is skipped if y1=y2. + sa = dx12 * (y - y1); + sb = dx02 * (y - y0); + for (; y <= y2; y++) + { + a = x1 + sa / dy12; + b = x0 + sb / dy02; + sa += dx12; + sb += dx02; + /* longhand: + a = x1 + (x2 - x1) * (y - y1) / (y2 - y1); + b = x0 + (x2 - x0) * (y - y0) / (y2 - y0); + */ + if (a > b) + swapValue(a, b); + HW::drawFastHLine(a, y, b-a+1, color); + } +} + +// Draw a 1-bit image (bitmap) at the specified (x, y) position from the +// provided bitmap buffer (must be PROGMEM memory) using the specified +// foreground color (unset bits are transparent). +template +void PDQ_GFX::drawBitmap(coord_t x, coord_t y, const uint8_t *bitmap, coord_t w, coord_t h, color_t color) +{ + coord_t i, j, byteWidth = (w + 7) / 8; + uint8_t byte; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if (i % 8 == 0) + byte = pgm_read_byte(bitmap + j * byteWidth + i / 8); + else + byte <<= 1; + + if (byte & 0x80) + HW::drawPixel(x+i, y+j, color); + } + } +} + +// Draw a 1-bit image (bitmap) at the specified (x, y) position from the +// provided bitmap buffer (must be PROGMEM memory) using the specified +// foreground (for set bits) and background (for clear bits) colors. +template +void PDQ_GFX::drawBitmap(coord_t x, coord_t y, const uint8_t *bitmap, coord_t w, coord_t h, color_t color, color_t bg) +{ + coord_t i, j, byteWidth = (w + 7) / 8; + uint8_t byte; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if (i % 8 == 0) + byte = pgm_read_byte(bitmap + j * byteWidth + i / 8); + else + byte <<= 1; + + if (byte & 0x80) + HW::drawPixel(x+i, y+j, color); + else + HW::drawPixel(x+i, y+j, bg); + } + } +} + +// drawBitmap() variant for RAM-resident (not PROGMEM) bitmaps. +template +void PDQ_GFX::drawBitmap(coord_t x, coord_t y, uint8_t *bitmap, coord_t w, coord_t h, color_t color) +{ + coord_t i, j, byteWidth = (w + 7) / 8; + uint8_t byte; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if (i % 8 == 0) + byte = bitmap[j * byteWidth + i / 8]; + else + byte <<= 1; + + if (byte & 0x80) + HW::drawPixel(x+i, y+j, color); + } + } +} + +// drawBitmap() variant w/background for RAM-resident (not PROGMEM) bitmaps. +template +void PDQ_GFX::drawBitmap(coord_t x, coord_t y, uint8_t *bitmap, coord_t w, coord_t h, color_t color, color_t bg) +{ + coord_t i, j, byteWidth = (w + 7) / 8; + uint8_t byte; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if (i % 8 == 0) + byte = bitmap[j * byteWidth + i / 8]; + else + byte <<= 1; + + if (byte & 0x80) + HW::drawPixel(x+i, y+j, color); + else + HW::drawPixel(x+i, y+j, bg); + } + } +} + +// Draw XBitMap Files (*.xbm), exported from GIMP, +// Usage: Export from GIMP to *.xbm, rename *.xbm to *.c and open in editor. +// C Array can be directly used with this function +template +void PDQ_GFX::drawXBitmap(coord_t x, coord_t y, const uint8_t *bitmap, coord_t w, coord_t h, color_t color) +{ + coord_t i, j, byteWidth = (w + 7) / 8; + uint8_t byte; + + for (j = 0; j < h; j++) + { + for (i = 0; i < w; i++) + { + if (i % 8 == 0) + byte = pgm_read_byte(bitmap + j * byteWidth + i / 8); + else + byte >>= 1; + + if (byte & 0x01) + HW::drawPixel(x+i, y+j, color); + } + } +} + +template +size_t PDQ_GFX::write(uint8_t c) +{ + // 'Classic' built-in font + if (!gfxFont) + { + if (c == '\n') + { + cursor_x = 0; + cursor_y += (coord_t)textsize*8; + } + else if (c != '\r') + { + HW::drawChar(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + cursor_x += textsize*6; + if (wrap && (cursor_x > (_width - textsize*6))) + { + cursor_x = 0; + cursor_y += textsize*8; + } + } + } + else + { + if(c == '\n') + { + cursor_x = 0; + cursor_y += (coord_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } + else if (c != '\r') + { + uint8_t first = pgm_read_byte(&gfxFont->first); + if ((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) + { + uint8_t c2 = c - pgm_read_byte(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c2]); + uint8_t w = pgm_read_byte(&glyph->width); + uint8_t h = pgm_read_byte(&glyph->height); + // Is there an associated bitmap? + if ((w > 0) && (h > 0)) + { + coord_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic + if(wrap && ((cursor_x + textsize * (xo + w)) >= _width)) + { + // Drawing character would go off right edge; wrap to new line + cursor_x = 0; + cursor_y += (coord_t)textsize * + (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + } + HW::drawCharGFX(cursor_x, cursor_y, c, textcolor, textbgcolor, textsize); + } + cursor_x += pgm_read_byte(&glyph->xAdvance) * (coord_t)textsize; + } + } + } + return 1; +} + +// Draw a character with built-in font +template +void PDQ_GFX::drawChar(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size) +{ + if ((x >= _width) || + (y >= _height) || + ((x + (6 * size) - 1) < 0) || + ((y + (8 * size) - 1) < 0)) + return; + + uint8_t is_opaque = (bg != color); + + if(!_cp437 && (c >= 176)) // Handle 'classic' charset behavior + c++; + + for (int8_t i=0; i<6; i++) + { + uint8_t line; + + if (i == 5) + line = 0x0; + else + line = pgm_read_byte(glcdfont+(c*5)+i); + + if (size == 1) + { + for (int8_t j = 0; j < 8; j++) + { + if (line & 0x1) + { + HW::drawPixel(x+i, y+j, color); + } + else if (is_opaque) + { + HW::drawPixel(x+i, y+j, bg); + } + line >>= 1; + } + } + else + { + for (int8_t j = 0; j < 8; j++) + { + if (line & 0x1) + { + HW::fillRect(x+(i*size), y+(j*size), size, size, color); + } + else if (is_opaque) + { + HW::fillRect(x+(i*size), y+(j*size), size, size, bg); + } + line >>= 1; + } + } + } +} + +// Draw a character with GFX font +template +void PDQ_GFX::drawCharGFX(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size) +{ + // Character is assumed previously filtered by write() to eliminate + // newlines, returns, non-printable characters, etc. Calling drawChar() + // directly with 'bad' characters of font may cause mayhem! + + c -= pgm_read_byte(&gfxFont->first); + GFXglyph *glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); + uint8_t *bitmap = (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); + + uint16_t bo = pgm_read_word(&glyph->bitmapOffset); + uint8_t w = pgm_read_byte(&glyph->width); + uint8_t h = pgm_read_byte(&glyph->height); + // uint8_t xa = pgm_read_byte(&glyph->xAdvance); + int8_t xo = pgm_read_byte(&glyph->xOffset); + int8_t yo = pgm_read_byte(&glyph->yOffset); + + // Todo: Add character clipping here + + // NOTE: THERE IS NO 'BACKGROUND' COLOR OPTION ON CUSTOM FONTS. + // THIS IS ON PURPOSE AND BY DESIGN. The background color feature + // has typically been used with the 'classic' font to overwrite old + // screen contents with new data. This ONLY works because the + // characters are a uniform size; it's not a sensible thing to do with + // proportionally-spaced fonts with glyphs of varying sizes (and that + // may overlap). To replace previously-drawn text when using a custom + // font, use the getTextBounds() function to determine the smallest + // rectangle encompassing a string, erase the area with fillRect(), + // then draw new text. This WILL infortunately 'blink' the text, but + // is unavoidable. Drawing 'background' pixels will NOT fix this, + // only creates a new set of problems. Have an idea to work around + // this (a canvas object type for MCUs that can afford the RAM and + // displays supporting setAddrWindow() and pushColors()), but haven't + // implemented this yet. + + if (bo & 0x8000) { + // packed font + uint8_t bits_cnt = 0; + uint8_t bits; + uint8_t cnt,cnt2; + bo &= 0x7FFF; + coord_t _y = y+yo; + for (coord_t yy=0; yy= w) + { + cnt2 = w-xx; + } else { + cnt2 = cnt; + } + + if (bits & 0x8) + { + if (size == 1) + { + HW::drawFastHLine(_x, _y, cnt2, color); + _x += cnt2; + } + else + { + HW::fillRect(x+xo+xx*size, y+yo+yy*size, cnt2*size, size, color); + // _x not used if size > 1, so not need to increment it + } + } else { + _x += cnt2; + } + + cnt -= cnt2; + if (cnt == 0) { + bits >>= 4; + cnt = (bits & 0x7)+1; + bits_cnt--; + } + } + } + } else { + uint8_t bit = 0; + uint8_t bits = 0; + if (size == 1) + { + coord_t _y = y+yo; + for (coord_t yy=0; yy +void PDQ_GFX::setCursor(coord_t x, coord_t y) +{ + cursor_x = (int16_t)x; + cursor_y = (int16_t)y; +} + +template +void PDQ_GFX::setTextSize(uint8_t s) +{ + textsize = (s > 0) ? s : 1; +} + +template +void PDQ_GFX::setTextColor(color_t c) +{ + // For 'transparent' background, we'll set the bg + // to the same as fg instead of using a flag + textcolor = c; + textbgcolor = c; +} + +template +void PDQ_GFX::setTextColor(color_t c, color_t b) +{ + textcolor = c; + textbgcolor = b; +} + +template +void PDQ_GFX::setTextWrap(boolean w) +{ + wrap = w; +} + +template +void PDQ_GFX::setRotation(uint8_t x) +{ + // Used by driver when it has no special support + rotation = x & 3; + switch(rotation) { + case 0: + case 2: + _width = WIDTH; + _height = HEIGHT; + break; + case 1: + case 3: + _width = HEIGHT; + _height = WIDTH; + break; + } +} + +template +void PDQ_GFX::cp437(boolean x) +{ + _cp437 = x; +} + +template +void PDQ_GFX::setFont(const GFXfont *f) +{ + if (f) // Font struct pointer passed in? + { + if (!gfxFont) // And no current font struct? + { + // Switching from classic to new font behavior. + // Move cursor pos down 6 pixels so it's on baseline. + cursor_y += 6; + } + } + else if (gfxFont) // NULL passed. Current font struct defined? + { + // Switching from new to classic font behavior. + // Move cursor pos up 6 pixels so it's at top-left of char. + cursor_y -= 6; + } + gfxFont = (GFXfont *)f; +} + +// Pass string and a cursor position, returns UL corner and W,H. +template +void PDQ_GFX::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) +{ + uint8_t c; // Current character + + *x1 = x; + *y1 = y; + *w = *h = 0; + + if (gfxFont) + { + GFXglyph *glyph; + uint8_t first = pgm_read_byte(&gfxFont->first); + uint8_t last = pgm_read_byte(&gfxFont->last); + uint8_t gw, gh, xa; + int8_t xo, yo; + int16_t minx = _width, miny = _height, maxx = -1, maxy = -1; + coord_t gx1, gy1, gx2, gy2; + coord_t ts = (coord_t)textsize, ya = (coord_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + + while((c = *str++)) + { + if (c != '\n') // Not a newline + { + if (c != '\r') // Not a carriage return, is normal char + { + if ((c >= first) && (c <= last)) // Char present in current font + { + c -= first; + glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); + gw = pgm_read_byte(&glyph->width); + gh = pgm_read_byte(&glyph->height); + xa = pgm_read_byte(&glyph->xAdvance); + xo = pgm_read_byte(&glyph->xOffset); + yo = pgm_read_byte(&glyph->yOffset); + if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) // Line wrap + { + x = 0; // Reset x to 0 + y += ya; // Advance y by 1 line + } + gx1 = x + xo * ts; + gy1 = y + yo * ts; + gx2 = gx1 + gw * ts - 1; + gy2 = gy1 + gh * ts - 1; + if (gx1 < minx) + minx = gx1; + if (gy1 < miny) + miny = gy1; + if (gx2 > maxx) + maxx = gx2; + if (gy2 > maxy) + maxy = gy2; + x += xa * ts; + } + } // Carriage return = do nothing + } + else // Newline + { + x = 0; // Reset x + y += ya; // Advance y by 1 line + } + } + // End of string + *x1 = minx; + *y1 = miny; + if (maxx >= minx) + *w = maxx - minx + 1; + if (maxy >= miny) + *h = maxy - miny + 1; + + } + else // Default font + { + uint16_t lineWidth = 0, maxWidth = 0; // Width of current, all lines + + while((c = *str++)) + { + if (c != '\n') // Not a newline + { + if (c != '\r') // Not a carriage return, is normal char + { + lineWidth += textsize * 6; // Includes interchar x gap + if (wrap && (cursor_x > (_width - textsize*6))) + { + x = 0; + y += textsize*8; + + if (lineWidth > maxWidth) // Save widest line + maxWidth = lineWidth; + lineWidth = textsize * 6; // First char on new line + } + } // Carriage return = do nothing + } + else // Newline + { + x = 0; // Reset x to 0 + y += textsize * 8; // Advance y by 1 line + if (lineWidth > maxWidth) // Save widest line + maxWidth = lineWidth; + lineWidth = 0; // Reset lineWidth for new line + } + } + // End of string + if (lineWidth) // Add height of last (or only) line + y += textsize * 8; + *w = maxWidth - 1; // Don't include last interchar x gap + *h = y - *y1; + + } // End classic vs custom font +} + +// Same as above, but for PROGMEM strings +template +void PDQ_GFX::getTextBounds(const __FlashStringHelper *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) +{ + uint8_t *s = (uint8_t *)str; + uint8_t c; + + *x1 = x; + *y1 = y; + *w = *h = 0; + + if (gfxFont) + { + GFXglyph *glyph; + uint8_t first = pgm_read_byte(&gfxFont->first); + uint8_t last = pgm_read_byte(&gfxFont->last); + uint8_t gw, gh, xa; + int8_t xo, yo; + int16_t minx = _width, miny = _height, maxx = -1, maxy = -1; + coord_t gx1, gy1, gx2, gy2; + coord_t ts = (coord_t)textsize; + coord_t ya = ts * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); + + while((c = pgm_read_byte(s++))) + { + if (c != '\n') // Not a newline + { + if (c != '\r') // Not a carriage return, is normal char + { + if ((c >= first) && (c <= last)) // Char present in current font + { + c -= first; + glyph = &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); + gw = pgm_read_byte(&glyph->width); + gh = pgm_read_byte(&glyph->height); + xa = pgm_read_byte(&glyph->xAdvance); + xo = pgm_read_byte(&glyph->xOffset); + yo = pgm_read_byte(&glyph->yOffset); + if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) // Line wrap + { + x = 0; // Reset x to 0 + y += ya; // Advance y by 1 line + } + gx1 = x + xo * ts; + gy1 = y + yo * ts; + gx2 = gx1 + gw * ts - 1; + gy2 = gy1 + gh * ts - 1; + if (gx1 < minx) + minx = gx1; + if (gy1 < miny) + miny = gy1; + if (gx2 > maxx) + maxx = gx2; + if (gy2 > maxy) + maxy = gy2; + x += xa * ts; + } + } // Carriage return = do nothing + } + else // Newline + { + x = 0; // Reset x + y += ya; // Advance y by 1 line + } + } + // End of string + *x1 = minx; + *y1 = miny; + if (maxx >= minx) + *w = maxx - minx + 1; + if (maxy >= miny) + *h = maxy - miny + 1; + + } + else // Default font + { + uint16_t lineWidth = 0, maxWidth = 0; // Width of current, all lines + + while((c = pgm_read_byte(s++))) + { + if (c != '\n') // Not a newline + { + if (c != '\r') // Not a carriage return, is normal char + { + if (wrap && ((x + textsize * 6) >= _width)) + { + x = 0; // Reset x to 0 + y += textsize * 8; // Advance y by 1 line + if (lineWidth > maxWidth) // Save widest line + maxWidth = lineWidth; + lineWidth = textsize * 6; // First char on new line + } + else // No line wrap, just keep incrementing X + { + lineWidth += textsize * 6; // Includes interchar x gap + } + } // Carriage return = do nothing + } + else // Newline + { + x = 0; // Reset x to 0 + y += textsize * 8; // Advance y by 1 line + if (lineWidth > maxWidth) // Save widest line + maxWidth = lineWidth; + lineWidth = 0; // Reset lineWidth for new line + } + } + // End of string + if (lineWidth) // Add height of last (or only) line + y += textsize * 8; + *w = maxWidth - 1; // Don't include last interchar x gap + *h = y - *y1; + + } // End classic vs custom font +} + +template +void PDQ_GFX::invertDisplay(boolean i) +{ + // Used by driver when it has no special support + // Do nothing, must be supported by driver +} + +/***************************************************************************/ +// code for the GFX button UI element + +template +PDQ_GFX_Button_::PDQ_GFX_Button_() +{ + _gfx = 0; +} + +template +void PDQ_GFX_Button_::initButton(PDQ_GFX *gfx, coord_t x, coord_t y, coord_t w, coord_t h, color_t outline, color_t fill, color_t textcolor, const char *label, uint8_t textsize) +{ + _gfx = gfx; + _x = x; + _y = y; + _w = w; + _h = h; + _outlinecolor = outline; + _fillcolor = fill; + _textcolor = textcolor; + _textsize = textsize; + strncpy(_label, label, 9); + _label[9] = 0; +} + +template +void PDQ_GFX_Button_::drawButton(boolean inverted) +{ + uint16_t fill, outline, text; + + if (!inverted) + { + fill = _fillcolor; + outline = _outlinecolor; + text = _textcolor; + } + else + { + fill = _textcolor; + outline = _outlinecolor; + text = _fillcolor; + } + + _gfx->fillRoundRect(_x - (_w/2), _y - (_h/2), _w, _h, min(_w,_h)/4, fill); + _gfx->drawRoundRect(_x - (_w/2), _y - (_h/2), _w, _h, min(_w,_h)/4, outline); + + _gfx->setCursor(_x - strlen(_label)*3*_textsize, _y-4*_textsize); + _gfx->setTextColor(text); + _gfx->setTextSize(_textsize); + _gfx->print(_label); +} + +template +boolean PDQ_GFX_Button_::contains(coord_t x, coord_t y) +{ + if ((x < (_x - _w/2)) || (x > (_x + _w/2))) + return false; + if ((y < (_y - _h/2)) || (y > (_y + _h/2))) + return false; + return true; +} + +template +void PDQ_GFX_Button_::press(boolean p) +{ + laststate = currstate; + currstate = p; +} + +template +boolean PDQ_GFX_Button_::isPressed() +{ + return currstate; +} + +template +boolean PDQ_GFX_Button_::justPressed() +{ + return (currstate && !laststate); +} + +template +boolean PDQ_GFX_Button_::justReleased() +{ + return (!currstate && laststate); +} + +#endif // _PDQ_GFX_H diff --git a/PDQ_MinLib/PDQ_ILI9341.h b/PDQ_MinLib/PDQ_ILI9341.h new file mode 100644 index 0000000..8cc4051 --- /dev/null +++ b/PDQ_MinLib/PDQ_ILI9341.h @@ -0,0 +1,1064 @@ +// This is the PDQ re-mixed version of Adafruit's library +// here is the original copyright notice: + +/*************************************************** + This is an Arduino Library for the Adafruit 2.2" SPI display. + This library works with the Adafruit 2.2" TFT Breakout w/SD card + ----> http://www.adafruit.com/products/1480 + + Check out the links above for our tutorials and wiring diagrams + These displays use SPI to communicate, 4 or 5 pins are required to + interface (RST is optional) + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + MIT license, all text above must be included in any redistribution + ****************************************************/ + +//=============================================================== +// This PDQ optimized version is by Xark +// +// Inspiration from Paul Stoffregen and the Teensy 3.1 community. +// +// GOALS: +// 1) Maintain "sketch" compatibility with original Adafruit libraries. +// 2) Be as much faster as is reasonably possible honoring goal 1. :-) +// 3) Be at least as small as Adafruit libraries. +// +// I believe all three of these have largely been achieved: +// 1) Near full compatibility. Only minor initialization changes in original sketch. +// 2) Between ~2.5 and ~12 times faster (fillRect ~2.5x, drawLine ~12x). +// An average of ~4x faster over entire "graphictest.ino" benchmark. +// +// Even if this library is faster, it was based on the Adafruit original. +// Adafruit deserves your support for making their library open-source (and +// for having some nice LCD modules and all kinds of other great parts too). +// Consider giving them your support if possible! + +#if !defined(_PDQ_ILI9341H_) +#define _PDQ_ILI9341H_ + +#include "Arduino.h" +#include "Print.h" + +#include "PDQ_GFX.h" + +#include + +#if !defined(ILI9341_CS_PIN) || !defined(ILI9341_DC_PIN) +#error Oops! You need to #include "PDQ_ILI9341_config.h" (modified with your pin configuration and options) from your sketch before #include "PDQ_ILI9341.h". +#endif + +#include "PDQ_FastPin.h" + +#if !defined(__AVR_ATtiny85__) && !defined(__AVR_ATtiny45__) +#define INLINE inline +#define INLINE_OPT __attribute__((always_inline)) +#else +#define INLINE +#define INLINE_OPT +#endif + +// Color definitions +enum +{ + ILI9341_BLACK = 0x0000, + ILI9341_BLUE = 0x001F, + ILI9341_RED = 0xF800, + ILI9341_GREEN = 0x07E0, + ILI9341_CYAN = 0x07FF, + ILI9341_MAGENTA = 0xF81F, + ILI9341_YELLOW = 0xFFE0, + ILI9341_WHITE = 0xFFFF, +}; + +class PDQ_ILI9341 : public PDQ_GFX +{ + public: + // ILI9341 commands + // For datasheet see https://www.adafruit.com/products/1480 + enum + { + ILI9341_NOP = 0x00, + ILI9341_SWRESET = 0x01, + ILI9341_RDDID = 0x04, + ILI9341_RDDST = 0x09, + + ILI9341_SLPIN = 0x10, + ILI9341_SLPOUT = 0x11, + ILI9341_PTLON = 0x12, + ILI9341_NORON = 0x13, + + ILI9341_RDMODE = 0x0A, + ILI9341_RDMADCTL = 0x0B, + ILI9341_RDPIXFMT = 0x0C, + ILI9341_RDIMGFMT = 0x0A, + ILI9341_RDSELFDIAG = 0x0F, + + ILI9341_INVOFF = 0x20, + ILI9341_INVON = 0x21, + ILI9341_GAMMASET = 0x26, + ILI9341_DISPOFF = 0x28, + ILI9341_DISPON = 0x29, + + ILI9341_CASET = 0x2A, + ILI9341_PASET = 0x2B, + ILI9341_RAMWR = 0x2C, + ILI9341_RAMRD = 0x2E, + + ILI9341_PTLAR = 0x30, + ILI9341_MADCTL = 0x36, + ILI9341_PIXFMT = 0x3A, + + ILI9341_FRMCTR1 = 0xB1, + ILI9341_FRMCTR2 = 0xB2, + ILI9341_FRMCTR3 = 0xB3, + ILI9341_INVCTR = 0xB4, + ILI9341_DFUNCTR = 0xB6, + + ILI9341_PWCTR1 = 0xC0, + ILI9341_PWCTR2 = 0xC1, + ILI9341_PWCTR3 = 0xC2, + ILI9341_PWCTR4 = 0xC3, + ILI9341_PWCTR5 = 0xC4, + ILI9341_VMCTR1 = 0xC5, + ILI9341_VMCTR2 = 0xC7, + + ILI9341_RDID1 = 0xDA, + ILI9341_RDID2 = 0xDB, + ILI9341_RDID3 = 0xDC, + ILI9341_RDID4 = 0xDD, + + ILI9341_GMCTRP1 = 0xE0, + ILI9341_GMCTRN1 = 0xE1, + + // ILI9341_PWCTR6 = 0xFC, + }; + + // some other misc. constants + enum + { + // screen dimensions + ILI9341_TFTWIDTH = 240, + ILI9341_TFTHEIGHT = 320, + + // MADCTL bits + ILI9341_MADCTL_MH = 0x04, // bit 2 = 0 for refresh left -> right, 1 for refresh right -> left + ILI9341_MADCTL_RGB = 0x00, // bit 3 = 0 for RGB color order + ILI9341_MADCTL_BGR = 0x08, // bit 3 = 1 for BGR color order + ILI9341_MADCTL_ML = 0x10, // bit 4 = 0 for refresh top -> bottom, 1 for bottom -> top + ILI9341_MADCTL_MV = 0x20, // bit 5 = 0 for column, row order (portrait), 1 for row, column order (landscape) + ILI9341_MADCTL_MX = 0x40, // bit 6 = 0 for left -> right, 1 for right -> left order + ILI9341_MADCTL_MY = 0x80, // bit 7 = 0 for top -> bottom, 1 for bottom -> top + + // delay indicator bit for commandList() + DELAY = 0x80 + }; + + // higher-level routines + PDQ_ILI9341(); + static void inline begin(void); + static void setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1); + static void pushColor(uint16_t color); + static void pushColor(uint16_t color, int cnt); + + // Pass 8-bit (each) R,G,B, get back 16-bit packed color + static INLINE uint16_t color565(uint8_t r, uint8_t g, uint8_t b) + { + return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); + } + static INLINE uint16_t Color565(uint8_t r, uint8_t g, uint8_t b) // older inconsistent name for compatibility + { + return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3); + } + + // required driver primitive methods (all except drawPixel can call generic version in PDQ_GFX with "_" postfix). + static void drawPixel(int x, int y, uint16_t color); + static void drawFastVLine(int x, int y, int h, uint16_t color); + static void drawFastHLine(int x, int y, int w, uint16_t color); + static void setRotation(uint8_t r); + static void invertDisplay(boolean i); + + static inline void fillScreen(uint16_t color) __attribute__((always_inline)) + { + fillScreen_(color); // call generic version + } + + static void drawLine(int x0, int y0, int x1, int y1, uint16_t color); + static void fillRect(int x, int y, int w, int h, uint16_t color); + + // === lower-level internal routines ========= + static void commandList(const uint8_t *addr); + + // NOTE: Make sure each spi_begin() is matched with a single spi_end() (and don't call either twice) + // set CS back to low (LCD selected) + static inline void spi_begin() __attribute__((always_inline)) + { +#if ILI9341_SAVE_SPCR && defined(AVR_HARDWARE_SPI) + swapValue(save_SPCR, SPCR); // swap initial/current SPCR settings +#endif + FastPin::lo(); // CS <= LOW (selected) + } + + // NOTE: Make sure each spi_begin() is matched with a single spi_end() (and don't call either twice) + // reset CS back to high (LCD unselected) + static inline void spi_end() __attribute__((always_inline)) + { + FastPin::hi(); // CS <= HIGH (deselected) +#if ILI9341_SAVE_SPCR && defined(AVR_HARDWARE_SPI) + swapValue(SPCR, save_SPCR); // swap current/initial SPCR settings +#endif + } + +#if defined(AVR_HARDWARE_SPI) + // 10 cycle delay (including "call") + static void delay10() __attribute__((noinline)) __attribute__((naked)) + { + __asm__ __volatile__ + ( + // +4 (call to get here) +#if !defined(__AVR_HAVE_RAMPD__) + " adiw r24,0\n" // +2 (2-cycle NOP) +#else + " nop\n" // +1 (1-cycle NOP) +#endif + " ret\n" // +4 (or +5 on >64KB AVR with RAMPD reg) + // = 10 cycles + : : : + ); + } + + // 13 cycle delay (including "call") + static void delay13() __attribute__((noinline)) __attribute__((naked)) + { + __asm__ __volatile__ + ( + // +4 (call to get here) + " adiw r24,0\n" // +2 (2-cycle NOP) + " adiw r24,0\n" // +2 (2-cycle NOP) +#if !defined(__AVR_HAVE_RAMPD__) + " nop\n" // +1 (1-cycle NOP) +#endif + " ret\n" // +4 (or +5 on >64KB AVR with RAMPD reg) + // = 13 cycles + : : : + ); + } + + // 15 cycle delay (including "call") + static void delay15() __attribute__((noinline)) __attribute__((naked)) + { + __asm__ __volatile__ + ( + // +4 (call to get here) + " adiw r24,0\n" // +2 (2-cycle NOP) + " adiw r24,0\n" // +2 (2-cycle NOP) + " adiw r24,0\n" // +2 (2-cycle NOP) +#if !defined(__AVR_HAVE_RAMPD__) + " nop\n" // +1 (1-cycle NOP) +#endif + " ret\n" // +4 (or +5 on >64KB AVR with RAMPD reg) + // = 15 cycles + : : : + ); + } + + // 17 cycle delay (including "call") + static void delay17() __attribute__((noinline)) __attribute__((naked)) + { + __asm__ __volatile__ + ( + // +4 (call to get here) + " adiw r24,0\n" // +2 (2-cycle NOP) + " adiw r24,0\n" // +2 (2-cycle NOP) + " adiw r24,0\n" // +2 (2-cycle NOP) + " adiw r24,0\n" // +2 (2-cycle NOP) +#if !defined(__AVR_HAVE_RAMPD__) + " nop\n" // +1 (2-cycle NOP) +#endif + " ret\n" // +4 (or +5 on >64KB AVR with RAMPD reg) + // = 17 cycles + : : : + ); + } + + // normal SPI write with minimal hand-tuned delay (assuming max DIV2 SPI rate) + static INLINE void spiWrite(uint8_t data) INLINE_OPT + { + SPDR = data; + __asm__ __volatile__ + ( + " call _ZN11PDQ_ILI93417delay17Ev\n" // call mangled delay17 (compiler would needlessly save/restore regs) + : : : + ); + } + + // special SPI write with minimal hand-tuned delay (assuming max DIV2 SPI rate) - minus 2 cycles for RS (etc.) change + static INLINE void spiWrite_preCmd(uint8_t data) INLINE_OPT + { + SPDR = data; + + __asm__ __volatile__ + ( + " call _ZN11PDQ_ILI93417delay15Ev\n" // call mangled delay15 (compiler would needlessly save/restore regs) + : : : + ); + } + + // SPI 16-bit write with minimal hand-tuned delay (assuming max DIV2 SPI rate) + static INLINE void spiWrite16(uint16_t data) INLINE_OPT + { + uint8_t temp; + __asm__ __volatile__ + ( + " out %[spi],%[hi]\n" // write SPI data (18 cycles until next write) + " call _ZN11PDQ_ILI93417delay17Ev\n" // call mangled delay17 (compiler would needlessly save/restore regs) + " out %[spi],%[lo]\n" // write SPI data (18 cycles until next write) + " call _ZN11PDQ_ILI93417delay17Ev\n" // call mangled delay17 (compiler would needlessly save/restore regs) + + : [temp] "=d" (temp) + : [spi] "i" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)data), [hi] "r" ((uint8_t)(data>>8)) + : + ); + } + + // SPI 16-bit write with minimal hand-tuned delay (assuming max DIV2 SPI rate) minus 2 cycles + static INLINE void spiWrite16_preCmd(uint16_t data) INLINE_OPT + { + uint8_t temp; + __asm__ __volatile__ + ( + " out %[spi],%[hi]\n" // write SPI data (18 cycles until next write) + " call _ZN11PDQ_ILI93417delay17Ev\n" // call mangled delay17 (compiler would needlessly save/restore regs) + " out %[spi],%[lo]\n" // write SPI data (18 cycles until next write) + " call _ZN11PDQ_ILI93417delay15Ev\n" // call mangled delay15 (compiler would needlessly save/restore regs) + + : [temp] "=d" (temp) + : [spi] "i" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)data), [hi] "r" ((uint8_t)(data>>8)) + : + ); + } + + // SPI 16-bit write with minimal hand-tuned delay (assuming max DIV2 SPI rate) minus 4 cycles + static INLINE void spiWrite16_lineDraw(uint16_t data) INLINE_OPT + { + uint8_t temp; + __asm__ __volatile__ + ( + " out %[spi],%[hi]\n" // write SPI data (18 cycles until next write) + " call _ZN11PDQ_ILI93417delay17Ev\n" // call mangled delay17 (compiler would needlessly save/restore regs) + " out %[spi],%[lo]\n" // write SPI data (18 cycles until next write) + + : [temp] "=d" (temp) + : [spi] "i" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)data), [hi] "r" ((uint8_t)(data>>8)) + : + ); + } + + // normal SPI write with minimal hand-tuned delay (assuming max DIV2 SPI rate) + static INLINE void spiWrite16(uint16_t data, int count) INLINE_OPT + { + uint8_t temp; + __asm__ __volatile__ + ( + " sbiw %[count],0\n" // test count + " brmi 4f\n" // if < 0 then done + " breq 4f\n" // if == 0 then done + "1: out %[spi],%[hi]\n" // write SPI data (18 cycles until next write) + " call _ZN11PDQ_ILI93417delay17Ev\n" // call mangled delay17 (compiler would needlessly save/restore regs) + " out %[spi],%[lo]\n" // write SPI data (18 cycles until next write) + " call _ZN11PDQ_ILI93417delay13Ev\n" // call mangled delay13 (compiler would needlessly save/restore regs) + " sbiw %[count],1\n" // +2 decrement count + " brne 1b\n" // +2/1 if != 0 then loop + // = 13 + 2 + 2 (17 cycles) + "4:\n" + + : [temp] "=d" (temp), [count] "+w" (count) + : [spi] "i" (_SFR_IO_ADDR(SPDR)), [lo] "r" ((uint8_t)data), [hi] "r" ((uint8_t)(data>>8)) + : + ); + } + +#else // bit-bang +#if defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny45__) + // USI hardware assisted + static void spiWrite(uint8_t data) __attribute__((noinline)) + { + USIDR = data; + __asm__ __volatile__ + ( + " out %[spi],%[clkp0]\n" // MSB + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" // LSB + " out %[spi],%[clkp1]\n" + : + : [spi] "i" (_SFR_IO_ADDR(USICR)), [clkp0] "a" ((uint8_t)((1<>8; + __asm__ __volatile__ + ( + " out %[spi],%[clkp0]\n" // MSB + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" + " out %[spi],%[clkp1]\n" + " out %[spi],%[clkp0]\n" // LSB + " out %[spi],%[clkp1]\n" + : + : [spi] "i" (_SFR_IO_ADDR(USICR)), [clkp0] "a" ((uint8_t)((1<>= 1) + { + if (data & bit) + FastPin::hi(); + else + FastPin::lo(); + + FastPin::hi(); + FastPin::lo(); + } + } + static void spiWrite16(uint16_t data) __attribute__((noinline)) + { + spiWrite(data >> 8); + spiWrite(data & 0xff); + } +#endif + static INLINE void spiWrite_preCmd(uint8_t data) INLINE_OPT + { + spiWrite(data); + } + static INLINE void spiWrite16_preCmd(uint16_t data) INLINE_OPT + { + spiWrite16(data); + } + static INLINE void spiWrite16_lineDraw(uint16_t data) INLINE_OPT + { + spiWrite16(data); + } + static INLINE void spiWrite16(uint16_t data, int count) INLINE_OPT + { + while (count-- > 0) + spiWrite16(data); + } + static inline void delay10() { } + static inline void delay13() { } + static inline void delay15() { } + static inline void delay17() { } +#endif + + // write SPI byte with RS (aka D/C) pin set low to indicate a command byte (and then reset back to high when done) + static INLINE void writeCommand(uint8_t data) INLINE_OPT + { + FastPin::lo(); // RS <= LOW indicate command byte + spiWrite_preCmd(data); + FastPin::hi(); // RS <= HIGH indicate data byte (always assumed left in data mode) + } + + // write SPI byte with RS assumed low indicating a data byte + static inline void writeData(uint8_t data) __attribute__((always_inline)) + { + spiWrite(data); + } + + // internal version that does not spi_begin()/spi_end() + static INLINE void setAddrWindow_(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) INLINE_OPT + { + writeCommand(ILI9341_CASET); // column address set + spiWrite16(x0); // XSTART + spiWrite16_preCmd(x1); // XEND + writeCommand(ILI9341_PASET); // row address set + spiWrite16(y0); // YSTART + spiWrite16_preCmd(y1); // YEND + writeCommand(ILI9341_RAMWR); // write to RAM + } + +#if ILI9341_SAVE_SPCR && defined(AVR_HARDWARE_SPI) + static volatile uint8_t save_SPCR; // initial SPCR value/saved SPCR value (swapped in spi_begin/spi_end) +#endif +}; + +typedef PDQ_GFX_Button_ PDQ_GFX_Button; + +/*************************************************** + This is an Arduino Library for the Adafruit 2.2" SPI display. + This library works with the Adafruit 2.2" TFT Breakout w/SD card + ----> http://www.adafruit.com/products/1480 + + Check out the links above for our tutorials and wiring diagrams + These displays use SPI to communicate, 4 or 5 pins are required to + interface (RST is optional) + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Written by Limor Fried/Ladyada for Adafruit Industries. + MIT license, all text above must be included in any redistribution + ****************************************************/ + +#if ILI9341_SAVE_SPCR && defined(AVR_HARDWARE_SPI) +// static data needed by base class +volatile uint8_t PDQ_ILI9341::save_SPCR; +#endif + +// Constructor when using hardware SPI. +PDQ_ILI9341::PDQ_ILI9341() : PDQ_GFX(ILI9341_TFTWIDTH, ILI9341_TFTHEIGHT) +{ +#if defined(AVR_HARDWARE_SPI) + // must reference these functions from C++ or they will be stripped by linker (called from inline asm) + delay10(); + delay13(); + delay15(); + delay17(); +#endif +} + +// Companion code to the above tables. Reads and issues +// a series of LCD commands stored in PROGMEM byte array. +void PDQ_ILI9341::commandList(const uint8_t *addr) +{ + uint8_t numCommands, numArgs; + uint16_t ms; + + numCommands = pgm_read_byte(addr++); // Number of commands to follow + while (numCommands--) // For each command... + { + writeCommand(pgm_read_byte(addr++)); // Read, issue command + numArgs = pgm_read_byte(addr++); // Number of args to follow + ms = numArgs & DELAY; // If hibit set, delay follows args + numArgs &= ~DELAY; // Mask out delay bit + while (numArgs--) // For each argument... + { + writeData(pgm_read_byte(addr++)); // Read, issue argument + } + + if (ms) + { + ms = pgm_read_byte(addr++); // Read post-command delay time (ms) + if(ms == 255) + ms = 500; // If 255, delay for 500 ms + delay(ms); + } + } +} + +void PDQ_ILI9341::begin(void) +{ + + // set CS and RS pin directions to output + FastPin::setOutput(); + FastPin::setOutput(); +#if !defined(AVR_HARDWARE_SPI) + #if defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) + USICR = (0<::setInput(); + #endif + FastPin::setOutput(); + FastPin::setOutput(); + FastPin::lo(); + FastPin::lo(); +#endif + + FastPin::hi(); // CS <= HIGH (deselected, so no spurious data) + FastPin::hi(); // RS <= HIGH (default data byte) + +#if defined(AVR_HARDWARE_SPI) + #if ILI9341_SAVE_SPCR + uint8_t oldSPCR = SPCR; // save initial SPCR settings + #endif + SPI.begin(); + SPI.setBitOrder(MSBFIRST); + SPI.setDataMode(SPI_MODE0); + SPI.setClockDivider(SPI_CLOCK_DIV2); // 8 MHz (full! speed!) [1 byte every 18 cycles] +#endif + +#if ILI9341_SAVE_SPCR && defined(AVR_HARDWARE_SPI) + save_SPCR = SPCR; // save SPCR settings + SPCR = oldSPCR; // restore previous SPCR settings (spi_begin/spi_end will switch between the two) +#endif + spi_begin(); + + // Initialization commands for ILI9341 screens + static const uint8_t ILI9341_cmds[] PROGMEM = + { + 22, + ILI9341_SWRESET, DELAY, // 1 + 5, + 0xEF, 3, // 2 + 0x03, 0x80, 0x02, + 0xCF, 3, // 3 + 0x00, 0xC1, 0x30, + 0xED, 4, // 4 + 0x64, 0x03, 0x12, 0x81, + 0xE8, 3, // 5 + 0x85, 0x00, 0x78, + 0xCB, 5, // 6 + 0x39, 0x2C, 0x00, 0x34, 0x02, + 0xF7, 1, // 7 + 0x20, + 0xEA, 2, // 8 + 0x00, 0x00, + ILI9341_PWCTR1, 1, // 9 power control + 0x23, // VRH[5:0] + ILI9341_PWCTR2, 1, // 10 power control + 0x10, // SAP[2:0];BT[3:0] + ILI9341_VMCTR1, 2, // 11 VCM control + 0x3e, 0x28, + ILI9341_VMCTR2, 1, // 12 VCM control2 + 0x86, // -- + ILI9341_MADCTL, 1, // 13 + (ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR), + ILI9341_PIXFMT, 1, // 14 + 0x55, + ILI9341_FRMCTR1, 2, // 15 + 0x00, 0x18, + ILI9341_DFUNCTR, 3, // 16 + 0x08, 0x82, 0x27, + 0xF2, 1, // 17 3Gamma Function Disable + 0x00, + ILI9341_GAMMASET, 1, // 18 Gamma curve selected + 0x01, + ILI9341_GMCTRP1, 15, // 19 Set Gamma + 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, + ILI9341_GMCTRN1, 15, // 20 + 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, + ILI9341_SLPOUT, DELAY, // 21 + 120, + ILI9341_DISPON, 0, // 22 + }; + + commandList(ILI9341_cmds); + + spi_end(); +} + +void PDQ_ILI9341::setAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) +{ + spi_begin(); + + setAddrWindow_(x0, y0, x1, y1); + + spi_end(); +} + +void PDQ_ILI9341::pushColor(uint16_t color) +{ + spi_begin(); + + spiWrite16_preCmd(color); + + spi_end(); +} + +void PDQ_ILI9341::pushColor(uint16_t color, int count) +{ + spi_begin(); + + spiWrite16(color, count); + + spi_end(); +} + +void PDQ_ILI9341::drawPixel(int x, int y, uint16_t color) +{ + if ((x < 0) ||(x >= _width) || (y < 0) || (y >= _height)) + return; + + spi_begin(); + + setAddrWindow_(x, y, x, y); + + spiWrite16_preCmd(color); + + spi_end(); +} + +void PDQ_ILI9341::drawFastVLine(int x, int y, int h, uint16_t color) +{ + // clipping + if ((x < 0) || (x >= _width) || (y >= _height)) + return; + + if (y < 0) + { + h += y; + y = 0; + } + + int y1 = y+h; + + if (y1 < 0) + return; + + if (y1 > _height) + h = _height-y; + + spi_begin(); + + setAddrWindow_(x, y, x, _height); + spiWrite16(color, h); + + spi_end(); +} + + +void PDQ_ILI9341::drawFastHLine(int x, int y, int w, uint16_t color) +{ + // clipping + if ((x >= _width) || (y < 0) || (y >= _height)) + return; + + if (x < 0) + { + w += x; + x = 0; + } + + int x1 = x+w; + + if (x1 < 0) + return; + + if (x1 > _width) + w = _width-w; + + spi_begin(); + + setAddrWindow_(x, y, _width, y); + spiWrite16(color, w); + + spi_end(); +} + +void PDQ_ILI9341::fillRect(int x, int y, int w, int h, uint16_t color) +{ + // rudimentary clipping (drawChar w/big text requires this) + if ((x >= _width) || (y >= _height)) + return; + if (x < 0) + { + w += x; + x = 0; + } + if (y < 0) + { + h += y; + y = 0; + } + if ((x + w) > _width) + w = _width - x; + if ((y + h) > _height) + h = _height - y; + + spi_begin(); + + setAddrWindow_(x, y, x+w-1, _height); + + for (; h > 0; h--) + { + spiWrite16(color, w); + } + + spi_end(); +} + +// Bresenham's algorithm - thx Wikipedia +void PDQ_ILI9341::drawLine(int x0, int y0, int x1, int y1, uint16_t color) +{ +#if 0 && defined(__AVR_ATtiny85__) || defined(__AVR_ATtiny45__) + drawLine_(x0, y0, x1, y1, color); +#else + int8_t steep = abs(y1 - y0) > abs(x1 - x0); + if (steep) + { + swapValue(x0, y0); + swapValue(x1, y1); + } + + if (x0 > x1) + { + swapValue(x0, x1); + swapValue(y0, y1); + } + + if (x1 < 0) + return; + + int dx, dy; + dx = x1 - x0; + dy = abs(y1 - y0); + + int err = dx / 2; + int8_t ystep; + + if (y0 < y1) + { + ystep = 1; + } + else + { + ystep = -1; + } + + uint8_t setaddr = 1; + +#if 0 && defined(__AVR_ATtiny85__) && !defined(__AVR_ATtiny45__) + int end = steep ? _height-1 : _width-1; + if (x1 > end) + x1 = end; + + for (; x0 <= x1; x0++) + { + if ((x0 >= 0) && (y0 >= 0) && (y0 <= end)) + break; + + err -= dy; + if (err < 0) + { + err += dx; + y0 += ystep; + } + } + + if (x0 > x1) + return; + + spi_begin(); + + for (; x0 <= x1; x0++) + { + if (setaddr) + { + if (steep) + setAddrWindow_(y0, x0, y0, end+1); + else + setAddrWindow_(x0, y0, end+1, y0); + setaddr = 0; + } + spiWrite16_lineDraw(color); + err -= dy; + if (err < 0) + { + y0 += ystep; + if ((y0 < 0) || (y0 > end)) + break; + err += dx; + setaddr = 1; + } + } +#else + if (steep) // y increments every iteration (y0 is x-axis, and x0 is y-axis) + { + if (x1 >= _height) + x1 = _height - 1; + + for (; x0 <= x1; x0++) + { + if ((x0 >= 0) && (y0 >= 0) && (y0 < _width)) + break; + + err -= dy; + if (err < 0) + { + err += dx; + y0 += ystep; + } + } + + if (x0 > x1) + return; + + spi_begin(); + + for (; x0 <= x1; x0++) + { + if (setaddr) + { + setAddrWindow_(y0, x0, y0, _height); + setaddr = 0; + } + spiWrite16_lineDraw(color); + err -= dy; + if (err < 0) + { + y0 += ystep; + if ((y0 < 0) || (y0 >= _width)) + break; + err += dx; + setaddr = 1; + } +#if defined(AVR_HARDWARE_SPI) + else + { + __asm__ __volatile__ + ( + " call _ZN11PDQ_ILI93417delay10Ev\n" + : : : + ); + } +#endif + } + } + else // x increments every iteration (x0 is x-axis, and y0 is y-axis) + { + if (x1 >= _width) + x1 = _width - 1; + + for (; x0 <= x1; x0++) + { + if ((x0 >= 0) && (y0 >= 0) && (y0 < _height)) + break; + + err -= dy; + if (err < 0) + { + err += dx; + y0 += ystep; + } + } + + if (x0 > x1) + return; + + spi_begin(); + + for (; x0 <= x1; x0++) + { + if (setaddr) + { + setAddrWindow_(x0, y0, _width, y0); + setaddr = 0; + } + spiWrite16_lineDraw(color); + err -= dy; + if (err < 0) + { + y0 += ystep; + if ((y0 < 0) || (y0 >= _height)) + break; + err += dx; + setaddr = 1; + } +#if defined(AVR_HARDWARE_SPI) + else + { + __asm__ __volatile__ + ( + " call _ZN11PDQ_ILI93417delay10Ev\n" + : : : + ); + } +#endif + } + } +#endif + + spi_end(); +#endif +} + +void PDQ_ILI9341::setRotation(uint8_t m) +{ + rotation = (m & 3); // can't be higher than 3 + + spi_begin(); + + writeCommand(ILI9341_MADCTL); + + switch (rotation) + { + default: + case 0: + writeData(ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR); + _width = ILI9341_TFTWIDTH; + _height = ILI9341_TFTHEIGHT; + break; + case 1: + writeData(ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR); + _width = ILI9341_TFTHEIGHT; + _height = ILI9341_TFTWIDTH; + break; + case 2: + writeData(ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR); + _width = ILI9341_TFTWIDTH; + _height = ILI9341_TFTHEIGHT; + break; + case 3: + writeData(ILI9341_MADCTL_MV | ILI9341_MADCTL_MY | ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR); + _width = ILI9341_TFTHEIGHT; + _height = ILI9341_TFTWIDTH; + break; + } + + spi_end(); +} + +void PDQ_ILI9341::invertDisplay(boolean i) +{ + spi_begin(); + + writeCommand(i ? ILI9341_INVON : ILI9341_INVOFF); + + spi_end(); +} + +#endif // !defined(_PDQ_ILI9341H_) diff --git a/PDQ_MinLib/README.md b/PDQ_MinLib/README.md new file mode 100644 index 0000000..48bd2e5 --- /dev/null +++ b/PDQ_MinLib/README.md @@ -0,0 +1,51 @@ +PDQ_GFX_Libs with packed font support +============ +Version with special "packed" font support. Also include TTF2GFX for create custom GFX fonts from TTF. +Speed up improvement for GFX text drawing about 2-3 times. +Allow to create custom fonts with subset of chars (not all ASCII table). +Special "packing" algorithm for GFX font allow to save 20-50% of space + +PDQ_GFX_Libs +============ + +An optimized fork of Adafruit's GFX library (and LCD drivers) for Arduino (AVR). + +This is a replacement "re-mix" of the Adafruit GFX library and associated hardware drivers. + +Currently supported are ILI9340, ILI9341, ST7735 and ST7781 LCD drivers (and compatible chipsets). + +It is between 2.5x and 12x faster than the Adafruit libraries for SPI LCDs, but it aims to be completely "sketch compatible" (so you +can easily speed up your sketches that are using Adafruit's library). You just need to change the name of the #include and "tft" +object. A version of the Adafruit "benchmark" example is included (PDQ_graphicsbest.ino) with each driver library. + +This includes the 1.8", 2.2" and 2.8" SPI TFT LCD boards or "touch shields" that are commonly available from Adafruit and +many other vendors. These are commonly 128x128, 128x160 or 240x320 (but the library supports rotation). + +I would also like to thank the excellent http://fastled.io/ project for creating the "FastPin.h" template header that allows +for full speed GPIO while allowing the use of "friendly" Arduino pin numbering (it is included in the PDQ driver libraries). + +New features in latest commit ("v1.1.5" 2016-04-09) include: + + * Synced core functions with Adafruit_GFX (few changes - I think their clipping is still broken [fixed in PDQ_GFX]) + * Support for new fonts as seen in Adafruit_GFX GitHub + * Minor bugfixes + +New features in latest commit ("v1.0.0" 2015-05-30) include: + + * Arduino IDE 1.6.x support (mainly information in library.properties, but also tested and 100% warning free). + * New ATtiny85 support for IL934x using USI SPI (not quite as fast as 328P - but can run 20MHz PLL to make up). + * New support for parallel ST7781 driver as used in Seeed Studio 2.8" Touch Shield (also sold by Radio Shack). This is the fastest LCD supported currently. + * "Bit-banged" SPI support. Not as fast, but can use (nearly) any pins. + * Added pushColor with a count that can speed up application rendering runs of same color. + * Tidied up files and made sure all drivers were updated with latest tweaks. + +Suggestions, issues, bugs and comments welcome. Via https://hackaday.io/Xark or visit #Arduino channel on Freenode.net IRC. +I have also posted a write-up about the development of this library at http://hackaday.io/Xark (describes most of the optimizations done). + + +Issues +------ + +Currently, the library may only be used from the INO file in your project. You _cannot_ include it in a header file and +use it from other CPP files. The current workaround is to write wrapper functions or classes, declare them in a header +file, and then implement them in the INO file. \ No newline at end of file diff --git a/PDQ_MinLib/gfxfont.h b/PDQ_MinLib/gfxfont.h new file mode 100644 index 0000000..78f3a47 --- /dev/null +++ b/PDQ_MinLib/gfxfont.h @@ -0,0 +1,29 @@ +// This is the PDQ re-mixed version of Adafruit's library from Xark +// here is the original copyright notice and license: + +// Font structures for newer Adafruit_GFX (1.1 and later). +// Example fonts are included in 'Fonts' directory. +// To use a font in your Arduino sketch, #include the corresponding .h +// file and pass address of GFXfont struct to setFont(). Pass NULL to +// revert to 'classic' fixed-space bitmap font. + +#ifndef _GFXFONT_H_ +#define _GFXFONT_H_ + +struct GFXglyph // Data stored PER GLYPH +{ + uint16_t bitmapOffset; // Pointer into GFXfont->bitmap + uint8_t width, height; // Bitmap dimensions in pixels + uint8_t xAdvance; // Distance to advance cursor (x axis) + int8_t xOffset, yOffset; // Dist from cursor pos to UL corner +}; + +struct GFXfont // Data stored for FONT AS A WHOLE: +{ + uint8_t *bitmap; // Glyph bitmaps, concatenated + GFXglyph *glyph; // Glyph array + uint8_t first, last; // ASCII extents + uint8_t yAdvance; // Newline distance (y axis) +}; + +#endif // _GFXFONT_H_ diff --git a/PDQ_MinLib/glcdfont.c b/PDQ_MinLib/glcdfont.c new file mode 100644 index 0000000..7231f92 --- /dev/null +++ b/PDQ_MinLib/glcdfont.c @@ -0,0 +1,278 @@ +// This is the 'classic' fixed-space bitmap font for Adafruit_GFX since 1.0. +// See gfxfont.h for newer custom bitmap font info. + +#ifndef FONT5X7_H +#define FONT5X7_H + +#ifdef __AVR__ + #include + #include +#elif defined(ESP8266) + #include +#else + #define PROGMEM +#endif + +// Standard ASCII 5x7 font + +const unsigned char glcdfont[] PROGMEM = + { + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, + 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, + 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, + 0x18, 0x3C, 0x7E, 0x3C, 0x18, + 0x1C, 0x57, 0x7D, 0x57, 0x1C, + 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, + 0x00, 0x18, 0x3C, 0x18, 0x00, + 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, + 0x00, 0x18, 0x24, 0x18, 0x00, + 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, + 0x30, 0x48, 0x3A, 0x06, 0x0E, + 0x26, 0x29, 0x79, 0x29, 0x26, + 0x40, 0x7F, 0x05, 0x05, 0x07, + 0x40, 0x7F, 0x05, 0x25, 0x3F, + 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, + 0x7F, 0x3E, 0x1C, 0x1C, 0x08, + 0x08, 0x1C, 0x1C, 0x3E, 0x7F, + 0x14, 0x22, 0x7F, 0x22, 0x14, + 0x5F, 0x5F, 0x00, 0x5F, 0x5F, + 0x06, 0x09, 0x7F, 0x01, 0x7F, + 0x00, 0x66, 0x89, 0x95, 0x6A, + 0x60, 0x60, 0x60, 0x60, 0x60, + 0x94, 0xA2, 0xFF, 0xA2, 0x94, + 0x08, 0x04, 0x7E, 0x04, 0x08, + 0x10, 0x20, 0x7E, 0x20, 0x10, + 0x08, 0x08, 0x2A, 0x1C, 0x08, + 0x08, 0x1C, 0x2A, 0x08, 0x08, + 0x1E, 0x10, 0x10, 0x10, 0x10, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, + 0x30, 0x38, 0x3E, 0x38, 0x30, + 0x06, 0x0E, 0x3E, 0x0E, 0x06, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x5F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x07, 0x00, + 0x14, 0x7F, 0x14, 0x7F, 0x14, + 0x24, 0x2A, 0x7F, 0x2A, 0x12, + 0x23, 0x13, 0x08, 0x64, 0x62, + 0x36, 0x49, 0x56, 0x20, 0x50, + 0x00, 0x08, 0x07, 0x03, 0x00, + 0x00, 0x1C, 0x22, 0x41, 0x00, + 0x00, 0x41, 0x22, 0x1C, 0x00, + 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, + 0x08, 0x08, 0x3E, 0x08, 0x08, + 0x00, 0x80, 0x70, 0x30, 0x00, + 0x08, 0x08, 0x08, 0x08, 0x08, + 0x00, 0x00, 0x60, 0x60, 0x00, + 0x20, 0x10, 0x08, 0x04, 0x02, + 0x3E, 0x51, 0x49, 0x45, 0x3E, + 0x00, 0x42, 0x7F, 0x40, 0x00, + 0x72, 0x49, 0x49, 0x49, 0x46, + 0x21, 0x41, 0x49, 0x4D, 0x33, + 0x18, 0x14, 0x12, 0x7F, 0x10, + 0x27, 0x45, 0x45, 0x45, 0x39, + 0x3C, 0x4A, 0x49, 0x49, 0x31, + 0x41, 0x21, 0x11, 0x09, 0x07, + 0x36, 0x49, 0x49, 0x49, 0x36, + 0x46, 0x49, 0x49, 0x29, 0x1E, + 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x40, 0x34, 0x00, 0x00, + 0x00, 0x08, 0x14, 0x22, 0x41, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x00, 0x41, 0x22, 0x14, 0x08, + 0x02, 0x01, 0x59, 0x09, 0x06, + 0x3E, 0x41, 0x5D, 0x59, 0x4E, + 0x7C, 0x12, 0x11, 0x12, 0x7C, + 0x7F, 0x49, 0x49, 0x49, 0x36, + 0x3E, 0x41, 0x41, 0x41, 0x22, + 0x7F, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x49, 0x49, 0x49, 0x41, + 0x7F, 0x09, 0x09, 0x09, 0x01, + 0x3E, 0x41, 0x41, 0x51, 0x73, + 0x7F, 0x08, 0x08, 0x08, 0x7F, + 0x00, 0x41, 0x7F, 0x41, 0x00, + 0x20, 0x40, 0x41, 0x3F, 0x01, + 0x7F, 0x08, 0x14, 0x22, 0x41, + 0x7F, 0x40, 0x40, 0x40, 0x40, + 0x7F, 0x02, 0x1C, 0x02, 0x7F, + 0x7F, 0x04, 0x08, 0x10, 0x7F, + 0x3E, 0x41, 0x41, 0x41, 0x3E, + 0x7F, 0x09, 0x09, 0x09, 0x06, + 0x3E, 0x41, 0x51, 0x21, 0x5E, + 0x7F, 0x09, 0x19, 0x29, 0x46, + 0x26, 0x49, 0x49, 0x49, 0x32, + 0x03, 0x01, 0x7F, 0x01, 0x03, + 0x3F, 0x40, 0x40, 0x40, 0x3F, + 0x1F, 0x20, 0x40, 0x20, 0x1F, + 0x3F, 0x40, 0x38, 0x40, 0x3F, + 0x63, 0x14, 0x08, 0x14, 0x63, + 0x03, 0x04, 0x78, 0x04, 0x03, + 0x61, 0x59, 0x49, 0x4D, 0x43, + 0x00, 0x7F, 0x41, 0x41, 0x41, + 0x02, 0x04, 0x08, 0x10, 0x20, + 0x00, 0x41, 0x41, 0x41, 0x7F, + 0x04, 0x02, 0x01, 0x02, 0x04, + 0x40, 0x40, 0x40, 0x40, 0x40, + 0x00, 0x03, 0x07, 0x08, 0x00, + 0x20, 0x54, 0x54, 0x78, 0x40, + 0x7F, 0x28, 0x44, 0x44, 0x38, + 0x38, 0x44, 0x44, 0x44, 0x28, + 0x38, 0x44, 0x44, 0x28, 0x7F, + 0x38, 0x54, 0x54, 0x54, 0x18, + 0x00, 0x08, 0x7E, 0x09, 0x02, + 0x18, 0xA4, 0xA4, 0x9C, 0x78, + 0x7F, 0x08, 0x04, 0x04, 0x78, + 0x00, 0x44, 0x7D, 0x40, 0x00, + 0x20, 0x40, 0x40, 0x3D, 0x00, + 0x7F, 0x10, 0x28, 0x44, 0x00, + 0x00, 0x41, 0x7F, 0x40, 0x00, + 0x7C, 0x04, 0x78, 0x04, 0x78, + 0x7C, 0x08, 0x04, 0x04, 0x78, + 0x38, 0x44, 0x44, 0x44, 0x38, + 0xFC, 0x18, 0x24, 0x24, 0x18, + 0x18, 0x24, 0x24, 0x18, 0xFC, + 0x7C, 0x08, 0x04, 0x04, 0x08, + 0x48, 0x54, 0x54, 0x54, 0x24, + 0x04, 0x04, 0x3F, 0x44, 0x24, + 0x3C, 0x40, 0x40, 0x20, 0x7C, + 0x1C, 0x20, 0x40, 0x20, 0x1C, + 0x3C, 0x40, 0x30, 0x40, 0x3C, + 0x44, 0x28, 0x10, 0x28, 0x44, + 0x4C, 0x90, 0x90, 0x90, 0x7C, + 0x44, 0x64, 0x54, 0x4C, 0x44, + 0x00, 0x08, 0x36, 0x41, 0x00, + 0x00, 0x00, 0x77, 0x00, 0x00, + 0x00, 0x41, 0x36, 0x08, 0x00, + 0x02, 0x01, 0x02, 0x04, 0x02, + 0x3C, 0x26, 0x23, 0x26, 0x3C, + 0x1E, 0xA1, 0xA1, 0x61, 0x12, + 0x3A, 0x40, 0x40, 0x20, 0x7A, + 0x38, 0x54, 0x54, 0x55, 0x59, + 0x21, 0x55, 0x55, 0x79, 0x41, + 0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut + 0x21, 0x55, 0x54, 0x78, 0x40, + 0x20, 0x54, 0x55, 0x79, 0x40, + 0x0C, 0x1E, 0x52, 0x72, 0x12, + 0x39, 0x55, 0x55, 0x55, 0x59, + 0x39, 0x54, 0x54, 0x54, 0x59, + 0x39, 0x55, 0x54, 0x54, 0x58, + 0x00, 0x00, 0x45, 0x7C, 0x41, + 0x00, 0x02, 0x45, 0x7D, 0x42, + 0x00, 0x01, 0x45, 0x7C, 0x40, + 0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut + 0xF0, 0x28, 0x25, 0x28, 0xF0, + 0x7C, 0x54, 0x55, 0x45, 0x00, + 0x20, 0x54, 0x54, 0x7C, 0x54, + 0x7C, 0x0A, 0x09, 0x7F, 0x49, + 0x32, 0x49, 0x49, 0x49, 0x32, + 0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut + 0x32, 0x4A, 0x48, 0x48, 0x30, + 0x3A, 0x41, 0x41, 0x21, 0x7A, + 0x3A, 0x42, 0x40, 0x20, 0x78, + 0x00, 0x9D, 0xA0, 0xA0, 0x7D, + 0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut + 0x3D, 0x40, 0x40, 0x40, 0x3D, + 0x3C, 0x24, 0xFF, 0x24, 0x24, + 0x48, 0x7E, 0x49, 0x43, 0x66, + 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, + 0xFF, 0x09, 0x29, 0xF6, 0x20, + 0xC0, 0x88, 0x7E, 0x09, 0x03, + 0x20, 0x54, 0x54, 0x79, 0x41, + 0x00, 0x00, 0x44, 0x7D, 0x41, + 0x30, 0x48, 0x48, 0x4A, 0x32, + 0x38, 0x40, 0x40, 0x22, 0x7A, + 0x00, 0x7A, 0x0A, 0x0A, 0x72, + 0x7D, 0x0D, 0x19, 0x31, 0x7D, + 0x26, 0x29, 0x29, 0x2F, 0x28, + 0x26, 0x29, 0x29, 0x29, 0x26, + 0x30, 0x48, 0x4D, 0x40, 0x20, + 0x38, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x08, 0x08, 0x38, + 0x2F, 0x10, 0xC8, 0xAC, 0xBA, + 0x2F, 0x10, 0x28, 0x34, 0xFA, + 0x00, 0x00, 0x7B, 0x00, 0x00, + 0x08, 0x14, 0x2A, 0x14, 0x22, + 0x22, 0x14, 0x2A, 0x14, 0x08, + 0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code + 0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block + 0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block + 0x00, 0x00, 0x00, 0xFF, 0x00, + 0x10, 0x10, 0x10, 0xFF, 0x00, + 0x14, 0x14, 0x14, 0xFF, 0x00, + 0x10, 0x10, 0xFF, 0x00, 0xFF, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x14, 0x14, 0x14, 0xFC, 0x00, + 0x14, 0x14, 0xF7, 0x00, 0xFF, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x14, 0x14, 0xF4, 0x04, 0xFC, + 0x14, 0x14, 0x17, 0x10, 0x1F, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0x1F, 0x00, + 0x10, 0x10, 0x10, 0xF0, 0x00, + 0x00, 0x00, 0x00, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0x1F, 0x10, + 0x10, 0x10, 0x10, 0xF0, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0xFF, 0x10, + 0x00, 0x00, 0x00, 0xFF, 0x14, + 0x00, 0x00, 0xFF, 0x00, 0xFF, + 0x00, 0x00, 0x1F, 0x10, 0x17, + 0x00, 0x00, 0xFC, 0x04, 0xF4, + 0x14, 0x14, 0x17, 0x10, 0x17, + 0x14, 0x14, 0xF4, 0x04, 0xF4, + 0x00, 0x00, 0xFF, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x14, 0x14, + 0x14, 0x14, 0xF7, 0x00, 0xF7, + 0x14, 0x14, 0x14, 0x17, 0x14, + 0x10, 0x10, 0x1F, 0x10, 0x1F, + 0x14, 0x14, 0x14, 0xF4, 0x14, + 0x10, 0x10, 0xF0, 0x10, 0xF0, + 0x00, 0x00, 0x1F, 0x10, 0x1F, + 0x00, 0x00, 0x00, 0x1F, 0x14, + 0x00, 0x00, 0x00, 0xFC, 0x14, + 0x00, 0x00, 0xF0, 0x10, 0xF0, + 0x10, 0x10, 0xFF, 0x10, 0xFF, + 0x14, 0x14, 0x14, 0xFF, 0x14, + 0x10, 0x10, 0x10, 0x1F, 0x00, + 0x00, 0x00, 0x00, 0xF0, 0x10, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, + 0xFF, 0xFF, 0xFF, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xFF, 0xFF, + 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, + 0x38, 0x44, 0x44, 0x38, 0x44, + 0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta + 0x7E, 0x02, 0x02, 0x06, 0x06, + 0x02, 0x7E, 0x02, 0x7E, 0x02, + 0x63, 0x55, 0x49, 0x41, 0x63, + 0x38, 0x44, 0x44, 0x3C, 0x04, + 0x40, 0x7E, 0x20, 0x1E, 0x20, + 0x06, 0x02, 0x7E, 0x02, 0x02, + 0x99, 0xA5, 0xE7, 0xA5, 0x99, + 0x1C, 0x2A, 0x49, 0x2A, 0x1C, + 0x4C, 0x72, 0x01, 0x72, 0x4C, + 0x30, 0x4A, 0x4D, 0x4D, 0x30, + 0x30, 0x48, 0x78, 0x48, 0x30, + 0xBC, 0x62, 0x5A, 0x46, 0x3D, + 0x3E, 0x49, 0x49, 0x49, 0x00, + 0x7E, 0x01, 0x01, 0x01, 0x7E, + 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, + 0x44, 0x44, 0x5F, 0x44, 0x44, + 0x40, 0x51, 0x4A, 0x44, 0x40, + 0x40, 0x44, 0x4A, 0x51, 0x40, + 0x00, 0x00, 0xFF, 0x01, 0x03, + 0xE0, 0x80, 0xFF, 0x00, 0x00, + 0x08, 0x08, 0x6B, 0x6B, 0x08, + 0x36, 0x12, 0x36, 0x24, 0x36, + 0x06, 0x0F, 0x09, 0x0F, 0x06, + 0x00, 0x00, 0x18, 0x18, 0x00, + 0x00, 0x00, 0x10, 0x10, 0x00, + 0x30, 0x40, 0xFF, 0x01, 0x01, + 0x00, 0x1F, 0x01, 0x01, 0x1E, + 0x00, 0x19, 0x1D, 0x17, 0x12, + 0x00, 0x3C, 0x3C, 0x3C, 0x3C, + 0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP +}; + +#endif // FONT5X7_H diff --git a/glcdfont.c b/glcdfont.c new file mode 100644 index 0000000..c2c52ca --- /dev/null +++ b/glcdfont.c @@ -0,0 +1,6 @@ +//Include the font so that it's built by the arduino +//default builder, despite being in a subdirectory +//#include "PDQ_MinLib/glcdfont.c" + +#include +const unsigned char glcdfont[] PROGMEM = {0}; \ No newline at end of file diff --git a/nano_font.cpp b/nano_font.cpp new file mode 100644 index 0000000..9d4803c --- /dev/null +++ b/nano_font.cpp @@ -0,0 +1,337 @@ +#include "nano_font.h" +#include + +const uint8_t ubitxBitmaps[] PROGMEM = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, + 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, + 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, + 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, + 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, + 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, + 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, + 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, + 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, + 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, + 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, + 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, + 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, + 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, + 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0xFF, 0xE0, 0xF3, 0xF9, 0xFC, 0xFE, 0x7E, + 0x3B, 0x1D, 0x84, 0x0E, 0x70, 0x73, 0x83, 0x9C, 0x18, 0xC7, 0xFF, 0xBF, + 0xFD, 0xFF, 0xE3, 0x9C, 0x18, 0xC0, 0xC6, 0x0E, 0x7D, 0xFF, 0xEF, 0xFF, + 0x18, 0xC0, 0xC6, 0x0E, 0x70, 0x73, 0x83, 0x9C, 0x00, 0x04, 0x01, 0xF8, + 0x7F, 0xCF, 0xDE, 0xE4, 0xEE, 0x4E, 0xE4, 0x0F, 0x40, 0x7E, 0x03, 0xFC, + 0x0F, 0xE0, 0x5E, 0x04, 0xFE, 0x4F, 0xE4, 0xFF, 0x4E, 0x7F, 0xE3, 0xFC, + 0x04, 0x00, 0x40, 0x04, 0x00, 0x3C, 0x06, 0x07, 0xE0, 0x60, 0xFF, 0x0C, + 0x0C, 0x30, 0x80, 0xC3, 0x18, 0x0C, 0x31, 0x00, 0xFF, 0x30, 0x07, 0xE6, + 0x00, 0x3C, 0x60, 0x00, 0x0C, 0x7C, 0x00, 0xCF, 0xE0, 0x19, 0xC6, 0x01, + 0x98, 0x70, 0x31, 0x87, 0x03, 0x1C, 0x60, 0x60, 0xFE, 0x04, 0x07, 0xC0, + 0x0F, 0x80, 0x1F, 0xC0, 0x3D, 0xE0, 0x38, 0xE0, 0x3C, 0xE0, 0x1D, 0xC0, + 0x1F, 0xC0, 0x0F, 0x00, 0x3F, 0x8C, 0x7B, 0xDC, 0x71, 0xDC, 0xF1, 0xFC, + 0xF0, 0xF8, 0xF0, 0x78, 0x79, 0xFC, 0x7F, 0xFC, 0x3F, 0x9E, 0x00, 0x00, + 0xFF, 0xFF, 0xE6, 0x60, 0x0C, 0x71, 0x8E, 0x31, 0xC7, 0x38, 0xE3, 0x8E, + 0x38, 0xE3, 0x8E, 0x38, 0x71, 0xC7, 0x0E, 0x38, 0x70, 0xC0, 0xC3, 0x86, + 0x1C, 0x70, 0xE3, 0x8E, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xCE, 0x38, 0xE7, + 0x1C, 0x63, 0x8C, 0x00, 0x10, 0x10, 0x10, 0xFE, 0x7C, 0x38, 0x6C, 0x44, + 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x60, + 0x06, 0x00, 0x60, 0x06, 0x00, 0xFF, 0xF2, 0xFE, 0xFF, 0xFF, 0xC0, 0xFF, + 0xF0, 0x04, 0x08, 0x30, 0x60, 0x83, 0x06, 0x08, 0x10, 0x60, 0xC1, 0x06, + 0x0C, 0x10, 0x20, 0xC0, 0x3F, 0x8F, 0xF9, 0xEF, 0x78, 0xFE, 0x0F, 0xC1, + 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xE3, 0xDE, + 0xF3, 0xFE, 0x3F, 0x80, 0x80, 0x06, 0x1C, 0x7F, 0xFF, 0xE1, 0xC3, 0x87, + 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x3F, 0x8F, 0xFB, 0xEF, + 0xF8, 0x7E, 0x0F, 0xC1, 0xC0, 0x38, 0x0F, 0x03, 0xC0, 0xF0, 0x7C, 0x1F, + 0x07, 0x80, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0x8F, 0xFB, 0xCF, + 0xF0, 0xFE, 0x1E, 0x03, 0xC0, 0x70, 0x7C, 0x0F, 0xC0, 0xFC, 0x03, 0x80, + 0x7E, 0x0F, 0xC1, 0xFC, 0xFB, 0xFE, 0x3F, 0x80, 0x80, 0x07, 0xC0, 0x7C, + 0x0F, 0xC0, 0xFC, 0x1F, 0xC3, 0xBC, 0x33, 0xC7, 0x3C, 0x63, 0xCE, 0x3C, + 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3F, + 0xEF, 0xFD, 0xFF, 0xB8, 0x06, 0x00, 0xC0, 0x1F, 0xE7, 0xFE, 0xF1, 0xE0, + 0x1C, 0x03, 0x80, 0x70, 0x0F, 0xC1, 0xFC, 0xFB, 0xFE, 0x3F, 0x80, 0x80, + 0x1F, 0x87, 0xF9, 0xE7, 0xB8, 0x7E, 0x01, 0xC0, 0x3B, 0xE7, 0xFE, 0xFB, + 0xFE, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xE1, 0xDE, 0xFB, 0xFE, 0x3F, 0x80, + 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0E, 0x01, 0xC0, 0x3C, 0x03, 0x80, + 0x70, 0x0F, 0x00, 0xE0, 0x0E, 0x01, 0xE0, 0x1C, 0x01, 0xC0, 0x1C, 0x03, + 0xC0, 0x3C, 0x00, 0x3F, 0x87, 0xFC, 0xF9, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, + 0x71, 0xC3, 0xF8, 0x7F, 0xCF, 0x1E, 0xE0, 0xEE, 0x0F, 0xE0, 0xFE, 0x0E, + 0xF1, 0xE7, 0xFC, 0x3F, 0x80, 0x40, 0x3F, 0x0F, 0xFB, 0xEF, 0x70, 0xFE, + 0x0F, 0xC1, 0xF8, 0x3F, 0x0F, 0xF3, 0xEF, 0xFC, 0xFB, 0x80, 0x70, 0x0F, + 0xC3, 0xFE, 0xF3, 0xFE, 0x3F, 0x80, 0x80, 0xFF, 0x80, 0x00, 0xFF, 0xF0, + 0xFF, 0x80, 0x00, 0xFF, 0xF2, 0xDE, 0x00, 0x70, 0x1F, 0x0F, 0xE7, 0xF0, + 0xF8, 0x0E, 0x00, 0xFC, 0x03, 0xF8, 0x0F, 0xE0, 0x1F, 0x00, 0x30, 0xFF, + 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0xF0, 0xC0, 0x0F, 0x80, 0x7F, 0x00, 0xFC, 0x03, 0xF0, 0x07, 0x03, 0xF1, + 0xFC, 0xFE, 0x0F, 0x80, 0xC0, 0x00, 0x1F, 0x0F, 0xF3, 0xFF, 0x78, 0xFE, + 0x0F, 0xC1, 0xC0, 0x38, 0x0F, 0x03, 0xE0, 0xF8, 0x3C, 0x07, 0x00, 0xE0, + 0x00, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xFE, + 0x00, 0xF0, 0x3C, 0x07, 0x00, 0x38, 0x38, 0x00, 0x30, 0xC0, 0x00, 0xE6, + 0x0F, 0xF1, 0x98, 0x73, 0xC7, 0xC3, 0x87, 0x0F, 0x0C, 0x1C, 0x3C, 0x30, + 0x61, 0xF1, 0xC1, 0x86, 0xC7, 0x0E, 0x1B, 0x1C, 0x38, 0xEC, 0x3B, 0xEF, + 0x38, 0xFD, 0xF8, 0x70, 0xC1, 0x80, 0xE0, 0x00, 0x01, 0xC0, 0x10, 0x03, + 0xFF, 0xC0, 0x03, 0xFF, 0x00, 0x03, 0xC0, 0x07, 0xC0, 0x07, 0xE0, 0x07, + 0xE0, 0x0F, 0xE0, 0x0E, 0xF0, 0x0E, 0xF0, 0x1E, 0x70, 0x1C, 0x78, 0x1C, + 0x78, 0x3C, 0x38, 0x3F, 0xFC, 0x3F, 0xFC, 0x7F, 0xFC, 0x70, 0x1E, 0xF0, + 0x1E, 0xF0, 0x0E, 0xE0, 0x0F, 0xFF, 0x03, 0xFF, 0xCF, 0xFF, 0xBC, 0x7E, + 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBF, 0xFE, 0xFF, 0xE3, 0xFF, 0xCF, 0x0F, + 0xBC, 0x0F, 0xF0, 0x1F, 0xC0, 0xFF, 0x03, 0xFF, 0xFE, 0xFF, 0xFB, 0xFF, + 0x80, 0x03, 0xC0, 0x1F, 0xF0, 0xFF, 0xF1, 0xF1, 0xE7, 0x81, 0xEF, 0x01, + 0xFC, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F, + 0x00, 0xEF, 0x01, 0xDE, 0x07, 0x9F, 0xFE, 0x1F, 0xFC, 0x1F, 0xE0, 0x04, + 0x00, 0xFE, 0x03, 0xFF, 0x8F, 0xFF, 0x38, 0x7E, 0xE0, 0x7B, 0x80, 0xFE, + 0x03, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x3F, + 0x80, 0xFE, 0x07, 0xBF, 0xFE, 0xFF, 0xF3, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1F, 0xFE, 0xFF, 0xF7, + 0xFF, 0xBC, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xE0, 0x0E, 0x00, + 0xE0, 0x0F, 0xFE, 0xFF, 0xEF, 0xFE, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, + 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x03, 0xE0, 0x0F, 0xF8, 0x1F, 0xFC, + 0x3E, 0x3E, 0x78, 0x0F, 0x70, 0x0F, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, + 0xF0, 0x7F, 0xF0, 0x7F, 0xF0, 0x7F, 0xF0, 0x07, 0x78, 0x0F, 0x7C, 0x1F, + 0x3F, 0xFF, 0x1F, 0xFB, 0x0F, 0xF3, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, + 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, + 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, + 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0xE0, 0x3C, + 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, + 0x80, 0xFE, 0x1F, 0xC3, 0xF8, 0x7F, 0xFE, 0xFF, 0xCF, 0xF0, 0x00, 0x00, + 0xE0, 0x3D, 0xC0, 0xFB, 0x83, 0xE7, 0x07, 0x8E, 0x1E, 0x1C, 0x78, 0x39, + 0xE0, 0x77, 0x80, 0xFF, 0x01, 0xFF, 0x03, 0xFE, 0x07, 0x9E, 0x0E, 0x1E, + 0x1C, 0x1E, 0x38, 0x3C, 0x70, 0x3C, 0xE0, 0x3D, 0xC0, 0x3C, 0xF0, 0x0F, + 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, + 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xF8, 0x1F, 0xFC, 0x0F, 0xFE, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, + 0xE1, 0xFF, 0xB0, 0xFF, 0xDC, 0x6F, 0xEE, 0x77, 0xF7, 0x3B, 0xF9, 0x9D, + 0xFC, 0xCC, 0xFE, 0x76, 0x7F, 0x3F, 0x3F, 0x8F, 0x9F, 0xC7, 0xCF, 0xE3, + 0xC7, 0xF1, 0xE3, 0xC0, 0xE0, 0x3F, 0xC0, 0xFF, 0x03, 0xFE, 0x0F, 0xFC, + 0x3F, 0xF0, 0xFE, 0xE3, 0xFB, 0x8F, 0xE7, 0x3F, 0x9E, 0xFE, 0x3B, 0xF8, + 0xFF, 0xE1, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x1F, 0xE0, 0x7F, 0x80, 0xF0, + 0x03, 0xE0, 0x07, 0xFC, 0x07, 0xFF, 0x07, 0xCF, 0xC7, 0x81, 0xF3, 0xC0, + 0x7B, 0xC0, 0x1D, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE, + 0x00, 0xFF, 0x00, 0x73, 0xC0, 0x79, 0xF0, 0x7C, 0x7F, 0xFC, 0x1F, 0xFC, + 0x07, 0xFC, 0x00, 0x20, 0x00, 0xFF, 0x07, 0xFF, 0x3F, 0xFD, 0xC3, 0xFE, + 0x07, 0xF0, 0x1F, 0x80, 0xFC, 0x0F, 0xE0, 0xFF, 0xFF, 0xBF, 0xF9, 0xFF, + 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x03, + 0xE0, 0x07, 0xFC, 0x07, 0xFF, 0x07, 0xCF, 0xC7, 0x80, 0xF3, 0xC0, 0x7B, + 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE, 0x04, + 0xFF, 0x07, 0x73, 0xC3, 0xF9, 0xF0, 0xFC, 0x7F, 0xFC, 0x1F, 0xFF, 0x07, + 0xFF, 0xC0, 0x20, 0xC0, 0xFF, 0x83, 0xFF, 0xCF, 0xFF, 0xBC, 0x3F, 0xF0, + 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xFF, 0xFB, 0xFF, 0x8F, 0xFF, 0xBC, + 0x1E, 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBC, 0x0E, 0xF0, 0x3F, 0xC0, 0xF0, + 0x0F, 0x80, 0xFF, 0xC7, 0xFF, 0xBE, 0x1E, 0xF0, 0x3B, 0xC0, 0xFF, 0x00, + 0x3F, 0x80, 0x7F, 0xE0, 0xFF, 0xE0, 0x3F, 0xC0, 0x0F, 0x00, 0x1F, 0x80, + 0x7F, 0x03, 0xFF, 0x1F, 0x7F, 0xF8, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, + 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, + 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, + 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, + 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0xC0, 0xFF, 0x07, 0x9F, 0xFE, 0x7F, 0xF0, + 0x7F, 0x80, 0x20, 0x00, 0xE0, 0x1F, 0xC0, 0x3B, 0xC0, 0xF3, 0x81, 0xE7, + 0x03, 0x8F, 0x0F, 0x0E, 0x1C, 0x1C, 0x38, 0x3C, 0x70, 0x39, 0xC0, 0x73, + 0x80, 0xE7, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x03, 0xC0, 0x07, 0x80, + 0x0F, 0x00, 0xF0, 0x38, 0x1D, 0xC1, 0xE0, 0xF7, 0x87, 0xC3, 0xDE, 0x1F, + 0x0F, 0x78, 0x7C, 0x38, 0xE3, 0xB0, 0xE3, 0x8E, 0xC7, 0x8F, 0x3B, 0x9C, + 0x1C, 0xEE, 0x70, 0x73, 0x39, 0xC1, 0xDC, 0x67, 0x07, 0x71, 0xB8, 0x0F, + 0xC7, 0xE0, 0x3E, 0x1F, 0x80, 0xF8, 0x3E, 0x01, 0xE0, 0xF0, 0x07, 0x83, + 0xC0, 0x1E, 0x0F, 0x00, 0xF0, 0x3D, 0xF0, 0x79, 0xE1, 0xE1, 0xE3, 0xC3, + 0xCF, 0x03, 0xFC, 0x07, 0xF8, 0x07, 0xE0, 0x07, 0x80, 0x0F, 0x00, 0x3F, + 0x00, 0x7F, 0x01, 0xFE, 0x07, 0x9E, 0x0F, 0x3C, 0x3C, 0x3C, 0xF8, 0x3D, + 0xE0, 0x78, 0xF0, 0x1F, 0xE0, 0x79, 0xE0, 0xF3, 0xC3, 0xC3, 0xC7, 0x87, + 0x9E, 0x07, 0x3C, 0x0F, 0x70, 0x0F, 0xE0, 0x1F, 0x80, 0x1F, 0x00, 0x3C, + 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F, 0x00, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x80, + 0x78, 0x07, 0x80, 0x78, 0x07, 0x80, 0x7C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, + 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xCE, 0x73, 0x9C, 0xE7, + 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCF, 0xFF, 0xE0, 0xC1, 0x81, 0x02, + 0x06, 0x04, 0x08, 0x18, 0x30, 0x20, 0x60, 0xC0, 0x81, 0x83, 0x02, 0x06, + 0xFF, 0xFF, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, + 0x1C, 0x71, 0xC7, 0xFF, 0xFF, 0xC0, 0x0F, 0x00, 0xF0, 0x0F, 0x01, 0xF8, + 0x1B, 0x83, 0x9C, 0x39, 0xC3, 0x0C, 0x70, 0xE7, 0x0E, 0xE0, 0x70, 0xFF, + 0xFF, 0xFF, 0xFC, 0x71, 0x86, 0x3F, 0x87, 0xFC, 0xFF, 0xEE, 0x1E, 0x01, + 0xE0, 0xFE, 0x7F, 0xEF, 0x8E, 0xE1, 0xEE, 0x1E, 0xF3, 0xEF, 0xFE, 0x7E, + 0xE1, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x7B, 0xE3, + 0xFF, 0x9F, 0xFE, 0xF8, 0xF7, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, + 0x3F, 0xC1, 0xDF, 0x9E, 0xFF, 0xE7, 0xFE, 0x00, 0x40, 0x1F, 0x83, 0xFC, + 0x7F, 0xEF, 0x0E, 0xE0, 0xEE, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0x0E, + 0x79, 0xE7, 0xFC, 0x3F, 0x80, 0x00, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, + 0x00, 0x71, 0xE7, 0x3F, 0xF7, 0xFF, 0xF0, 0xFE, 0x0F, 0xE0, 0x7E, 0x07, + 0xE0, 0x7E, 0x0F, 0xF0, 0xF7, 0x9F, 0x7F, 0xF3, 0xF7, 0x00, 0x00, 0x1F, + 0x07, 0xFC, 0x7B, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE, 0xFF, 0xFF, 0xFF, 0xE0, + 0x0E, 0x0E, 0xF1, 0xE7, 0xFC, 0x3F, 0x80, 0x40, 0x00, 0x1E, 0x3E, 0x3C, + 0x3C, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, + 0x3C, 0x3C, 0x1E, 0x73, 0xF7, 0x7F, 0xFF, 0x0F, 0xF0, 0xFE, 0x07, 0xE0, + 0x7E, 0x07, 0xE0, 0x7F, 0x0F, 0x79, 0xF7, 0xFF, 0x3F, 0x70, 0x07, 0x00, + 0x7F, 0x0F, 0x7F, 0xE3, 0xFC, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, + 0xDF, 0x3F, 0xF7, 0xFF, 0xF1, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, + 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1C, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFC, 0x39, 0xCE, 0x70, 0x1C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, + 0xCE, 0x7F, 0xFF, 0xC0, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, + 0x0E, 0xF1, 0xEF, 0x3C, 0xF7, 0x8F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x8F, + 0x3C, 0xF3, 0xCF, 0x1E, 0xF1, 0xEF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFC, 0xF7, 0xCF, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0xF8, 0x78, 0xFF, + 0x0E, 0x1F, 0xE1, 0xC3, 0xFC, 0x38, 0x7F, 0x87, 0x0F, 0xF0, 0xE1, 0xFE, + 0x1C, 0x3F, 0xC3, 0x87, 0xF8, 0x70, 0xFF, 0x0E, 0x1E, 0xEF, 0x9F, 0xFB, + 0xFF, 0xF8, 0xFE, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, + 0xF0, 0x7E, 0x0E, 0x1F, 0x81, 0xFF, 0x1F, 0xFD, 0xE1, 0xEF, 0x07, 0x70, + 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x83, 0x9E, 0x3C, 0xFF, 0xC3, 0xFC, + 0x01, 0x00, 0xF7, 0xC7, 0xFF, 0x3F, 0xFD, 0xF1, 0xEF, 0x07, 0xF8, 0x3F, + 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xBE, 0x3D, 0xFF, 0xCF, 0x7C, 0x78, + 0x83, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x00, 0x1E, 0x77, 0xF7, 0x7F, + 0xFF, 0x0F, 0xE0, 0xFE, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0xFF, 0x0F, 0xF9, + 0xF7, 0xFF, 0x3F, 0x70, 0x47, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0xEF, + 0xFF, 0xFF, 0x8E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x00, 0x3F, + 0x8F, 0xFB, 0xEF, 0xF8, 0x7F, 0x01, 0xFE, 0x1F, 0xF0, 0xFF, 0x01, 0xFC, + 0x1F, 0xC3, 0xFF, 0xF7, 0xFC, 0x08, 0x00, 0x38, 0x70, 0xE7, 0xFF, 0xFF, + 0xCE, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0F, 0x8F, 0x04, 0xF0, 0x7F, + 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, + 0x0F, 0x79, 0xF7, 0xFF, 0x3F, 0x70, 0x80, 0xF0, 0x7B, 0x83, 0x9E, 0x1C, + 0x71, 0xE3, 0x8E, 0x1E, 0x70, 0x73, 0x83, 0xB8, 0x1D, 0xC0, 0x7E, 0x03, + 0xE0, 0x1F, 0x00, 0x78, 0x00, 0xF0, 0xE1, 0xDC, 0x78, 0x77, 0x1F, 0x3D, + 0xC7, 0xCE, 0x79, 0xF3, 0x8E, 0xEC, 0xE3, 0xBB, 0x78, 0xEC, 0xFC, 0x1F, + 0x3F, 0x07, 0xCF, 0xC1, 0xF1, 0xE0, 0x7C, 0x78, 0x0E, 0x1E, 0x00, 0x78, + 0xF3, 0xC7, 0x8F, 0x78, 0x3B, 0x81, 0xFC, 0x07, 0xC0, 0x1E, 0x01, 0xF0, + 0x1F, 0xC0, 0xEF, 0x0F, 0x78, 0xF1, 0xE7, 0x87, 0x80, 0xF0, 0x7B, 0x83, + 0x9E, 0x1C, 0xF1, 0xE3, 0x8E, 0x1E, 0x70, 0x73, 0x83, 0xB8, 0x1D, 0xC0, + 0x7E, 0x03, 0xE0, 0x1F, 0x00, 0x78, 0x03, 0x80, 0x1C, 0x01, 0xE0, 0x3E, + 0x01, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x1E, 0x0F, 0x83, 0xC1, 0xE0, + 0xF0, 0x78, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0x3C, 0xF9, 0xC3, + 0x87, 0x0E, 0x1C, 0x38, 0x73, 0xC7, 0x0F, 0x07, 0x0E, 0x1C, 0x38, 0x70, + 0xE1, 0xC3, 0xE7, 0xC7, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xC3, + 0xCF, 0x0C, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0xC7, 0x3C, 0xE3, 0x8E, 0x38, + 0xE3, 0x8E, 0xF3, 0xCE, 0x00, 0x10, 0x0F, 0x85, 0xBD, 0xE1, 0xF0, 0x08, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, + 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, + 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0 }; + +const GFXglyph ubitxGlyphs[] PROGMEM = { + { 0, 13, 18, 17, 2, -17 }, // 0x14 + { 30, 13, 18, 17, 2, -17 }, // 0x15 + { 60, 13, 18, 17, 2, -17 }, // 0x16 + { 90, 13, 18, 17, 2, -17 }, // 0x17 + { 120, 13, 18, 17, 2, -17 }, // 0x18 + { 150, 13, 18, 17, 2, -17 }, // 0x19 + { 180, 13, 18, 17, 2, -17 }, // 0x1A + { 210, 13, 18, 17, 2, -17 }, // 0x1B + { 240, 13, 18, 17, 2, -17 }, // 0x1C + { 270, 13, 18, 17, 2, -17 }, // 0x1D + { 300, 13, 18, 17, 2, -17 }, // 0x1E + { 330, 13, 18, 17, 2, -17 }, // 0x1F + { 360, 0, 0, 7, 0, 1 }, // 0x20 ' ' + { 360, 3, 17, 8, 3, -16 }, // 0x21 '!' + { 367, 9, 7, 11, 1, -17 }, // 0x22 '"' + { 375, 13, 18, 13, 0, -16 }, // 0x23 '#' + { 405, 12, 21, 13, 1, -17 }, // 0x24 '$' + { 437, 20, 17, 21, 1, -16 }, // 0x25 '%' + { 480, 16, 18, 17, 1, -16 }, // 0x26 '&' + { 516, 4, 7, 6, 1, -17 }, // 0x27 ''' + { 520, 6, 23, 8, 1, -17 }, // 0x28 '(' + { 538, 6, 23, 8, 1, -17 }, // 0x29 ')' + { 556, 8, 8, 9, 1, -17 }, // 0x2A '*' + { 564, 12, 11, 14, 1, -10 }, // 0x2B '+' + { 581, 3, 8, 7, 2, -3 }, // 0x2C ',' + { 584, 6, 3, 8, 1, -7 }, // 0x2D '-' + { 587, 3, 4, 7, 2, -3 }, // 0x2E '.' + { 589, 7, 17, 7, 0, -16 }, // 0x2F '/' + { 604, 11, 18, 13, 1, -16 }, // 0x30 '0' + { 629, 7, 17, 13, 2, -16 }, // 0x31 '1' + { 644, 11, 17, 13, 1, -16 }, // 0x32 '2' + { 668, 11, 18, 13, 1, -16 }, // 0x33 '3' + { 693, 12, 17, 13, 1, -16 }, // 0x34 '4' + { 719, 11, 18, 13, 1, -16 }, // 0x35 '5' + { 744, 11, 18, 13, 1, -16 }, // 0x36 '6' + { 769, 12, 17, 13, 1, -16 }, // 0x37 '7' + { 795, 12, 18, 13, 1, -16 }, // 0x38 '8' + { 822, 11, 18, 13, 1, -16 }, // 0x39 '9' + { 847, 3, 12, 8, 3, -11 }, // 0x3A ':' + { 852, 3, 16, 8, 3, -11 }, // 0x3B ';' + { 858, 12, 11, 14, 1, -10 }, // 0x3C '<' + { 875, 12, 9, 14, 1, -9 }, // 0x3D '=' + { 889, 12, 11, 14, 1, -10 }, // 0x3E '>' + { 906, 11, 18, 15, 2, -17 }, // 0x3F '?' + { 931, 22, 21, 23, 1, -17 }, // 0x40 '@' + { 989, 16, 18, 17, 1, -17 }, // 0x41 'A' + { 1025, 14, 18, 17, 2, -17 }, // 0x42 'B' + { 1057, 15, 19, 17, 1, -17 }, // 0x43 'C' + { 1093, 14, 18, 17, 2, -17 }, // 0x44 'D' + { 1125, 13, 18, 16, 2, -17 }, // 0x45 'E' + { 1155, 12, 18, 15, 2, -17 }, // 0x46 'F' + { 1182, 16, 18, 19, 1, -17 }, // 0x47 'G' + { 1218, 14, 18, 17, 2, -17 }, // 0x48 'H' + { 1250, 3, 18, 7, 2, -17 }, // 0x49 'I' + { 1257, 11, 19, 13, 1, -17 }, // 0x4A 'J' + { 1284, 15, 18, 17, 2, -17 }, // 0x4B 'K' + { 1318, 12, 18, 15, 2, -17 }, // 0x4C 'L' + { 1345, 17, 18, 20, 2, -17 }, // 0x4D 'M' + { 1384, 14, 18, 17, 2, -17 }, // 0x4E 'N' + { 1416, 17, 19, 19, 1, -17 }, // 0x4F 'O' + { 1457, 13, 18, 16, 2, -17 }, // 0x50 'P' + { 1487, 17, 19, 19, 1, -17 }, // 0x51 'Q' + { 1528, 14, 18, 17, 2, -17 }, // 0x52 'R' + { 1560, 14, 19, 16, 1, -17 }, // 0x53 'S' + { 1594, 14, 18, 15, 0, -17 }, // 0x54 'T' + { 1626, 14, 19, 17, 2, -17 }, // 0x55 'U' + { 1660, 15, 18, 16, 1, -17 }, // 0x56 'V' + { 1694, 22, 18, 23, 0, -17 }, // 0x57 'W' + { 1744, 15, 18, 16, 1, -17 }, // 0x58 'X' + { 1778, 15, 18, 16, 1, -17 }, // 0x59 'Y' + { 1812, 13, 18, 15, 1, -17 }, // 0x5A 'Z' + { 1842, 5, 23, 8, 2, -17 }, // 0x5B '[' + { 1857, 7, 17, 7, 0, -16 }, // 0x5C '\' + { 1872, 6, 23, 8, 0, -17 }, // 0x5D ']' + { 1890, 12, 11, 14, 1, -16 }, // 0x5E '^' + { 1907, 15, 2, 13, -1, 4 }, // 0x5F '_' + { 1911, 5, 3, 8, 0, -17 }, // 0x60 '`' + { 1913, 12, 14, 13, 1, -12 }, // 0x61 'a' + { 1934, 13, 19, 15, 1, -17 }, // 0x62 'b' + { 1965, 12, 14, 13, 1, -12 }, // 0x63 'c' + { 1986, 12, 19, 15, 1, -17 }, // 0x64 'd' + { 2015, 12, 14, 13, 1, -12 }, // 0x65 'e' + { 2036, 8, 18, 8, 0, -17 }, // 0x66 'f' + { 2054, 12, 18, 15, 1, -12 }, // 0x67 'g' + { 2081, 11, 18, 15, 2, -17 }, // 0x68 'h' + { 2106, 3, 18, 7, 2, -17 }, // 0x69 'i' + { 2113, 5, 23, 7, 0, -17 }, // 0x6A 'j' + { 2128, 12, 18, 13, 1, -17 }, // 0x6B 'k' + { 2155, 3, 18, 7, 2, -17 }, // 0x6C 'l' + { 2162, 19, 13, 21, 1, -12 }, // 0x6D 'm' + { 2193, 11, 13, 15, 2, -12 }, // 0x6E 'n' + { 2211, 13, 14, 15, 1, -12 }, // 0x6F 'o' + { 2234, 13, 18, 15, 1, -12 }, // 0x70 'p' + { 2264, 12, 18, 15, 1, -12 }, // 0x71 'q' + { 2291, 7, 13, 9, 2, -12 }, // 0x72 'r' + { 2303, 11, 14, 13, 1, -12 }, // 0x73 's' + { 2323, 7, 17, 8, 0, -15 }, // 0x74 't' + { 2338, 12, 14, 15, 1, -12 }, // 0x75 'u' + { 2359, 13, 13, 13, 0, -12 }, // 0x76 'v' + { 2381, 18, 13, 19, 0, -12 }, // 0x77 'w' + { 2411, 13, 13, 13, 0, -12 }, // 0x78 'x' + { 2433, 13, 18, 13, 0, -12 }, // 0x79 'y' + { 2463, 10, 13, 12, 1, -12 }, // 0x7A 'z' + { 2480, 7, 23, 9, 1, -17 }, // 0x7B '{' + { 2501, 2, 23, 7, 2, -17 }, // 0x7C '|' + { 2507, 6, 23, 9, 2, -17 }, // 0x7D '}' + { 2525, 11, 5, 14, 1, -7 }, // 0x7E '~' + { 2532, 13, 18, 17, 2, -17 } }; // 0x7F + +const GFXfont ubitx_font PROGMEM = { + (uint8_t *)ubitxBitmaps, + (GFXglyph *)ubitxGlyphs, + 0x14, + 0x7F, + 33}; + +// Approx. 3325 bytes diff --git a/nano_font.h b/nano_font.h new file mode 100644 index 0000000..1b56f73 --- /dev/null +++ b/nano_font.h @@ -0,0 +1,9 @@ +#ifndef _NANO_FONT +#define _NANO_FONT + +#include +#include "PDQ_MinLib/gfxfont.h" + +extern const GFXfont ubitx_font; + +#endif //_NANO_FONT \ No newline at end of file diff --git a/nano_gui.cpp b/nano_gui.cpp index 97d7ddb..01dd3be 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -3,19 +3,9 @@ #include "ubitx.h" #include "nano_gui.h" -//#include "Adafruit_GFX.h" -//#include #include #include -#define TFT_CS 10 -#define TFT_RS 9 - - -GFXfont *gfxFont = NULL; -//int touch_x, touch_y; -//XPT2046_Touchscreen ts(CS_PIN); -//TS_Point ts_point; struct Point ts_point; //filled from a test run of calibration routine @@ -149,360 +139,80 @@ void scaleTouch(struct Point *p){ // p->y = ((long)(p->y) * 10l)/(long)(slope_y) - offset_y; } +/***************** + * Begin TFT functions + *****************/ +#define ILI9341_CS_PIN TFT_CS +#define ILI9341_DC_PIN TFT_DC +#include "PDQ_MinLib/PDQ_ILI9341.h" +PDQ_ILI9341 tft; -#if !defined(__INT_MAX__) || (__INT_MAX__ > 0xFFFF) - #define pgm_read_pointer(addr) ((void *)pgm_read_dword(addr)) -#else - #define pgm_read_pointer(addr) ((void *)pgm_read_word(addr)) -#endif - -inline GFXglyph * pgm_read_glyph_ptr(const GFXfont *gfxFont, uint8_t c) -{ -#ifdef __AVR__ - return &(((GFXglyph *)pgm_read_pointer(&gfxFont->glyph))[c]); -#else - // expression in __AVR__ section may generate "dereferencing type-punned pointer will break strict-aliasing rules" warning - // In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way - // So expression may be simplified - return gfxFont->glyph + c; -#endif //__AVR__ -} - -inline uint8_t * pgm_read_bitmap_ptr(const GFXfont *gfxFont){ -#ifdef __AVR__ - return (uint8_t *)pgm_read_pointer(&gfxFont->bitmap); -#else - // expression in __AVR__ section generates "dereferencing type-punned pointer will break strict-aliasing rules" warning - // In fact, on other platforms (such as STM32) there is no need to do this pointer magic as program memory may be read in a usual way - // So expression may be simplified - return gfxFont->bitmap; -#endif //__AVR__ -} - -inline static void utft_write(unsigned char d){ - SPI.transfer(d); -} +#include "nano_font.h" -inline static void utftCmd(unsigned char VH){ - *(portOutputRegister(digitalPinToPort(TFT_RS))) &= ~digitalPinToBitMask(TFT_RS);//LCD_RS=0; - utft_write(VH); -} -inline static void utftData(unsigned char VH){ - *(portOutputRegister(digitalPinToPort(TFT_RS)))|= digitalPinToBitMask(TFT_RS);//LCD_RS=1; - utft_write(VH); +bool xpt2046_Init(){ + pinMode(CS_PIN, OUTPUT); + digitalWrite(CS_PIN, HIGH); } +void displayInit(void){ + tft.begin(); + tft.setFont(&ubitx_font); + tft.setTextWrap(false); + tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK); + tft.setTextSize(1); + tft.setRotation(1); -static void utftAddress(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2){ - - utftCmd(0x2a); - utftData(x1>>8); - utftData(x1); - utftData(x2>>8); - utftData(x2); - utftCmd(0x2b); - utftData(y1>>8); - utftData(y1); - utftData(y2>>8); - utftData(y2); - utftCmd(0x2c); + xpt2046_Init(); + readTouchCalibration(); } -void displayPixel(unsigned int x, unsigned int y, unsigned int c){ - unsigned int i,j; - digitalWrite(TFT_CS,LOW); - - utftCmd(0x02c); //write_memory_start - utftAddress(x,y,x,y); - utftData(c>>8); - utftData(c); - - digitalWrite(TFT_CS,HIGH); +void displayPixel(unsigned int x, unsigned int y, unsigned int c){ + tft.drawPixel(x,y,c); } -void displayHline(unsigned int x, unsigned int y, unsigned int l, unsigned int c){ - unsigned int i,j; - - digitalWrite(TFT_CS,LOW); - utftCmd(0x02c); //write_memory_start - l=l+x; - utftAddress(x,y,l,y); - j = l; - for(i=1;i<=j;i++) - { - utftData(c>>8); - utftData(c); - } - digitalWrite(TFT_CS,HIGH); - checkCAT(); +void displayHline(unsigned int x, unsigned int y, unsigned int w, unsigned int c){ + tft.drawFastHLine(x,y,w,c); } -void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c){ - unsigned int i,j; - digitalWrite(TFT_CS,LOW); - - utftCmd(0x02c); //write_memory_start - l=l+y; - utftAddress(x,y,x,l); - j = l; - for(i=1;i<=l;i++) - { - utftData(c>>8); - utftData(c); - } - digitalWrite(TFT_CS,HIGH); - checkCAT(); +void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c){ + tft.drawFastVLine(x,y,l,c); } void displayClear(unsigned int color){ - unsigned int i,m; - - digitalWrite(TFT_CS,LOW); - utftAddress(0,0,320,240); - for(i=0;i<320;i++) - for(m=0;m<240;m++){ - utftData(color>>8); - utftData(color); - } - digitalWrite(TFT_CS,HIGH); + tft.fillRect(0,0,320,240,color); } void displayRect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c){ - displayHline(x , y , w, c); - displayHline(x , y+h, w, c); - displayVline(x , y , h, c); - displayVline(x+w, y , h, c); + tft.drawRect(x,y,w,h,c); } void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c){ - unsigned int i; - - for(i=0;ifirst); - GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c); - uint8_t *bitmap = pgm_read_bitmap_ptr(gfxFont); - - uint16_t bo = pgm_read_word(&glyph->bitmapOffset); - uint8_t w = pgm_read_byte(&glyph->width), - h = pgm_read_byte(&glyph->height); - int8_t xo = pgm_read_byte(&glyph->xOffset), - yo = pgm_read_byte(&glyph->yOffset); - uint8_t xx, yy, bits = 0, bit = 0; - int16_t xo16 = 0, yo16 = 0; - - digitalWrite(TFT_CS,LOW); - -#ifdef FAST_TEXT - uint16_t hpc = 0; // Horizontal foreground pixel count - for(yy=0; yy>= 1; - } - // Draw pixels for this line as we are about to increment yy - if (hpc) { - displayHline(x+xo+xx-hpc, y+yo+yy, hpc, color); - hpc=0; - } - checkCAT(); - } -#else - for(yy=0; yyfirst); - if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) { - GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); - ext += (uint8_t)pgm_read_byte(&glyph->xAdvance); - } - }//end of the while loop of the characters to be printed - return ext; + tft.drawCharGFX(x,y,c,color,bg,1); } void displayRawText(char *text, int x1, int y1, int color, int background){ - while(*text){ - char c = *text++; - - uint8_t first = pgm_read_byte(&gfxFont->first); - if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) { - - GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); - uint8_t w = pgm_read_byte(&glyph->width), - h = pgm_read_byte(&glyph->height); - if((w > 0) && (h > 0)) { // Is there an associated bitmap? - int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic - displayChar(x1, y1+TEXT_LINE_HEIGHT, c, color, background); - checkCAT(); - } - x1 += (uint8_t)pgm_read_byte(&glyph->xAdvance); - } - }//end of the while loop of the characters to be printed + tft.setTextColor(color,background); + tft.setCursor(x1,y1); + tft.print(text); } -// The generic routine to display one line on the LCD void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border) { - displayFillrect(x1, y1, w ,h, background); displayRect(x1, y1, w ,h, border); - x1 += (w - displayTextExtent(text))/2; - y1 += (h - TEXT_LINE_HEIGHT)/2; - while(*text){ - char c = *text++; - - uint8_t first = pgm_read_byte(&gfxFont->first); - if((c >= first) && (c <= (uint8_t)pgm_read_byte(&gfxFont->last))) { - - GFXglyph *glyph = pgm_read_glyph_ptr(gfxFont, c - first); - uint8_t w = pgm_read_byte(&glyph->width), - h = pgm_read_byte(&glyph->height); - if((w > 0) && (h > 0)) { // Is there an associated bitmap? - int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic - displayChar(x1, y1+TEXT_LINE_HEIGHT, c, color, background); - checkCAT(); - } - x1 += (uint8_t)pgm_read_byte(&glyph->xAdvance); - } - }//end of the while loop of the characters to be printed + int16_t x1_out; + int16_t y1_out; + uint16_t width_out; + uint16_t height_out; + tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out); + x1_out += (w - width_out)/2; + y1_out += 2*height_out + (h - height_out)/2; + displayRawText(text,x1_out,y1_out,color,background); } void setupTouch(){ diff --git a/nano_gui.h b/nano_gui.h index a66b1b0..efb163b 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -15,7 +15,6 @@ void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c void displayRect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c); void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c); void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg); -int displayTextExtent(char *text); void displayRawText(char *text, int x1, int y1, int color, int background); void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border); @@ -53,356 +52,4 @@ void scaleTouch(struct Point *p); #define BUTTON_CHECK #define BUTTON_SPINNER -/// Font data stored PER GLYPH -typedef struct { - uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap - uint8_t width; ///< Bitmap dimensions in pixels - uint8_t height; ///< Bitmap dimensions in pixels - uint8_t xAdvance; ///< Distance to advance cursor (x axis) - int8_t xOffset; ///< X dist from cursor pos to UL corner - int8_t yOffset; ///< Y dist from cursor pos to UL corner -} GFXglyph; - -/// Data stored for FONT AS A WHOLE -typedef struct { - uint8_t *bitmap; ///< Glyph bitmaps, concatenated - GFXglyph *glyph; ///< Glyph array - uint8_t first; ///< ASCII extents (first char) - uint8_t last; ///< ASCII extents (last char) - uint8_t yAdvance; ///< Newline distance (y axis) -} GFXfont; - -const uint8_t ubitxBitmaps[] PROGMEM = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0xFF, 0xE0, 0xF3, 0xF9, 0xFC, 0xFE, 0x7E, - 0x3B, 0x1D, 0x84, 0x0E, 0x70, 0x73, 0x83, 0x9C, 0x18, 0xC7, 0xFF, 0xBF, - 0xFD, 0xFF, 0xE3, 0x9C, 0x18, 0xC0, 0xC6, 0x0E, 0x7D, 0xFF, 0xEF, 0xFF, - 0x18, 0xC0, 0xC6, 0x0E, 0x70, 0x73, 0x83, 0x9C, 0x00, 0x04, 0x01, 0xF8, - 0x7F, 0xCF, 0xDE, 0xE4, 0xEE, 0x4E, 0xE4, 0x0F, 0x40, 0x7E, 0x03, 0xFC, - 0x0F, 0xE0, 0x5E, 0x04, 0xFE, 0x4F, 0xE4, 0xFF, 0x4E, 0x7F, 0xE3, 0xFC, - 0x04, 0x00, 0x40, 0x04, 0x00, 0x3C, 0x06, 0x07, 0xE0, 0x60, 0xFF, 0x0C, - 0x0C, 0x30, 0x80, 0xC3, 0x18, 0x0C, 0x31, 0x00, 0xFF, 0x30, 0x07, 0xE6, - 0x00, 0x3C, 0x60, 0x00, 0x0C, 0x7C, 0x00, 0xCF, 0xE0, 0x19, 0xC6, 0x01, - 0x98, 0x70, 0x31, 0x87, 0x03, 0x1C, 0x60, 0x60, 0xFE, 0x04, 0x07, 0xC0, - 0x0F, 0x80, 0x1F, 0xC0, 0x3D, 0xE0, 0x38, 0xE0, 0x3C, 0xE0, 0x1D, 0xC0, - 0x1F, 0xC0, 0x0F, 0x00, 0x3F, 0x8C, 0x7B, 0xDC, 0x71, 0xDC, 0xF1, 0xFC, - 0xF0, 0xF8, 0xF0, 0x78, 0x79, 0xFC, 0x7F, 0xFC, 0x3F, 0x9E, 0x00, 0x00, - 0xFF, 0xFF, 0xE6, 0x60, 0x0C, 0x71, 0x8E, 0x31, 0xC7, 0x38, 0xE3, 0x8E, - 0x38, 0xE3, 0x8E, 0x38, 0x71, 0xC7, 0x0E, 0x38, 0x70, 0xC0, 0xC3, 0x86, - 0x1C, 0x70, 0xE3, 0x8E, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xCE, 0x38, 0xE7, - 0x1C, 0x63, 0x8C, 0x00, 0x10, 0x10, 0x10, 0xFE, 0x7C, 0x38, 0x6C, 0x44, - 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x60, - 0x06, 0x00, 0x60, 0x06, 0x00, 0xFF, 0xF2, 0xFE, 0xFF, 0xFF, 0xC0, 0xFF, - 0xF0, 0x04, 0x08, 0x30, 0x60, 0x83, 0x06, 0x08, 0x10, 0x60, 0xC1, 0x06, - 0x0C, 0x10, 0x20, 0xC0, 0x3F, 0x8F, 0xF9, 0xEF, 0x78, 0xFE, 0x0F, 0xC1, - 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xE3, 0xDE, - 0xF3, 0xFE, 0x3F, 0x80, 0x80, 0x06, 0x1C, 0x7F, 0xFF, 0xE1, 0xC3, 0x87, - 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x3F, 0x8F, 0xFB, 0xEF, - 0xF8, 0x7E, 0x0F, 0xC1, 0xC0, 0x38, 0x0F, 0x03, 0xC0, 0xF0, 0x7C, 0x1F, - 0x07, 0x80, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0x8F, 0xFB, 0xCF, - 0xF0, 0xFE, 0x1E, 0x03, 0xC0, 0x70, 0x7C, 0x0F, 0xC0, 0xFC, 0x03, 0x80, - 0x7E, 0x0F, 0xC1, 0xFC, 0xFB, 0xFE, 0x3F, 0x80, 0x80, 0x07, 0xC0, 0x7C, - 0x0F, 0xC0, 0xFC, 0x1F, 0xC3, 0xBC, 0x33, 0xC7, 0x3C, 0x63, 0xCE, 0x3C, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3F, - 0xEF, 0xFD, 0xFF, 0xB8, 0x06, 0x00, 0xC0, 0x1F, 0xE7, 0xFE, 0xF1, 0xE0, - 0x1C, 0x03, 0x80, 0x70, 0x0F, 0xC1, 0xFC, 0xFB, 0xFE, 0x3F, 0x80, 0x80, - 0x1F, 0x87, 0xF9, 0xE7, 0xB8, 0x7E, 0x01, 0xC0, 0x3B, 0xE7, 0xFE, 0xFB, - 0xFE, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xE1, 0xDE, 0xFB, 0xFE, 0x3F, 0x80, - 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0E, 0x01, 0xC0, 0x3C, 0x03, 0x80, - 0x70, 0x0F, 0x00, 0xE0, 0x0E, 0x01, 0xE0, 0x1C, 0x01, 0xC0, 0x1C, 0x03, - 0xC0, 0x3C, 0x00, 0x3F, 0x87, 0xFC, 0xF9, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, - 0x71, 0xC3, 0xF8, 0x7F, 0xCF, 0x1E, 0xE0, 0xEE, 0x0F, 0xE0, 0xFE, 0x0E, - 0xF1, 0xE7, 0xFC, 0x3F, 0x80, 0x40, 0x3F, 0x0F, 0xFB, 0xEF, 0x70, 0xFE, - 0x0F, 0xC1, 0xF8, 0x3F, 0x0F, 0xF3, 0xEF, 0xFC, 0xFB, 0x80, 0x70, 0x0F, - 0xC3, 0xFE, 0xF3, 0xFE, 0x3F, 0x80, 0x80, 0xFF, 0x80, 0x00, 0xFF, 0xF0, - 0xFF, 0x80, 0x00, 0xFF, 0xF2, 0xDE, 0x00, 0x70, 0x1F, 0x0F, 0xE7, 0xF0, - 0xF8, 0x0E, 0x00, 0xFC, 0x03, 0xF8, 0x0F, 0xE0, 0x1F, 0x00, 0x30, 0xFF, - 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0xC0, 0x0F, 0x80, 0x7F, 0x00, 0xFC, 0x03, 0xF0, 0x07, 0x03, 0xF1, - 0xFC, 0xFE, 0x0F, 0x80, 0xC0, 0x00, 0x1F, 0x0F, 0xF3, 0xFF, 0x78, 0xFE, - 0x0F, 0xC1, 0xC0, 0x38, 0x0F, 0x03, 0xE0, 0xF8, 0x3C, 0x07, 0x00, 0xE0, - 0x00, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xFE, - 0x00, 0xF0, 0x3C, 0x07, 0x00, 0x38, 0x38, 0x00, 0x30, 0xC0, 0x00, 0xE6, - 0x0F, 0xF1, 0x98, 0x73, 0xC7, 0xC3, 0x87, 0x0F, 0x0C, 0x1C, 0x3C, 0x30, - 0x61, 0xF1, 0xC1, 0x86, 0xC7, 0x0E, 0x1B, 0x1C, 0x38, 0xEC, 0x3B, 0xEF, - 0x38, 0xFD, 0xF8, 0x70, 0xC1, 0x80, 0xE0, 0x00, 0x01, 0xC0, 0x10, 0x03, - 0xFF, 0xC0, 0x03, 0xFF, 0x00, 0x03, 0xC0, 0x07, 0xC0, 0x07, 0xE0, 0x07, - 0xE0, 0x0F, 0xE0, 0x0E, 0xF0, 0x0E, 0xF0, 0x1E, 0x70, 0x1C, 0x78, 0x1C, - 0x78, 0x3C, 0x38, 0x3F, 0xFC, 0x3F, 0xFC, 0x7F, 0xFC, 0x70, 0x1E, 0xF0, - 0x1E, 0xF0, 0x0E, 0xE0, 0x0F, 0xFF, 0x03, 0xFF, 0xCF, 0xFF, 0xBC, 0x7E, - 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBF, 0xFE, 0xFF, 0xE3, 0xFF, 0xCF, 0x0F, - 0xBC, 0x0F, 0xF0, 0x1F, 0xC0, 0xFF, 0x03, 0xFF, 0xFE, 0xFF, 0xFB, 0xFF, - 0x80, 0x03, 0xC0, 0x1F, 0xF0, 0xFF, 0xF1, 0xF1, 0xE7, 0x81, 0xEF, 0x01, - 0xFC, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F, - 0x00, 0xEF, 0x01, 0xDE, 0x07, 0x9F, 0xFE, 0x1F, 0xFC, 0x1F, 0xE0, 0x04, - 0x00, 0xFE, 0x03, 0xFF, 0x8F, 0xFF, 0x38, 0x7E, 0xE0, 0x7B, 0x80, 0xFE, - 0x03, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x3F, - 0x80, 0xFE, 0x07, 0xBF, 0xFE, 0xFF, 0xF3, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1F, 0xFE, 0xFF, 0xF7, - 0xFF, 0xBC, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1F, 0xFF, 0xFF, - 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xE0, 0x0E, 0x00, - 0xE0, 0x0F, 0xFE, 0xFF, 0xEF, 0xFE, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, - 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x03, 0xE0, 0x0F, 0xF8, 0x1F, 0xFC, - 0x3E, 0x3E, 0x78, 0x0F, 0x70, 0x0F, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, - 0xF0, 0x7F, 0xF0, 0x7F, 0xF0, 0x7F, 0xF0, 0x07, 0x78, 0x0F, 0x7C, 0x1F, - 0x3F, 0xFF, 0x1F, 0xFB, 0x0F, 0xF3, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, - 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, - 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0xE0, 0x3C, - 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, - 0x80, 0xFE, 0x1F, 0xC3, 0xF8, 0x7F, 0xFE, 0xFF, 0xCF, 0xF0, 0x00, 0x00, - 0xE0, 0x3D, 0xC0, 0xFB, 0x83, 0xE7, 0x07, 0x8E, 0x1E, 0x1C, 0x78, 0x39, - 0xE0, 0x77, 0x80, 0xFF, 0x01, 0xFF, 0x03, 0xFE, 0x07, 0x9E, 0x0E, 0x1E, - 0x1C, 0x1E, 0x38, 0x3C, 0x70, 0x3C, 0xE0, 0x3D, 0xC0, 0x3C, 0xF0, 0x0F, - 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, - 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, - 0xFF, 0xF8, 0x1F, 0xFC, 0x0F, 0xFE, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, - 0xE1, 0xFF, 0xB0, 0xFF, 0xDC, 0x6F, 0xEE, 0x77, 0xF7, 0x3B, 0xF9, 0x9D, - 0xFC, 0xCC, 0xFE, 0x76, 0x7F, 0x3F, 0x3F, 0x8F, 0x9F, 0xC7, 0xCF, 0xE3, - 0xC7, 0xF1, 0xE3, 0xC0, 0xE0, 0x3F, 0xC0, 0xFF, 0x03, 0xFE, 0x0F, 0xFC, - 0x3F, 0xF0, 0xFE, 0xE3, 0xFB, 0x8F, 0xE7, 0x3F, 0x9E, 0xFE, 0x3B, 0xF8, - 0xFF, 0xE1, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x1F, 0xE0, 0x7F, 0x80, 0xF0, - 0x03, 0xE0, 0x07, 0xFC, 0x07, 0xFF, 0x07, 0xCF, 0xC7, 0x81, 0xF3, 0xC0, - 0x7B, 0xC0, 0x1D, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE, - 0x00, 0xFF, 0x00, 0x73, 0xC0, 0x79, 0xF0, 0x7C, 0x7F, 0xFC, 0x1F, 0xFC, - 0x07, 0xFC, 0x00, 0x20, 0x00, 0xFF, 0x07, 0xFF, 0x3F, 0xFD, 0xC3, 0xFE, - 0x07, 0xF0, 0x1F, 0x80, 0xFC, 0x0F, 0xE0, 0xFF, 0xFF, 0xBF, 0xF9, 0xFF, - 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x03, - 0xE0, 0x07, 0xFC, 0x07, 0xFF, 0x07, 0xCF, 0xC7, 0x80, 0xF3, 0xC0, 0x7B, - 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE, 0x04, - 0xFF, 0x07, 0x73, 0xC3, 0xF9, 0xF0, 0xFC, 0x7F, 0xFC, 0x1F, 0xFF, 0x07, - 0xFF, 0xC0, 0x20, 0xC0, 0xFF, 0x83, 0xFF, 0xCF, 0xFF, 0xBC, 0x3F, 0xF0, - 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xFF, 0xFB, 0xFF, 0x8F, 0xFF, 0xBC, - 0x1E, 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBC, 0x0E, 0xF0, 0x3F, 0xC0, 0xF0, - 0x0F, 0x80, 0xFF, 0xC7, 0xFF, 0xBE, 0x1E, 0xF0, 0x3B, 0xC0, 0xFF, 0x00, - 0x3F, 0x80, 0x7F, 0xE0, 0xFF, 0xE0, 0x3F, 0xC0, 0x0F, 0x00, 0x1F, 0x80, - 0x7F, 0x03, 0xFF, 0x1F, 0x7F, 0xF8, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, - 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, - 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, - 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, - 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0xC0, 0xFF, 0x07, 0x9F, 0xFE, 0x7F, 0xF0, - 0x7F, 0x80, 0x20, 0x00, 0xE0, 0x1F, 0xC0, 0x3B, 0xC0, 0xF3, 0x81, 0xE7, - 0x03, 0x8F, 0x0F, 0x0E, 0x1C, 0x1C, 0x38, 0x3C, 0x70, 0x39, 0xC0, 0x73, - 0x80, 0xE7, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x03, 0xC0, 0x07, 0x80, - 0x0F, 0x00, 0xF0, 0x38, 0x1D, 0xC1, 0xE0, 0xF7, 0x87, 0xC3, 0xDE, 0x1F, - 0x0F, 0x78, 0x7C, 0x38, 0xE3, 0xB0, 0xE3, 0x8E, 0xC7, 0x8F, 0x3B, 0x9C, - 0x1C, 0xEE, 0x70, 0x73, 0x39, 0xC1, 0xDC, 0x67, 0x07, 0x71, 0xB8, 0x0F, - 0xC7, 0xE0, 0x3E, 0x1F, 0x80, 0xF8, 0x3E, 0x01, 0xE0, 0xF0, 0x07, 0x83, - 0xC0, 0x1E, 0x0F, 0x00, 0xF0, 0x3D, 0xF0, 0x79, 0xE1, 0xE1, 0xE3, 0xC3, - 0xCF, 0x03, 0xFC, 0x07, 0xF8, 0x07, 0xE0, 0x07, 0x80, 0x0F, 0x00, 0x3F, - 0x00, 0x7F, 0x01, 0xFE, 0x07, 0x9E, 0x0F, 0x3C, 0x3C, 0x3C, 0xF8, 0x3D, - 0xE0, 0x78, 0xF0, 0x1F, 0xE0, 0x79, 0xE0, 0xF3, 0xC3, 0xC3, 0xC7, 0x87, - 0x9E, 0x07, 0x3C, 0x0F, 0x70, 0x0F, 0xE0, 0x1F, 0x80, 0x1F, 0x00, 0x3C, - 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x80, - 0x78, 0x07, 0x80, 0x78, 0x07, 0x80, 0x7C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, - 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xCE, 0x73, 0x9C, 0xE7, - 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCF, 0xFF, 0xE0, 0xC1, 0x81, 0x02, - 0x06, 0x04, 0x08, 0x18, 0x30, 0x20, 0x60, 0xC0, 0x81, 0x83, 0x02, 0x06, - 0xFF, 0xFF, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, - 0x1C, 0x71, 0xC7, 0xFF, 0xFF, 0xC0, 0x0F, 0x00, 0xF0, 0x0F, 0x01, 0xF8, - 0x1B, 0x83, 0x9C, 0x39, 0xC3, 0x0C, 0x70, 0xE7, 0x0E, 0xE0, 0x70, 0xFF, - 0xFF, 0xFF, 0xFC, 0x71, 0x86, 0x3F, 0x87, 0xFC, 0xFF, 0xEE, 0x1E, 0x01, - 0xE0, 0xFE, 0x7F, 0xEF, 0x8E, 0xE1, 0xEE, 0x1E, 0xF3, 0xEF, 0xFE, 0x7E, - 0xE1, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x7B, 0xE3, - 0xFF, 0x9F, 0xFE, 0xF8, 0xF7, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, - 0x3F, 0xC1, 0xDF, 0x9E, 0xFF, 0xE7, 0xFE, 0x00, 0x40, 0x1F, 0x83, 0xFC, - 0x7F, 0xEF, 0x0E, 0xE0, 0xEE, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0x0E, - 0x79, 0xE7, 0xFC, 0x3F, 0x80, 0x00, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, - 0x00, 0x71, 0xE7, 0x3F, 0xF7, 0xFF, 0xF0, 0xFE, 0x0F, 0xE0, 0x7E, 0x07, - 0xE0, 0x7E, 0x0F, 0xF0, 0xF7, 0x9F, 0x7F, 0xF3, 0xF7, 0x00, 0x00, 0x1F, - 0x07, 0xFC, 0x7B, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE, 0xFF, 0xFF, 0xFF, 0xE0, - 0x0E, 0x0E, 0xF1, 0xE7, 0xFC, 0x3F, 0x80, 0x40, 0x00, 0x1E, 0x3E, 0x3C, - 0x3C, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x1E, 0x73, 0xF7, 0x7F, 0xFF, 0x0F, 0xF0, 0xFE, 0x07, 0xE0, - 0x7E, 0x07, 0xE0, 0x7F, 0x0F, 0x79, 0xF7, 0xFF, 0x3F, 0x70, 0x07, 0x00, - 0x7F, 0x0F, 0x7F, 0xE3, 0xFC, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, - 0xDF, 0x3F, 0xF7, 0xFF, 0xF1, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, - 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1C, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFC, 0x39, 0xCE, 0x70, 0x1C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, - 0xCE, 0x7F, 0xFF, 0xC0, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, - 0x0E, 0xF1, 0xEF, 0x3C, 0xF7, 0x8F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x8F, - 0x3C, 0xF3, 0xCF, 0x1E, 0xF1, 0xEF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF7, 0xCF, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0xF8, 0x78, 0xFF, - 0x0E, 0x1F, 0xE1, 0xC3, 0xFC, 0x38, 0x7F, 0x87, 0x0F, 0xF0, 0xE1, 0xFE, - 0x1C, 0x3F, 0xC3, 0x87, 0xF8, 0x70, 0xFF, 0x0E, 0x1E, 0xEF, 0x9F, 0xFB, - 0xFF, 0xF8, 0xFE, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, - 0xF0, 0x7E, 0x0E, 0x1F, 0x81, 0xFF, 0x1F, 0xFD, 0xE1, 0xEF, 0x07, 0x70, - 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x83, 0x9E, 0x3C, 0xFF, 0xC3, 0xFC, - 0x01, 0x00, 0xF7, 0xC7, 0xFF, 0x3F, 0xFD, 0xF1, 0xEF, 0x07, 0xF8, 0x3F, - 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xBE, 0x3D, 0xFF, 0xCF, 0x7C, 0x78, - 0x83, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x00, 0x1E, 0x77, 0xF7, 0x7F, - 0xFF, 0x0F, 0xE0, 0xFE, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0xFF, 0x0F, 0xF9, - 0xF7, 0xFF, 0x3F, 0x70, 0x47, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0xEF, - 0xFF, 0xFF, 0x8E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x00, 0x3F, - 0x8F, 0xFB, 0xEF, 0xF8, 0x7F, 0x01, 0xFE, 0x1F, 0xF0, 0xFF, 0x01, 0xFC, - 0x1F, 0xC3, 0xFF, 0xF7, 0xFC, 0x08, 0x00, 0x38, 0x70, 0xE7, 0xFF, 0xFF, - 0xCE, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0F, 0x8F, 0x04, 0xF0, 0x7F, - 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, - 0x0F, 0x79, 0xF7, 0xFF, 0x3F, 0x70, 0x80, 0xF0, 0x7B, 0x83, 0x9E, 0x1C, - 0x71, 0xE3, 0x8E, 0x1E, 0x70, 0x73, 0x83, 0xB8, 0x1D, 0xC0, 0x7E, 0x03, - 0xE0, 0x1F, 0x00, 0x78, 0x00, 0xF0, 0xE1, 0xDC, 0x78, 0x77, 0x1F, 0x3D, - 0xC7, 0xCE, 0x79, 0xF3, 0x8E, 0xEC, 0xE3, 0xBB, 0x78, 0xEC, 0xFC, 0x1F, - 0x3F, 0x07, 0xCF, 0xC1, 0xF1, 0xE0, 0x7C, 0x78, 0x0E, 0x1E, 0x00, 0x78, - 0xF3, 0xC7, 0x8F, 0x78, 0x3B, 0x81, 0xFC, 0x07, 0xC0, 0x1E, 0x01, 0xF0, - 0x1F, 0xC0, 0xEF, 0x0F, 0x78, 0xF1, 0xE7, 0x87, 0x80, 0xF0, 0x7B, 0x83, - 0x9E, 0x1C, 0xF1, 0xE3, 0x8E, 0x1E, 0x70, 0x73, 0x83, 0xB8, 0x1D, 0xC0, - 0x7E, 0x03, 0xE0, 0x1F, 0x00, 0x78, 0x03, 0x80, 0x1C, 0x01, 0xE0, 0x3E, - 0x01, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x1E, 0x0F, 0x83, 0xC1, 0xE0, - 0xF0, 0x78, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0x3C, 0xF9, 0xC3, - 0x87, 0x0E, 0x1C, 0x38, 0x73, 0xC7, 0x0F, 0x07, 0x0E, 0x1C, 0x38, 0x70, - 0xE1, 0xC3, 0xE7, 0xC7, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xC3, - 0xCF, 0x0C, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0xC7, 0x3C, 0xE3, 0x8E, 0x38, - 0xE3, 0x8E, 0xF3, 0xCE, 0x00, 0x10, 0x0F, 0x85, 0xBD, 0xE1, 0xF0, 0x08, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0 }; - -const GFXglyph ubitxGlyphs[] PROGMEM = { - { 0, 13, 18, 17, 2, -17 }, // 0x14 - { 30, 13, 18, 17, 2, -17 }, // 0x15 - { 60, 13, 18, 17, 2, -17 }, // 0x16 - { 90, 13, 18, 17, 2, -17 }, // 0x17 - { 120, 13, 18, 17, 2, -17 }, // 0x18 - { 150, 13, 18, 17, 2, -17 }, // 0x19 - { 180, 13, 18, 17, 2, -17 }, // 0x1A - { 210, 13, 18, 17, 2, -17 }, // 0x1B - { 240, 13, 18, 17, 2, -17 }, // 0x1C - { 270, 13, 18, 17, 2, -17 }, // 0x1D - { 300, 13, 18, 17, 2, -17 }, // 0x1E - { 330, 13, 18, 17, 2, -17 }, // 0x1F - { 360, 0, 0, 7, 0, 1 }, // 0x20 ' ' - { 360, 3, 17, 8, 3, -16 }, // 0x21 '!' - { 367, 9, 7, 11, 1, -17 }, // 0x22 '"' - { 375, 13, 18, 13, 0, -16 }, // 0x23 '#' - { 405, 12, 21, 13, 1, -17 }, // 0x24 '$' - { 437, 20, 17, 21, 1, -16 }, // 0x25 '%' - { 480, 16, 18, 17, 1, -16 }, // 0x26 '&' - { 516, 4, 7, 6, 1, -17 }, // 0x27 ''' - { 520, 6, 23, 8, 1, -17 }, // 0x28 '(' - { 538, 6, 23, 8, 1, -17 }, // 0x29 ')' - { 556, 8, 8, 9, 1, -17 }, // 0x2A '*' - { 564, 12, 11, 14, 1, -10 }, // 0x2B '+' - { 581, 3, 8, 7, 2, -3 }, // 0x2C ',' - { 584, 6, 3, 8, 1, -7 }, // 0x2D '-' - { 587, 3, 4, 7, 2, -3 }, // 0x2E '.' - { 589, 7, 17, 7, 0, -16 }, // 0x2F '/' - { 604, 11, 18, 13, 1, -16 }, // 0x30 '0' - { 629, 7, 17, 13, 2, -16 }, // 0x31 '1' - { 644, 11, 17, 13, 1, -16 }, // 0x32 '2' - { 668, 11, 18, 13, 1, -16 }, // 0x33 '3' - { 693, 12, 17, 13, 1, -16 }, // 0x34 '4' - { 719, 11, 18, 13, 1, -16 }, // 0x35 '5' - { 744, 11, 18, 13, 1, -16 }, // 0x36 '6' - { 769, 12, 17, 13, 1, -16 }, // 0x37 '7' - { 795, 12, 18, 13, 1, -16 }, // 0x38 '8' - { 822, 11, 18, 13, 1, -16 }, // 0x39 '9' - { 847, 3, 12, 8, 3, -11 }, // 0x3A ':' - { 852, 3, 16, 8, 3, -11 }, // 0x3B ';' - { 858, 12, 11, 14, 1, -10 }, // 0x3C '<' - { 875, 12, 9, 14, 1, -9 }, // 0x3D '=' - { 889, 12, 11, 14, 1, -10 }, // 0x3E '>' - { 906, 11, 18, 15, 2, -17 }, // 0x3F '?' - { 931, 22, 21, 23, 1, -17 }, // 0x40 '@' - { 989, 16, 18, 17, 1, -17 }, // 0x41 'A' - { 1025, 14, 18, 17, 2, -17 }, // 0x42 'B' - { 1057, 15, 19, 17, 1, -17 }, // 0x43 'C' - { 1093, 14, 18, 17, 2, -17 }, // 0x44 'D' - { 1125, 13, 18, 16, 2, -17 }, // 0x45 'E' - { 1155, 12, 18, 15, 2, -17 }, // 0x46 'F' - { 1182, 16, 18, 19, 1, -17 }, // 0x47 'G' - { 1218, 14, 18, 17, 2, -17 }, // 0x48 'H' - { 1250, 3, 18, 7, 2, -17 }, // 0x49 'I' - { 1257, 11, 19, 13, 1, -17 }, // 0x4A 'J' - { 1284, 15, 18, 17, 2, -17 }, // 0x4B 'K' - { 1318, 12, 18, 15, 2, -17 }, // 0x4C 'L' - { 1345, 17, 18, 20, 2, -17 }, // 0x4D 'M' - { 1384, 14, 18, 17, 2, -17 }, // 0x4E 'N' - { 1416, 17, 19, 19, 1, -17 }, // 0x4F 'O' - { 1457, 13, 18, 16, 2, -17 }, // 0x50 'P' - { 1487, 17, 19, 19, 1, -17 }, // 0x51 'Q' - { 1528, 14, 18, 17, 2, -17 }, // 0x52 'R' - { 1560, 14, 19, 16, 1, -17 }, // 0x53 'S' - { 1594, 14, 18, 15, 0, -17 }, // 0x54 'T' - { 1626, 14, 19, 17, 2, -17 }, // 0x55 'U' - { 1660, 15, 18, 16, 1, -17 }, // 0x56 'V' - { 1694, 22, 18, 23, 0, -17 }, // 0x57 'W' - { 1744, 15, 18, 16, 1, -17 }, // 0x58 'X' - { 1778, 15, 18, 16, 1, -17 }, // 0x59 'Y' - { 1812, 13, 18, 15, 1, -17 }, // 0x5A 'Z' - { 1842, 5, 23, 8, 2, -17 }, // 0x5B '[' - { 1857, 7, 17, 7, 0, -16 }, // 0x5C '\' - { 1872, 6, 23, 8, 0, -17 }, // 0x5D ']' - { 1890, 12, 11, 14, 1, -16 }, // 0x5E '^' - { 1907, 15, 2, 13, -1, 4 }, // 0x5F '_' - { 1911, 5, 3, 8, 0, -17 }, // 0x60 '`' - { 1913, 12, 14, 13, 1, -12 }, // 0x61 'a' - { 1934, 13, 19, 15, 1, -17 }, // 0x62 'b' - { 1965, 12, 14, 13, 1, -12 }, // 0x63 'c' - { 1986, 12, 19, 15, 1, -17 }, // 0x64 'd' - { 2015, 12, 14, 13, 1, -12 }, // 0x65 'e' - { 2036, 8, 18, 8, 0, -17 }, // 0x66 'f' - { 2054, 12, 18, 15, 1, -12 }, // 0x67 'g' - { 2081, 11, 18, 15, 2, -17 }, // 0x68 'h' - { 2106, 3, 18, 7, 2, -17 }, // 0x69 'i' - { 2113, 5, 23, 7, 0, -17 }, // 0x6A 'j' - { 2128, 12, 18, 13, 1, -17 }, // 0x6B 'k' - { 2155, 3, 18, 7, 2, -17 }, // 0x6C 'l' - { 2162, 19, 13, 21, 1, -12 }, // 0x6D 'm' - { 2193, 11, 13, 15, 2, -12 }, // 0x6E 'n' - { 2211, 13, 14, 15, 1, -12 }, // 0x6F 'o' - { 2234, 13, 18, 15, 1, -12 }, // 0x70 'p' - { 2264, 12, 18, 15, 1, -12 }, // 0x71 'q' - { 2291, 7, 13, 9, 2, -12 }, // 0x72 'r' - { 2303, 11, 14, 13, 1, -12 }, // 0x73 's' - { 2323, 7, 17, 8, 0, -15 }, // 0x74 't' - { 2338, 12, 14, 15, 1, -12 }, // 0x75 'u' - { 2359, 13, 13, 13, 0, -12 }, // 0x76 'v' - { 2381, 18, 13, 19, 0, -12 }, // 0x77 'w' - { 2411, 13, 13, 13, 0, -12 }, // 0x78 'x' - { 2433, 13, 18, 13, 0, -12 }, // 0x79 'y' - { 2463, 10, 13, 12, 1, -12 }, // 0x7A 'z' - { 2480, 7, 23, 9, 1, -17 }, // 0x7B '{' - { 2501, 2, 23, 7, 2, -17 }, // 0x7C '|' - { 2507, 6, 23, 9, 2, -17 }, // 0x7D '}' - { 2525, 11, 5, 14, 1, -7 }, // 0x7E '~' - { 2532, 13, 18, 17, 2, -17 } }; // 0x7F - -const GFXfont ubitx_font PROGMEM = { - (uint8_t *)ubitxBitmaps, - (GFXglyph *)ubitxGlyphs, - 0x14, 0x7F, 33 }; - -// Approx. 3325 bytes - #endif // _NANO_GUI_H_ From 6eed9a40c1dc74c988ee5d723911bca86c8b5c87 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 31 Dec 2019 18:46:31 -0800 Subject: [PATCH 003/324] Fix text alignment --- nano_gui.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index 01dd3be..00ac5b5 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -210,9 +210,9 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr uint16_t width_out; uint16_t height_out; tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out); - x1_out += (w - width_out)/2; - y1_out += 2*height_out + (h - height_out)/2; - displayRawText(text,x1_out,y1_out,color,background); + x1 += (w - ( width_out + (x1_out-x1)))/2; + y1 += h - (h - height_out)/2; + displayRawText(text,x1,y1,color,background); } void setupTouch(){ From 2345b34c1a04d60910d74899e54462ebd2fd0741 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 31 Dec 2019 18:47:08 -0800 Subject: [PATCH 004/324] Render CW text using normal routine --- ubitx_ui.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 1f27322..c468e79 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -4,14 +4,6 @@ #include "ubitx.h" #include "nano_gui.h" -/** - * The user interface of the ubitx consists of the encoder, the push-button on top of it - * and the 16x2 LCD display. - * The upper line of the display is constantly used to display frequency and status - * of the radio. Occasionally, it is used to provide a two-line information that is - * quickly cleared up. - */ - #define BUTTON_SELECTED 1 struct Button { @@ -405,16 +397,15 @@ void enterFreq(){ } void drawCWStatus(){ - displayFillrect(0, 201, 320, 39, DISPLAY_NAVY); - strcpy(b, " cw:"); - int wpm = 1200/cwSpeed; + strcpy(b, " cw: "); + int wpm = 1200/cwSpeed; itoa(wpm,c, 10); strcat(b, c); strcat(b, "wpm, "); itoa(sideTone, c, 10); strcat(b, c); strcat(b, "hz"); - displayRawText(b, 0, 201, DISPLAY_CYAN, DISPLAY_NAVY); + displayText(b, 0, 201, 320, 39, DISPLAY_CYAN, DISPLAY_NAVY, DISPLAY_NAVY); } From 042adee42c6bdde352ca245cf386af628fb58157 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 10:18:06 -0800 Subject: [PATCH 005/324] Clean up duplicated text/defines --- ubitx.h | 7 +--- ubitx_v6.3.1_code.ino | 90 +------------------------------------------ 2 files changed, 2 insertions(+), 95 deletions(-) diff --git a/ubitx.h b/ubitx.h index 4304650..32ec2b9 100644 --- a/ubitx.h +++ b/ubitx.h @@ -43,11 +43,6 @@ it uses an ILI9341 display controller and an XPT2046 touch controller. #define TFT_DC 9 #define TFT_CS 10 #define CS_PIN 8 //this is the pin to select the touch controller on spi interface -// MOSI=11, MISO=12, SCK=13 - -//XPT2046_Touchscreen ts(CS_PIN); - -//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); /** * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. @@ -60,7 +55,7 @@ it uses an ILI9341 display controller and an XPT2046 touch controller. * the input and output from the USB port. We must keep a count of the bytes used while reading * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. */ -extern char c[30], b[30]; +extern char c[30], b[30]; extern char printBuff[2][20]; //mirrors what is showing on the two lines of the display extern int count; //to generally count ticks, loops, etc diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 4d162c4..d2518d1 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -45,74 +45,6 @@ code). Here are some defines and declarations used by Jerry's routines: */ - -/** - * We need to carefully pick assignment of pin for various purposes. - * There are two sets of completely programmable pins on the Raduino. - * First, on the top of the board, in line with the LCD connector is an 8-pin connector - * that is largely meant for analog inputs and front-panel control. It has a regulated 5v output, - * ground and six pins. Each of these six pins can be individually programmed - * either as an analog input, a digital input or a digital output. - * The pins are assigned as follows (left to right, display facing you): - * Pin 1 (Violet), A7, SPARE - * Pin 2 (Blue), A6, KEYER (DATA) - * Pin 3 (Green), +5v - * Pin 4 (Yellow), Gnd - * Pin 5 (Orange), A3, PTT - * Pin 6 (Red), A2, F BUTTON - * Pin 7 (Brown), A1, ENC B - * Pin 8 (Black), A0, ENC A - *Note: A5, A4 are wired to the Si5351 as I2C interface - * * - * Though, this can be assigned anyway, for this application of the Arduino, we will make the following - * assignment - * A2 will connect to the PTT line, which is the usually a part of the mic connector - * A3 is connected to a push button that can momentarily ground this line. This will be used for RIT/Bandswitching, etc. - * A6 is to implement a keyer, it is reserved and not yet implemented - * A7 is connected to a center pin of good quality 100K or 10K linear potentiometer with the two other ends connected to - * ground and +5v lines available on the connector. This implments the tuning mechanism - */ - -#define ENC_A (A0) -#define ENC_B (A1) -#define FBUTTON (A2) -#define PTT (A3) -#define ANALOG_KEYER (A6) -#define ANALOG_SPARE (A7) - - -/** pin assignments -14 T_IRQ 2 std changed -13 T_DOUT (parallel to SOD/MOSI, pin 9 of display) -12 T_DIN (parallel to SDI/MISO, pin 6 of display) -11 T_CS 9 (we need to specify this) -10 T_CLK (parallel to SCK, pin 7 of display) -9 SDO(MSIO) 12 12 (spi) -8 LED A0 8 (not needed, permanently on +3.3v) (resistor from 5v, -7 SCK 13 13 (spi) -6 SDI 11 11 (spi) -5 D/C A3 7 (changable) -4 RESET A4 9 (not needed, permanently +5v) -3 CS A5 10 (changable) -2 GND GND -1 VCC VCC - -The model is called tjctm24028-spi -it uses an ILI9341 display controller and an XPT2046 touch controller. -*/ - -#define TFT_DC 9 -#define TFT_CS 10 - -//#define TIRQ_PIN 2 -#define CS_PIN 8 - -// MOSI=11, MISO=12, SCK=13 - -//XPT2046_Touchscreen ts(CS_PIN); - -//Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC); - /** * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. * We have to be very careful with variables that are declared inside the functions as they are @@ -124,26 +56,7 @@ it uses an ILI9341 display controller and an XPT2046 touch controller. * the input and output from the USB port. We must keep a count of the bytes used while reading * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. */ -char c[30], b[30]; -char printBuff[2][20]; //mirrors what is showing on the two lines of the display -int count = 0; //to generally count ticks, loops, etc - -/** - * The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig. - * This assignment is as follows : - * Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - * GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7 - * These too are flexible with what you may do with them, for the Raduino, we use them to : - * - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer - * - CW_KEY line : turns on the carrier for CW - */ - -#define TX_RX (7) -#define CW_TONE (6) -#define TX_LPF_A (5) -#define TX_LPF_B (4) -#define TX_LPF_C (3) -#define CW_KEY (2) +char c[30], b[30]; /** * These are the indices where these user changable settinngs are stored in the EEPROM @@ -193,7 +106,6 @@ int count = 0; //to generally count ticks, loops, etc * 12 MHz where its fifth harmonic beats with the arduino's 16 Mhz oscillator's fourth harmonic */ - #define INIT_USB_FREQ (11059200l) // limits the tuning and working range of the ubitx between 3 MHz and 30 MHz #define LOWEST_FREQ (100000l) From ee5b3f4ce344842e8ffa848662218e9f3c4b40aa Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 11:42:44 -0800 Subject: [PATCH 006/324] Remove unused extern --- ubitx.h | 1 - 1 file changed, 1 deletion(-) diff --git a/ubitx.h b/ubitx.h index 32ec2b9..10fdc63 100644 --- a/ubitx.h +++ b/ubitx.h @@ -57,7 +57,6 @@ it uses an ILI9341 display controller and an XPT2046 touch controller. */ extern char c[30], b[30]; extern char printBuff[2][20]; //mirrors what is showing on the two lines of the display -extern int count; //to generally count ticks, loops, etc /** * The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig. From a718d3064d1d1b3a29a74ab364540fe67dfaa900 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 11:48:41 -0800 Subject: [PATCH 007/324] Get rid of touch-specific SPI settings --- nano_gui.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index 00ac5b5..acc008e 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -37,7 +37,6 @@ void writeTouchCalibration(){ #define Z_THRESHOLD 400 #define Z_THRESHOLD_INT 75 #define MSEC_THRESHOLD 3 -#define SPI_SETTING SPISettings(2000000, MSBFIRST, SPI_MODE0) static uint32_t msraw=0x80000000; static int16_t xraw=0, yraw=0, zraw=0; @@ -63,7 +62,6 @@ static void touch_update(){ uint32_t now = millis(); if (now - msraw < MSEC_THRESHOLD) return; - SPI.beginTransaction(SPI_SETTING); digitalWrite(CS_PIN, LOW); SPI.transfer(0xB1 /* Z1 */); int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3; @@ -81,7 +79,6 @@ static void touch_update(){ data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down data[5] = SPI.transfer16(0) >> 3; digitalWrite(CS_PIN, HIGH); - SPI.endTransaction(); //Serial.printf("z=%d :: z1=%d, z2=%d ", z, z1, z2); if (z < 0) z = 0; if (z < Z_THRESHOLD) { // if ( !touched ) { From 3713406ad87e24982c52854ca59add9be36c7119 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 11:58:28 -0800 Subject: [PATCH 008/324] Clean up button indentation --- ubitx_ui.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index c468e79..722484b 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -15,23 +15,23 @@ struct Button { #define MAX_BUTTONS 17 const struct Button btn_set[MAX_BUTTONS] PROGMEM = { //const struct Button btn_set [] = { - {0, 10, 159, 36, "VFOA", "A"}, + { 0, 10, 159, 36, "VFOA", "A"}, {160, 10, 159, 36, "VFOB", "B"}, - {0, 80, 60, 36, "RIT", "R"}, - {64, 80, 60, 36, "USB", "U"}, + { 0, 80, 60, 36, "RIT", "R"}, + { 64, 80, 60, 36, "USB", "U"}, {128, 80, 60, 36, "LSB", "L"}, {192, 80, 60, 36, "CW", "M"}, {256, 80, 60, 36, "SPL", "S"}, - {0, 120, 60, 36, "80", "8"}, - {64, 120, 60, 36, "40", "4"}, + { 0, 120, 60, 36, "80", "8"}, + { 64, 120, 60, 36, "40", "4"}, {128, 120, 60, 36, "30", "3"}, {192, 120, 60, 36, "20", "2"}, {256, 120, 60, 36, "17", "7"}, - {0, 160, 60, 36, "15", "5"}, - {64, 160, 60, 36, "10", "1"}, + { 0, 160, 60, 36, "15", "5"}, + { 64, 160, 60, 36, "10", "1"}, {128, 160, 60, 36, "WPM", "W"}, {192, 160, 60, 36, "TON", "T"}, {256, 160, 60, 36, "FRQ", "F"}, @@ -39,23 +39,23 @@ const struct Button btn_set[MAX_BUTTONS] PROGMEM = { #define MAX_KEYS 17 const struct Button keypad[MAX_KEYS] PROGMEM = { - {0, 80, 60, 36, "1", "1"}, - {64, 80, 60, 36, "2", "2"}, + { 0, 80, 60, 36, "1", "1"}, + { 64, 80, 60, 36, "2", "2"}, {128, 80, 60, 36, "3", "3"}, - {192, 80, 60, 36, "", ""}, - {256, 80, 60, 36, "OK", "K"}, + {192, 80, 60, 36, "", ""}, + {256, 80, 60, 36, "OK", "K"}, - {0, 120, 60, 36, "4", "4"}, - {64, 120, 60, 36, "5", "5"}, - {128, 120, 60, 36, "6", "6"}, - {192, 120, 60, 36, "0", "0"}, - {256, 120, 60, 36, "<-", "B"}, + { 0, 120, 60, 36, "4", "4"}, + { 64, 120, 60, 36, "5", "5"}, + {128, 120, 60, 36, "6", "6"}, + {192, 120, 60, 36, "0", "0"}, + {256, 120, 60, 36, "<-", "B"}, - {0, 160, 60, 36, "7", "7"}, - {64, 160, 60, 36, "8", "8"}, + { 0, 160, 60, 36, "7", "7"}, + { 64, 160, 60, 36, "8", "8"}, {128, 160, 60, 36, "9", "9"}, - {192, 160, 60, 36, "", ""}, - {256, 160, 60, 36, "Can", "C"}, + {192, 160, 60, 36, "", ""}, + {256, 160, 60, 36, "Can", "C"}, }; boolean getButton(char *text, struct Button *b){ From cf62bd779ce6cfafd85006461c029ffb5aaa6c70 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 16:17:37 -0800 Subject: [PATCH 009/324] Major refactor to make rendering parameters more centralized --- ubitx_ui.cpp | 824 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 499 insertions(+), 325 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 722484b..907fbb2 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -4,68 +4,147 @@ #include "ubitx.h" #include "nano_gui.h" -#define BUTTON_SELECTED 1 +static const unsigned int COLOR_TEXT = DISPLAY_WHITE; +static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK; + +static const unsigned int COLOR_ACTIVE_VFO_TEXT = DISPLAY_WHITE; +static const unsigned int COLOR_ACTIVE_VFO_BACKGROUND = DISPLAY_DARKGREY; + +static const unsigned int COLOR_INACTIVE_VFO_TEXT = DISPLAY_GREEN; +static const unsigned int COLOR_INACTIVE_VFO_BACKGROUND = DISPLAY_DARKGREY; + +static const unsigned int COLOR_INACTIVE_TEXT = DISPLAY_GREEN; +static const unsigned int COLOR_INACTIVE_BACKGROUND = DISPLAY_DARKGREY; +static const unsigned int COLOR_INACTIVE_BORDER = DISPLAY_DARKGREY; + +static const unsigned int COLOR_ACTIVE_TEXT = DISPLAY_BLACK; +static const unsigned int COLOR_ACTIVE_BACKGROUND = DISPLAY_ORANGE; +static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; + +static const unsigned int LAYOUT_VFO_LABEL_X = 0; +static const unsigned int LAYOUT_VFO_LABEL_Y = 10; +static const unsigned int LAYOUT_VFO_LABEL_WIDTH = 159; +static const unsigned int LAYOUT_VFO_LABEL_HEIGHT = 36; +static const unsigned int LAYOUT_VFO_LABEL_PITCH_X = 160; + +static const unsigned int LAYOUT_MODE_TEXT_X = 0; +static const unsigned int LAYOUT_MODE_TEXT_Y = 55; +static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; +static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 30; + +static const unsigned int LAYOUT_BUTTON_X = 0; +static const unsigned int LAYOUT_BUTTON_Y = 80; +static const unsigned int LAYOUT_BUTTON_WIDTH = 60; +static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; +static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; +static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; + +static const unsigned int LAYOUT_CW_TEXT_X = 0; +static const unsigned int LAYOUT_CW_TEXT_Y = 201; +static const unsigned int LAYOUT_CW_TEXT_WIDTH = 320; +static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 39; + +static const unsigned int LAYOUT_TX_X = 280; +static const unsigned int LAYOUT_TX_Y = 48; +static const unsigned int LAYOUT_TX_WIDTH = 37; +static const unsigned int LAYOUT_TX_HEIGHT = 28; + +enum btn_set_e { + BUTTON_VFOA, + BUTTON_VFOB, + BUTTON_RIT, + BUTTON_USB, + BUTTON_LSB, + BUTTON_CW, + BUTTON_SPL, + BUTTON_80, + BUTTON_40, + BUTTON_30, + BUTTON_20, + BUTTON_17, + BUTTON_15, + BUTTON_10, + BUTTON_WPM, + BUTTON_TON, + BUTTON_FRQ, + BUTTON_TOTAL +}; struct Button { int x, y, w, h; - char *text; - char *morse; + unsigned int id; + char text[5]; + char morse; }; -#define MAX_BUTTONS 17 -const struct Button btn_set[MAX_BUTTONS] PROGMEM = { -//const struct Button btn_set [] = { - { 0, 10, 159, 36, "VFOA", "A"}, - {160, 10, 159, 36, "VFOB", "B"}, +constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = { + {LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A'}, + {LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B'}, - { 0, 80, 60, 36, "RIT", "R"}, - { 64, 80, 60, 36, "USB", "U"}, - {128, 80, 60, 36, "LSB", "L"}, - {192, 80, 60, 36, "CW", "M"}, - {256, 80, 60, 36, "SPL", "S"}, - - { 0, 120, 60, 36, "80", "8"}, - { 64, 120, 60, 36, "40", "4"}, - {128, 120, 60, 36, "30", "3"}, - {192, 120, 60, 36, "20", "2"}, - {256, 120, 60, 36, "17", "7"}, - - { 0, 160, 60, 36, "15", "5"}, - { 64, 160, 60, 36, "10", "1"}, - {128, 160, 60, 36, "WPM", "W"}, - {192, 160, 60, 36, "TON", "T"}, - {256, 160, 60, 36, "FRQ", "F"}, + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R'}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U'}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'M'}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S'}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8'}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4'}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2'}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7'}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5'}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1'}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_WPM, "WPM", 'W'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_TON, "TON", 'T'}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F'}, }; -#define MAX_KEYS 17 -const struct Button keypad[MAX_KEYS] PROGMEM = { - { 0, 80, 60, 36, "1", "1"}, - { 64, 80, 60, 36, "2", "2"}, - {128, 80, 60, 36, "3", "3"}, - {192, 80, 60, 36, "", ""}, - {256, 80, 60, 36, "OK", "K"}, - - { 0, 120, 60, 36, "4", "4"}, - { 64, 120, 60, 36, "5", "5"}, - {128, 120, 60, 36, "6", "6"}, - {192, 120, 60, 36, "0", "0"}, - {256, 120, 60, 36, "<-", "B"}, - - { 0, 160, 60, 36, "7", "7"}, - { 64, 160, 60, 36, "8", "8"}, - {128, 160, 60, 36, "9", "9"}, - {192, 160, 60, 36, "", ""}, - {256, 160, 60, 36, "Can", "C"}, +static const unsigned int KEYS_OFFSET = 256;//Unique from buttons +enum keypad_e { + KEYS_1 = KEYS_OFFSET, + KEYS_2, + KEYS_3, + KEYS_BLANK_1, + KEYS_OK, + KEYS_4, + KEYS_5, + KEYS_6, + KEYS_0, + KEYS_BACKSPACE, + KEYS_7, + KEYS_8, + KEYS_9, + KEYS_BLANK_2, + KEYS_CANCEL, + KEYS_TOTAL = KEYS_CANCEL - KEYS_OFFSET + 1 +}; +constexpr Button keypad[KEYS_TOTAL] PROGMEM = { + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_1, "1", '1'}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_2, "2", '2'}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_3, "3", '3'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_1, "", '\0'}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_OK, "OK", 'K'}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_4, "4", '4'}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_5, "5", '5'}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_6, "6", '6'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_0, "0", '0'}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BACKSPACE, "<-", 'B'}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_7, "7", '7'}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_8, "8", '8'}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_9, "9", '9'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_2, "", '\0'}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_CANCEL, "Can", 'C'}, }; -boolean getButton(char *text, struct Button *b){ - for (int i = 0; i < MAX_BUTTONS; i++){ - memcpy_P(b, btn_set + i, sizeof(struct Button)); - if (!strcmp(text, b->text)){ - return true; - } +boolean getButton(btn_set_e index, Button* button){ + if(BUTTON_TOTAL == index){ + return false; } - return false; + memcpy_P(button, &(btn_set[index]), sizeof(Button)); + return true; } @@ -84,60 +163,59 @@ void formatFreq(long f, char *buff) { //one mhz digit if less than 10 M, two digits if more if (f < 10000000l){ buff[0] = ' '; - strncat(buff, b, 4); + strncat(buff, b, 4); strcat(buff, "."); strncat(buff, &b[4], 2); } else { strncat(buff, b, 5); strcat(buff, "."); - strncat(buff, &b[5], 2); + strncat(buff, &b[5], 2); } } -void drawCommandbar(char *text){ - displayFillrect(30,45,280, 32, DISPLAY_NAVY); - displayRawText(text, 30, 45, DISPLAY_WHITE, DISPLAY_NAVY); +inline void drawCommandbar(char* text){ + displayText(text, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } /** A generic control to read variable values */ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix) { - int knob = 0; - int knob_value; + int knob = 0; + int knob_value; - while (btnDown()) - active_delay(100); + while (btnDown()) + active_delay(100); - active_delay(200); - knob_value = initial; - - strcpy(b, prefix); - itoa(knob_value, c, 10); - strcat(b, c); - strcat(b, postfix); - drawCommandbar(b); + active_delay(200); + knob_value = initial; - while(!btnDown() && digitalRead(PTT) == HIGH){ + strcpy(b, prefix); + itoa(knob_value, c, 10); + strcat(b, c); + strcat(b, postfix); + drawCommandbar(b); - knob = enc_read(); - if (knob != 0){ - if (knob_value > minimum && knob < 0) - knob_value -= step_size; - if (knob_value < maximum && knob > 0) - knob_value += step_size; - - strcpy(b, prefix); - itoa(knob_value, c, 10); - strcat(b, c); - strcat(b, postfix); - drawCommandbar(b); - } - checkCAT(); + while(!btnDown() && digitalRead(PTT) == HIGH){ + knob = enc_read(); + if (knob != 0){ + if (knob_value > minimum && knob < 0) + knob_value -= step_size; + if (knob_value < maximum && knob > 0) + knob_value += step_size; + + strcpy(b, prefix); + itoa(knob_value, c, 10); + strcat(b, c); + strcat(b, postfix); + drawCommandbar(b); } - displayFillrect(30,41,280, 32, DISPLAY_NAVY); - return knob_value; + checkCAT(); + } + b[0] = 0; + drawCommandbar(b); + return knob_value; } void printCarrierFreq(unsigned long freq){ @@ -152,138 +230,168 @@ void printCarrierFreq(unsigned long freq){ strncat(c, &b[2], 3); strcat(c, "."); strncat(c, &b[5], 1); - displayText(c, 110, 100, 100, 30, DISPLAY_CYAN, DISPLAY_NAVY, DISPLAY_NAVY); + displayText(c, 110, 100, 100, 30, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } void displayDialog(char *title, char *instructions){ - displayClear(DISPLAY_BLACK); - displayRect(10,10,300,220, DISPLAY_WHITE); - displayHline(20,45,280,DISPLAY_WHITE); - displayRect(12,12,296,216, DISPLAY_WHITE); - displayRawText(title, 20, 20, DISPLAY_CYAN, DISPLAY_NAVY); - displayRawText(instructions, 20, 200, DISPLAY_CYAN, DISPLAY_NAVY); + displayClear(COLOR_BACKGROUND); + displayRect(10,10,300,220, COLOR_TEXT); + displayHline(20,45,280,COLOR_TEXT); + displayRect(12,12,296,216, COLOR_TEXT); + displayRawText(title, 20, 20, COLOR_TEXT, COLOR_BACKGROUND); + displayRawText(instructions, 20, 200, COLOR_TEXT, COLOR_BACKGROUND); } - - - -char vfoDisplay[12]; void displayVFO(int vfo){ int x, y; - int displayColor, displayBorder; - Button b; + int displayColor, displayBackground, displayBorder; + Button button; - if (vfo == VFO_A){ - getButton("VFOA", &b); - if (splitOn){ - if (vfoActive == VFO_A) - strcpy(c, "R:"); - else - strcpy(c, "T:"); + if (splitOn){ + if (vfoActive == vfo){ + c[0] = 'R'; } - else - strcpy(c, "A:"); + else{ + c[0] = 'T'; + } + } + else{ + if(VFO_A == vfo){ + c[0] = 'A'; + } + else if(VFO_B == vfo){ + c[0] = 'B'; + } + else{ + c[0] = '?'; + } + } + c[1] = ':'; + + + if (vfo == VFO_A){ + getButton(BUTTON_VFOA, &button); + if (vfoActive == VFO_A){ formatFreq(frequency, c+2); - displayColor = DISPLAY_WHITE; - displayBorder = DISPLAY_BLACK; + displayColor = COLOR_ACTIVE_VFO_TEXT; + displayBackground = COLOR_ACTIVE_VFO_BACKGROUND; + displayBorder = COLOR_ACTIVE_BORDER; }else{ formatFreq(vfoA, c+2); - displayColor = DISPLAY_GREEN; - displayBorder = DISPLAY_BLACK; + displayColor = COLOR_INACTIVE_VFO_TEXT; + displayBackground = COLOR_INACTIVE_VFO_BACKGROUND; + displayBorder = COLOR_INACTIVE_BORDER; } } if (vfo == VFO_B){ - getButton("VFOB", &b); + getButton(BUTTON_VFOB, &button); - if (splitOn){ - if (vfoActive == VFO_B) - strcpy(c, "R:"); - else - strcpy(c, "T:"); - } - else - strcpy(c, "B:"); if (vfoActive == VFO_B){ formatFreq(frequency, c+2); - displayColor = DISPLAY_WHITE; - displayBorder = DISPLAY_WHITE; + displayColor = COLOR_ACTIVE_VFO_TEXT; + displayBackground = COLOR_ACTIVE_VFO_BACKGROUND; + displayBorder = COLOR_ACTIVE_BORDER; } else { - displayColor = DISPLAY_GREEN; - displayBorder = DISPLAY_BLACK; formatFreq(vfoB, c+2); + displayColor = COLOR_INACTIVE_VFO_TEXT; + displayBackground = COLOR_INACTIVE_VFO_BACKGROUND; + displayBorder = COLOR_INACTIVE_BORDER; } } - if (vfoDisplay[0] == 0){ - displayFillrect(b.x, b.y, b.w, b.h, DISPLAY_BLACK); - if (vfoActive == vfo) - displayRect(b.x, b.y, b.w , b.h, DISPLAY_WHITE); - else - displayRect(b.x, b.y, b.w , b.h, DISPLAY_NAVY); - } - x = b.x + 6; - y = b.y + 3; - - char *text = c; + displayText(c, button.x, button.y, button.w, button.h, displayColor, displayBackground, displayBorder); +} - for (int i = 0; i <= strlen(c); i++){ - char digit = c[i]; - if (digit != vfoDisplay[i]){ - - displayFillrect(x, y, 15, b.h-6, DISPLAY_BLACK); - //checkCAT(); - - displayChar(x, y + TEXT_LINE_HEIGHT + 3, digit, displayColor, DISPLAY_BLACK); - checkCAT(); - } - if (digit == ':' || digit == '.') - x += 7; - else - x += 16; - text++; - }//end of the while loop of the characters to be printed - - strcpy(vfoDisplay, c); +void btnDrawActive(Button* button){ + displayText(button->text, button->x, button->y, button->w, button->h, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); +} +void btnDrawInactive(Button* button){ + displayText(button->text, button->x, button->y, button->w, button->h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); } -void btnDraw(struct Button *b){ - if (!strcmp(b->text, "VFOA")){ - memset(vfoDisplay, 0, sizeof(vfoDisplay)); - displayVFO(VFO_A); - } - else if(!strcmp(b->text, "VFOB")){ - memset(vfoDisplay, 0, sizeof(vfoDisplay)); - displayVFO(VFO_B); - } - else if ((!strcmp(b->text, "RIT") && ritOn == 1) || - (!strcmp(b->text, "USB") && isUSB == 1) || - (!strcmp(b->text, "LSB") && isUSB == 0) || - (!strcmp(b->text, "SPL") && splitOn == 1)) - displayText(b->text, b->x, b->y, b->w, b->h, DISPLAY_BLACK, DISPLAY_ORANGE, DISPLAY_DARKGREY); - else if (!strcmp(b->text, "CW") && cwMode == 1) - displayText(b->text, b->x, b->y, b->w, b->h, DISPLAY_BLACK, DISPLAY_ORANGE, DISPLAY_DARKGREY); - else - displayText(b->text, b->x, b->y, b->w, b->h, DISPLAY_GREEN, DISPLAY_BLACK, DISPLAY_DARKGREY); +void btnDraw(struct Button *button){ + switch(button->id){ + case BUTTON_VFOA: + { + displayVFO(VFO_A); + break; + } + case BUTTON_VFOB: + { + displayVFO(VFO_B); + break; + } + case BUTTON_RIT: + { + if(1 == ritOn){ + btnDrawActive(button); + } + else{ + btnDrawInactive(button); + } + break; + } + case BUTTON_USB: + { + if(1 == isUSB){ + btnDrawActive(button); + } + else{ + btnDrawInactive(button); + } + break; + } + case BUTTON_LSB: + { + if(0 == isUSB){ + btnDrawActive(button); + } + else{ + btnDrawInactive(button); + } + break; + } + case BUTTON_SPL: + { + if(1 == splitOn){ + btnDrawActive(button); + } + else{ + btnDrawInactive(button); + } + break; + } + case BUTTON_CW: + { + if(1 == cwMode){ + btnDrawActive(button); + } + else{ + btnDrawInactive(button); + } + break; + } + default: + { + btnDrawInactive(button); + break; + } + }//End switch } void displayRIT(){ - displayFillrect(0,41,320,30, DISPLAY_NAVY); + c[0] = 0; + displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); if (ritOn){ - strcpy(c, "TX:"); + strcpy_P(c,(const char*)F("TX:")); formatFreq(ritTxFrequency, c+3); if (vfoActive == VFO_A) - displayText(c, 0, 45,159, 30, DISPLAY_WHITE, DISPLAY_NAVY, DISPLAY_NAVY); - else - displayText(c, 160, 45,159, 30, DISPLAY_WHITE, DISPLAY_NAVY, DISPLAY_NAVY); - } - else { - if (vfoActive == VFO_A) - displayText("", 0, 45,159, 30, DISPLAY_WHITE, DISPLAY_NAVY, DISPLAY_NAVY); + displayText(c, LAYOUT_MODE_TEXT_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); else - displayText("", 160, 45,159, 30, DISPLAY_WHITE, DISPLAY_NAVY, DISPLAY_NAVY); + displayText(c, LAYOUT_MODE_TEXT_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } } @@ -295,13 +403,13 @@ void fastTune(){ active_delay(50); active_delay(300); - displayRawText("Fast tune", 100, 55, DISPLAY_CYAN, DISPLAY_NAVY); + displayText("Fast tune", LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); while(1){ checkCAT(); //exit after debouncing the btnDown if (btnDown()){ - displayFillrect(100, 55, 120, 30, DISPLAY_NAVY); + displayFillrect(LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); //wait until the button is realsed and then return while(btnDown()) @@ -328,10 +436,10 @@ void enterFreq(){ //display all the buttons int f; - for (int i = 0; i < MAX_KEYS; i++){ - struct Button b; - memcpy_P(&b, keypad + i, sizeof(struct Button)); - btnDraw(&b); + for (int i = 0; i < KEYS_TOTAL; i++){ + Button button; + memcpy_P(&button, &(keypad[i]), sizeof(Button)); + btnDraw(&button); } int cursor_pos = 0; @@ -346,17 +454,18 @@ void enterFreq(){ scaleTouch(&ts_point); - int total = sizeof(btn_set)/sizeof(struct Button); - for (int i = 0; i < MAX_KEYS; i++){ - struct Button b; - memcpy_P(&b, keypad + i, sizeof(struct Button)); + for (int i = 0; i < KEYS_TOTAL; i++){ + Button button; + memcpy_P(&button, &(keypad[i]), sizeof(Button)); - int x2 = b.x + b.w; - int y2 = b.y + b.h; + int x2 = button.x + button.w; + int y2 = button.y + button.h; - if (b.x < ts_point.x && ts_point.x < x2 && - b.y < ts_point.y && ts_point.y < y2){ - if (!strcmp(b.text, "OK")){ + if(button.x < ts_point.x && ts_point.x < x2 && + button.y < ts_point.y && ts_point.y < y2){ + switch(button.id){ + case KEYS_OK: + { long f = atol(c); if(30000 >= f && f > 100){ frequency = f * 1000l; @@ -369,31 +478,55 @@ void enterFreq(){ } guiUpdate(); return; + break; } - else if (!strcmp(b.text, "<-")){ + + case KEYS_BACKSPACE: + { c[cursor_pos] = 0; - if (cursor_pos > 0) - cursor_pos--; + if (cursor_pos > 0){ + cursor_pos--; + } c[cursor_pos] = 0; + break; } - else if (!strcmp(b.text, "Can")){ + case KEYS_CANCEL: + { guiUpdate(); return; + break; } - else if('0' <= b.text[0] && b.text[0] <= '9'){ - c[cursor_pos++] = b.text[0]; + case KEYS_0: + case KEYS_1: + case KEYS_2: + case KEYS_3: + case KEYS_4: + case KEYS_5: + case KEYS_6: + case KEYS_7: + case KEYS_8: + case KEYS_9: + { + c[cursor_pos++] = button.text[0]; c[cursor_pos] = 0; + break; + } + default: + { + //Serial.print(F("Unknown key id: ")); + //Serial.println(button.id); + break; } - } - } // end of the button scanning loop + }//switch + }//if button hit test + }// end of the button scanning loop strcpy(b, c); strcat(b, " KHz"); - displayText(b, 0, 42, 320, 30, DISPLAY_WHITE, DISPLAY_NAVY, DISPLAY_NAVY); + displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); delay(300); while(readTouch()) checkCAT(); } // end of event loop : while(1) - } void drawCWStatus(){ @@ -405,15 +538,15 @@ void drawCWStatus(){ itoa(sideTone, c, 10); strcat(b, c); strcat(b, "hz"); - displayText(b, 0, 201, 320, 39, DISPLAY_CYAN, DISPLAY_NAVY, DISPLAY_NAVY); + displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } void drawTx(){ if (inTx) - displayText("TX", 280, 48, 37, 28, DISPLAY_BLACK, DISPLAY_ORANGE, DISPLAY_BLUE); + displayText("TX", LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND); else - displayFillrect(280, 48, 37, 28, DISPLAY_NAVY); + displayFillrect(LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_BACKGROUND); } void drawStatusbar(){ drawCWStatus(); @@ -426,13 +559,10 @@ void guiUpdate(){ return; */ // use the current frequency as the VFO frequency for the active VFO - displayClear(DISPLAY_NAVY); + displayClear(COLOR_BACKGROUND); - memset(vfoDisplay, 0, 12); displayVFO(VFO_A); - checkCAT(); - memset(vfoDisplay, 0, 12); - displayVFO(VFO_B); + displayVFO(VFO_B); checkCAT(); displayRIT(); @@ -440,14 +570,14 @@ void guiUpdate(){ //force the display to refresh everything //display all the buttons - for (int i = 0; i < MAX_BUTTONS; i++){ - struct Button b; - memcpy_P(&b, btn_set + i, sizeof(struct Button)); - btnDraw(&b); + for (int i = 0; i < BUTTON_TOTAL; i++){ + Button button; + memcpy_P(&button, &(btn_set[i]), sizeof(Button)); + btnDraw(&button); checkCAT(); } drawStatusbar(); - checkCAT(); + checkCAT(); } @@ -520,60 +650,56 @@ int enc_read(void) { return(result); } -void ritToggle(struct Button *b){ +void ritToggle(struct Button *button){ if (ritOn == 0){ ritEnable(frequency); } else ritDisable(); - btnDraw(b); + btnDraw(button); displayRIT(); } -void splitToggle(struct Button *b){ +void splitToggle(Button *button){ if (splitOn) splitOn = 0; else splitOn = 1; - btnDraw(b); + btnDraw(button); //disable rit as well ritDisable(); - struct Button b2; - getButton("RIT", &b2); - btnDraw(&b2); + Button button2; + getButton(BUTTON_RIT, &button2); + btnDraw(&button2); displayRIT(); - memset(vfoDisplay, 0, sizeof(vfoDisplay)); displayVFO(VFO_A); - memset(vfoDisplay, 0, sizeof(vfoDisplay)); - displayVFO(VFO_B); + displayVFO(VFO_B); } void vfoReset(){ - Button b; + Button button; if (vfoActive = VFO_A) vfoB = vfoA; else vfoA = vfoB; if (splitOn){ - getButton("SPL", &b); - splitToggle(&b); + getButton(BUTTON_SPL, &button); + splitToggle(&button); } if (ritOn){ - getButton("RIT", &b); - ritToggle(&b); + getButton(BUTTON_RIT, &button); + ritToggle(&button); } - memset(vfoDisplay, 0, sizeof(vfoDisplay)); displayVFO(VFO_A); - memset(vfoDisplay, 0, sizeof(vfoDisplay)); - displayVFO(VFO_B); + displayVFO(VFO_B); saveVFOs(); } @@ -589,39 +715,36 @@ void cwToggle(struct Button *b){ btnDraw(b); } -void sidebandToggle(struct Button *b){ - if (!strcmp(b->text, "LSB")) +void sidebandToggle(Button* button){ + if(BUTTON_LSB == button->id) isUSB = 0; else isUSB = 1; - struct Button e; - getButton("USB", &e); - btnDraw(&e); - getButton("LSB", &e); - btnDraw(&e); + struct Button button2; + getButton(BUTTON_USB, &button2); + btnDraw(&button2); + getButton(BUTTON_LSB, &button2); + btnDraw(&button2); saveVFOs(); } void redrawVFOs(){ - - struct Button b; + struct Button button; ritDisable(); - getButton("RIT", &b); - btnDraw(&b); + getButton(BUTTON_RIT, &button); + btnDraw(&button); displayRIT(); - memset(vfoDisplay, 0, sizeof(vfoDisplay)); displayVFO(VFO_A); - memset(vfoDisplay, 0, sizeof(vfoDisplay)); displayVFO(VFO_B); //draw the lsb/usb buttons, the sidebands might have changed - getButton("LSB", &b); - btnDraw(&b); - getButton("USB", &b); - btnDraw(&b); + getButton(BUTTON_LSB, &button); + btnDraw(&button); + getButton(BUTTON_USB, &button); + btnDraw(&button); } @@ -694,64 +817,116 @@ void setCwTone(){ //save the setting EEPROM.put(CW_SIDETONE, sideTone); - displayFillrect(30,41,280, 32, DISPLAY_NAVY); + b[0] = 0; + drawCommandbar(b); drawStatusbar(); // printLine2(""); // updateDisplay(); } -void doCommand(struct Button *b){ - - if (!strcmp(b->text, "RIT")) - ritToggle(b); - else if (!strcmp(b->text, "LSB")) - sidebandToggle(b); - else if (!strcmp(b->text, "USB")) - sidebandToggle(b); - else if (!strcmp(b->text, "CW")) - cwToggle(b); - else if (!strcmp(b->text, "SPL")) - splitToggle(b); - else if (!strcmp(b->text, "VFOA")){ - if (vfoActive == VFO_A) - fastTune(); - else - switchVFO(VFO_A); - } - else if (!strcmp(b->text, "VFOB")){ - if (vfoActive == VFO_B) - fastTune(); - else - switchVFO(VFO_B); +void doCommand(Button* button){ + switch(button->id){ + case BUTTON_RIT: + { + ritToggle(button); + break; + } + case BUTTON_LSB: + case BUTTON_USB: + { + sidebandToggle(button); + break; + } + case BUTTON_CW: + { + cwToggle(button); + break; + } + case BUTTON_SPL: + { + splitToggle(button); + break; + } + case BUTTON_VFOA: + { + if(VFO_A == vfoActive){ + fastTune(); + } + else{ + switchVFO(VFO_A); + } + break; + } + case BUTTON_VFOB: + { + if(VFO_B == vfoActive){ + fastTune(); + } + else{ + switchVFO(VFO_B); + } + break; + } + case BUTTON_80: + { + switchBand(3500000L); + break; + } + case BUTTON_40: + { + switchBand(7000000L); + break; + } + case BUTTON_30: + { + switchBand(10000000L); + break; + } + case BUTTON_20: + { + switchBand(14000000L); + break; + } + case BUTTON_17: + { + switchBand(18000000L); + break; + } + case BUTTON_15: + { + switchBand(21000000L); + break; + } + case BUTTON_10: + { + switchBand(28000000L); + break; + } + case BUTTON_FRQ: + { + enterFreq(); + break; + } + case BUTTON_WPM: + { + setCwSpeed(); + break; + } + case BUTTON_TON: + { + setCwTone(); + break; + } + default: + { + //Serial.print(F("Unknown command: ")); + //Serial.println(button.id); + break; + } } - else if (!strcmp(b->text, "A=B")) - vfoReset(); - else if (!strcmp(b->text, "80")) - switchBand(3500000l); - else if (!strcmp(b->text, "40")) - switchBand(7000000l); - else if (!strcmp(b->text, "30")) - switchBand(10000000l); - else if (!strcmp(b->text, "20")) - switchBand(14000000l); - else if (!strcmp(b->text, "17")) - switchBand(18000000l); - else if (!strcmp(b->text, "15")) - switchBand(21000000l); - else if (!strcmp(b->text, "13")) - switchBand(24800000l); - else if (!strcmp(b->text, "10")) - switchBand(28000000l); - else if (!strcmp(b->text, "FRQ")) - enterFreq(); - else if (!strcmp(b->text, "WPM")) - setCwSpeed(); - else if (!strcmp(b->text, "TON")) - setCwTone(); } void checkTouch(){ - if (!readTouch()) return; @@ -762,17 +937,16 @@ void checkTouch(){ /* //debug code Serial.print(ts_point.x); Serial.print(' ');Serial.println(ts_point.y); */ - int total = sizeof(btn_set)/sizeof(struct Button); - for (int i = 0; i < MAX_BUTTONS; i++){ - struct Button b; - memcpy_P(&b, btn_set + i, sizeof(struct Button)); + for (int i = 0; i < BUTTON_TOTAL; i++){ + Button button; + memcpy_P(&button, &(btn_set[i]), sizeof(Button)); - int x2 = b.x + b.w; - int y2 = b.y + b.h; + int x2 = button.x + button.w; + int y2 = button.y + button.h; - if (b.x < ts_point.x && ts_point.x < x2 && - b.y < ts_point.y && ts_point.y < y2) - doCommand(&b); + if(button.x < ts_point.x && ts_point.x < x2 && + button.y < ts_point.y && ts_point.y < y2) + doCommand(&button); } } @@ -786,10 +960,10 @@ int btnDown(){ void drawFocus(int ibtn, int color){ - struct Button b; + Button button; - memcpy_P(&b, btn_set + ibtn, sizeof(struct Button)); - displayRect(b.x, b.y, b.w, b.h, color); + memcpy_P(&button, &(btn_set[ibtn]), sizeof(Button)); + displayRect(button.x, button.y, button.w, button.h, color); } void doCommands(){ @@ -807,22 +981,22 @@ void doCommands(){ //check if the knob's button was pressed btnState = btnDown(); if (btnState){ - struct Button b; - memcpy_P(&b, btn_set + select/10, sizeof(struct Button)); + Button button; + memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); - doCommand(&b); + doCommand(&button); //unfocus the buttons - drawFocus(select, DISPLAY_BLUE); + drawFocus(select, COLOR_INACTIVE_BORDER); if (vfoActive == VFO_A) - drawFocus(0, DISPLAY_WHITE); + drawFocus(BUTTON_VFOA, COLOR_ACTIVE_BORDER); else - drawFocus(1, DISPLAY_WHITE); + drawFocus(BUTTON_VFOB, COLOR_ACTIVE_BORDER); //wait for the button to be up and debounce while(btnDown()) active_delay(100); - active_delay(500); + active_delay(500); return; } @@ -834,7 +1008,7 @@ void doCommands(){ } if (i > 0){ - if (select + i < MAX_BUTTONS * 10) + if (select + i < BUTTON_TOTAL * 10) select += i; } if (i < 0 && select + i >= 0) @@ -844,8 +1018,8 @@ void doCommands(){ continue; //we are on a new button - drawFocus(prevButton, DISPLAY_BLUE); - drawFocus(select/10, DISPLAY_WHITE); + drawFocus(prevButton, COLOR_INACTIVE_BORDER); + drawFocus(select/10, COLOR_ACTIVE_BORDER); prevButton = select/10; } // guiUpdate(); From 7f4169bce5d1b0350438715adfce79735055a11c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 16:28:34 -0800 Subject: [PATCH 010/324] Tweak layout to work better --- ubitx_ui.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 907fbb2..06ce38c 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -28,26 +28,26 @@ static const unsigned int LAYOUT_VFO_LABEL_HEIGHT = 36; static const unsigned int LAYOUT_VFO_LABEL_PITCH_X = 160; static const unsigned int LAYOUT_MODE_TEXT_X = 0; -static const unsigned int LAYOUT_MODE_TEXT_Y = 55; +static const unsigned int LAYOUT_MODE_TEXT_Y = LAYOUT_VFO_LABEL_Y + LAYOUT_VFO_LABEL_HEIGHT + 1; static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; -static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 30; +static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; static const unsigned int LAYOUT_BUTTON_X = 0; -static const unsigned int LAYOUT_BUTTON_Y = 80; +static const unsigned int LAYOUT_BUTTON_Y = LAYOUT_MODE_TEXT_Y + LAYOUT_MODE_TEXT_HEIGHT + 1; static const unsigned int LAYOUT_BUTTON_WIDTH = 60; static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; static const unsigned int LAYOUT_CW_TEXT_X = 0; -static const unsigned int LAYOUT_CW_TEXT_Y = 201; +static const unsigned int LAYOUT_CW_TEXT_Y = LAYOUT_BUTTON_Y + 3*LAYOUT_BUTTON_PITCH_Y + 1; static const unsigned int LAYOUT_CW_TEXT_WIDTH = 320; -static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 39; +static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 36; static const unsigned int LAYOUT_TX_X = 280; -static const unsigned int LAYOUT_TX_Y = 48; -static const unsigned int LAYOUT_TX_WIDTH = 37; -static const unsigned int LAYOUT_TX_HEIGHT = 28; +static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; +static const unsigned int LAYOUT_TX_WIDTH = 40; +static const unsigned int LAYOUT_TX_HEIGHT = 36; enum btn_set_e { BUTTON_VFOA, From aa80dae4253070edc4f6d9e9e35db3a49847f41f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 18:42:34 -0800 Subject: [PATCH 011/324] Overhaul setup page with layout variables --- setup.cpp | 132 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 100 insertions(+), 32 deletions(-) diff --git a/setup.cpp b/setup.cpp index 616cfda..b1d0b32 100644 --- a/setup.cpp +++ b/setup.cpp @@ -213,34 +213,81 @@ void setupKeyer(){ EEPROM.put(CW_KEY_TYPE, tmp_key); - menuOn = 0; + menuOn = 0; } +static const unsigned int COLOR_TEXT = DISPLAY_WHITE; +static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK; +static const unsigned int COLOR_TITLE_BACKGROUND = DISPLAY_NAVY; +static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; +static const unsigned int COLOR_INACTIVE_BORDER = DISPLAY_DARKGREY; + +static const unsigned int LAYOUT_TITLE_X = 10; +static const unsigned int LAYOUT_TITLE_Y = 10; +static const unsigned int LAYOUT_TITLE_WIDTH = 300; +static const unsigned int LAYOUT_TITLE_HEIGHT = 35; + +static const unsigned int LAYOUT_ITEM_X = 30; +static const unsigned int LAYOUT_ITEM_Y = LAYOUT_TITLE_Y + LAYOUT_TITLE_HEIGHT + 5; +static const unsigned int LAYOUT_ITEM_WIDTH = 260; +static const unsigned int LAYOUT_ITEM_HEIGHT = 30; +static const unsigned int LAYOUT_ITEM_PITCH_Y = 31; + +const char MI_SET_FREQ [] PROGMEM = "Set Freq..."; +const char MI_SET_BFO [] PROGMEM = "Set BFO..."; +const char MI_CW_DELAY [] PROGMEM = "CW Delay..."; +const char MI_CW_KEYER [] PROGMEM = "CW Keyer..."; +const char MI_TOUCH [] PROGMEM = "Touch Screen..."; +const char MI_EXIT [] PROGMEM = "Exit"; + +enum MenuIds { + MENU_SET_FREQ, + MENU_SET_BFO, + MENU_CW_DELAY, + MENU_CW_KEYER, + MENU_TOUCH, + MENU_EXIT, + MENU_TOTAL +}; + +const char* const menuItems [MENU_TOTAL] PROGMEM { + MI_SET_FREQ, + MI_SET_BFO, + MI_CW_DELAY, + MI_CW_KEYER, + MI_TOUCH, + MI_EXIT +}; + void drawSetupMenu(){ - displayClear(DISPLAY_BLACK); - - displayText("Setup", 10, 10, 300, 35, DISPLAY_WHITE, DISPLAY_NAVY, DISPLAY_WHITE); - displayRect(10,10,300,220, DISPLAY_WHITE); - - displayRawText("Set Freq...", 30, 50, DISPLAY_WHITE, DISPLAY_NAVY); - displayRawText("Set BFO...", 30, 80, DISPLAY_WHITE, DISPLAY_NAVY); - displayRawText("CW Delay...", 30, 110, DISPLAY_WHITE, DISPLAY_NAVY); - displayRawText("CW Keyer...", 30, 140, DISPLAY_WHITE, DISPLAY_NAVY); - displayRawText("Touch Screen...", 30, 170, DISPLAY_WHITE, DISPLAY_NAVY); - displayRawText("Exit", 30, 200, DISPLAY_WHITE, DISPLAY_NAVY); + displayClear(COLOR_BACKGROUND); + strcpy_P(b,(const char*)F("Setup")); + displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); + for(unsigned int i = 0; i < MENU_TOTAL; ++i){ + strcpy_P(b,(const char*)pgm_read_word(&(menuItems[i]))); + displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + i*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); + } } -static int prevPuck = -1; void movePuck(int i){ - if (prevPuck >= 0) - displayRect(15, 49 + (prevPuck * 30), 290, 25, DISPLAY_NAVY); - displayRect(15, 49 + (i * 30), 290, 25, DISPLAY_WHITE); + static int prevPuck = 1;//Start value at 1 so that on init, when we get called with 0, we'll update + + //Don't update if we're already on the right selection + if(prevPuck == i){ + return; + } + + //Clear old + displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (prevPuck*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_INACTIVE_BORDER); + //Draw new + displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_ACTIVE_BORDER); prevPuck = i; } void doSetup2(){ - int select=0, i,btnState; + static const unsigned int COUNTS_PER_ITEM = 10; + int select=0, i, btnState; drawSetupMenu(); movePuck(select); @@ -256,13 +303,13 @@ void doSetup2(){ i = enc_read(); if (i > 0){ - if (select + i < 60) + if (select + i < MENU_TOTAL*COUNTS_PER_ITEM) select += i; - movePuck(select/10); + movePuck(select/COUNTS_PER_ITEM); } - if (i < 0 && select - i >= 0){ + if (i < 0 && select + i >= 0){ select += i; //caught ya, i is already -ve here, so you add it - movePuck(select/10); + movePuck(select/COUNTS_PER_ITEM); } if (!btnDown()){ @@ -276,19 +323,40 @@ void doSetup2(){ } active_delay(300); - if (select < 10) - setupFreq(); - else if (select < 20 ) - setupBFO(); - else if (select < 30 ) - setupCwDelay(); - else if (select < 40) + switch(select/COUNTS_PER_ITEM){ + case MENU_SET_FREQ: + { + setupFreq(); + break; + } + case MENU_SET_BFO: + { + setupBFO(); + break; + } + case MENU_CW_DELAY: + { + setupCwDelay(); + break; + } + case MENU_CW_KEYER: + { setupKeyer(); - else if (select < 50) + break; + } + case MENU_TOUCH: + { setupTouch(); - else - break; //exit setup was chosen - //setupExit(); + break; + } + case MENU_EXIT: + default: + { + Serial.println(F("Exiting menu")); + menuOn = 0; + break; + } + }//switch //redraw drawSetupMenu(); } From 5d7c66dc0c53a8d8d3008ad4f9164fb09cd15d08 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 20:25:42 -0800 Subject: [PATCH 012/324] Remove debugging print --- setup.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.cpp b/setup.cpp index b1d0b32..c37f433 100644 --- a/setup.cpp +++ b/setup.cpp @@ -352,7 +352,6 @@ void doSetup2(){ case MENU_EXIT: default: { - Serial.println(F("Exiting menu")); menuOn = 0; break; } From ad2e8341d558ca96db35745a8cceb2b57ad8708e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 20:26:34 -0800 Subject: [PATCH 013/324] Change SPI clock so that we're not violating the touch sensor's timing --- nano_gui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index acc008e..56c693d 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -62,6 +62,7 @@ static void touch_update(){ uint32_t now = millis(); if (now - msraw < MSEC_THRESHOLD) return; + SPI.setClockDivider(SPI_CLOCK_DIV8);//2MHz digitalWrite(CS_PIN, LOW); SPI.transfer(0xB1 /* Z1 */); int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3; @@ -79,7 +80,8 @@ static void touch_update(){ data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down data[5] = SPI.transfer16(0) >> 3; digitalWrite(CS_PIN, HIGH); - //Serial.printf("z=%d :: z1=%d, z2=%d ", z, z1, z2); + SPI.setClockDivider(SPI_CLOCK_DIV2);//Return to full speed for TFT + if (z < 0) z = 0; if (z < Z_THRESHOLD) { // if ( !touched ) { // Serial.println(); @@ -121,7 +123,7 @@ boolean readTouch(){ if (zraw >= Z_THRESHOLD) { ts_point.x = xraw; ts_point.y = yraw; -// Serial.print(ts_point.x); Serial.print(",");Serial.println(ts_point.y); + //Serial.print(ts_point.x); Serial.print(",");Serial.println(ts_point.y); return true; } return false; @@ -131,9 +133,7 @@ void scaleTouch(struct Point *p){ p->x = ((long)(p->x - offset_x) * 10l)/ (long)slope_x; p->y = ((long)(p->y - offset_y) * 10l)/ (long)slope_y; -// Serial.print(p->x); Serial.print(",");Serial.println(p->y); - -// p->y = ((long)(p->y) * 10l)/(long)(slope_y) - offset_y; + //Serial.print(p->x); Serial.print(",");Serial.println(p->y); } /***************** From 224fb496cd7e713415c1bb477534e3569f9dd0cc Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 20:27:29 -0800 Subject: [PATCH 014/324] Add some button printout debugging, and center the button grid --- ubitx_ui.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 06ce38c..87775b3 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -32,7 +32,7 @@ static const unsigned int LAYOUT_MODE_TEXT_Y = LAYOUT_VFO_LABEL_Y + LAYOUT_VFO_L static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; -static const unsigned int LAYOUT_BUTTON_X = 0; +static const unsigned int LAYOUT_BUTTON_X = 2; static const unsigned int LAYOUT_BUTTON_Y = LAYOUT_MODE_TEXT_Y + LAYOUT_MODE_TEXT_HEIGHT + 1; static const unsigned int LAYOUT_BUTTON_WIDTH = 60; static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; @@ -463,6 +463,8 @@ void enterFreq(){ if(button.x < ts_point.x && ts_point.x < x2 && button.y < ts_point.y && ts_point.y < y2){ + Serial.print(F("Entered key: ")); + Serial.println(button.text); switch(button.id){ case KEYS_OK: { @@ -825,6 +827,13 @@ void setCwTone(){ } void doCommand(Button* button){ + Serial.print(F("Doing command: ")); + Serial.print(button->text); + Serial.print(F(", Hitbox: ")); + Serial.print(button->x);Serial.print(F(",")); + Serial.print(button->y);Serial.print(F(";")); + Serial.print(button->x + button->w);Serial.print(F(",")); + Serial.println(button->y + button->h); switch(button->id){ case BUTTON_RIT: { From 817edf254640e4311841dbd613b22defd83f238b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 20:32:18 -0800 Subject: [PATCH 015/324] Display tone prior to loop, so that it's not just a blank screen --- ubitx_ui.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 87775b3..4ac25ba 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -791,6 +791,11 @@ void setCwTone(){ int prev_sideTone; tone(CW_TONE, sideTone); + itoa(sideTone, c, 10); + strcpy(b, "CW Tone: "); + strcat(b, c); + strcat(b, " Hz"); + drawCommandbar(b); //disable all clock 1 and clock 2 while (digitalRead(PTT) == HIGH && !btnDown()) From c8a538511eed518817baa4b7f65d6b13777480f2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 20:42:27 -0800 Subject: [PATCH 016/324] Tweak colors to look more like stock --- ubitx_ui.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 4ac25ba..07e4b4d 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -5,16 +5,16 @@ #include "nano_gui.h" static const unsigned int COLOR_TEXT = DISPLAY_WHITE; -static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK; +static const unsigned int COLOR_BACKGROUND = DISPLAY_NAVY; static const unsigned int COLOR_ACTIVE_VFO_TEXT = DISPLAY_WHITE; -static const unsigned int COLOR_ACTIVE_VFO_BACKGROUND = DISPLAY_DARKGREY; +static const unsigned int COLOR_ACTIVE_VFO_BACKGROUND = DISPLAY_BLACK; static const unsigned int COLOR_INACTIVE_VFO_TEXT = DISPLAY_GREEN; -static const unsigned int COLOR_INACTIVE_VFO_BACKGROUND = DISPLAY_DARKGREY; +static const unsigned int COLOR_INACTIVE_VFO_BACKGROUND = DISPLAY_BLACK; static const unsigned int COLOR_INACTIVE_TEXT = DISPLAY_GREEN; -static const unsigned int COLOR_INACTIVE_BACKGROUND = DISPLAY_DARKGREY; +static const unsigned int COLOR_INACTIVE_BACKGROUND = DISPLAY_BLACK; static const unsigned int COLOR_INACTIVE_BORDER = DISPLAY_DARKGREY; static const unsigned int COLOR_ACTIVE_TEXT = DISPLAY_BLACK; @@ -463,8 +463,8 @@ void enterFreq(){ if(button.x < ts_point.x && ts_point.x < x2 && button.y < ts_point.y && ts_point.y < y2){ - Serial.print(F("Entered key: ")); - Serial.println(button.text); + //Serial.print(F("Entered key: ")); + //Serial.println(button.text); switch(button.id){ case KEYS_OK: { @@ -832,13 +832,13 @@ void setCwTone(){ } void doCommand(Button* button){ - Serial.print(F("Doing command: ")); - Serial.print(button->text); - Serial.print(F(", Hitbox: ")); - Serial.print(button->x);Serial.print(F(",")); - Serial.print(button->y);Serial.print(F(";")); - Serial.print(button->x + button->w);Serial.print(F(",")); - Serial.println(button->y + button->h); + //Serial.print(F("Doing command: ")); + //Serial.print(button->text); + //Serial.print(F(", Hitbox: ")); + //Serial.print(button->x);Serial.print(F(",")); + //Serial.print(button->y);Serial.print(F(";")); + //Serial.print(button->x + button->w);Serial.print(F(",")); + //Serial.println(button->y + button->h); switch(button->id){ case BUTTON_RIT: { From 2902764d73dda66c17d37d0ef6faba70951d9706 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 1 Jan 2020 20:49:35 -0800 Subject: [PATCH 017/324] Save ~4% progmem by using a slightly smaller font --- PDQ_MinLib/FreeSansBold9pt7b.h | 208 ++++++++++++++++++++ nano_font.cpp | 335 +-------------------------------- nano_font.h | 2 +- nano_gui.cpp | 2 +- 4 files changed, 212 insertions(+), 335 deletions(-) create mode 100644 PDQ_MinLib/FreeSansBold9pt7b.h diff --git a/PDQ_MinLib/FreeSansBold9pt7b.h b/PDQ_MinLib/FreeSansBold9pt7b.h new file mode 100644 index 0000000..aeea463 --- /dev/null +++ b/PDQ_MinLib/FreeSansBold9pt7b.h @@ -0,0 +1,208 @@ +const uint8_t FreeSansBold9pt7bBitmaps[] PROGMEM = { + 0xFF, 0xFF, 0xFE, 0x48, 0x7E, 0xEF, 0xDF, 0xBF, 0x74, 0x40, 0x19, 0x86, + 0x67, 0xFD, 0xFF, 0x33, 0x0C, 0xC3, 0x33, 0xFE, 0xFF, 0x99, 0x86, 0x61, + 0x90, 0x10, 0x1F, 0x1F, 0xDE, 0xFF, 0x3F, 0x83, 0xC0, 0xFC, 0x1F, 0x09, + 0xFC, 0xFE, 0xF7, 0xF1, 0xE0, 0x40, 0x38, 0x10, 0x7C, 0x30, 0xC6, 0x20, + 0xC6, 0x40, 0xC6, 0x40, 0x7C, 0x80, 0x39, 0x9C, 0x01, 0x3E, 0x03, 0x63, + 0x02, 0x63, 0x04, 0x63, 0x0C, 0x3E, 0x08, 0x1C, 0x0E, 0x01, 0xF8, 0x3B, + 0x83, 0xB8, 0x3F, 0x01, 0xE0, 0x3E, 0x67, 0x76, 0xE3, 0xEE, 0x1C, 0xF3, + 0xC7, 0xFE, 0x3F, 0x70, 0xFF, 0xF4, 0x18, 0x63, 0x1C, 0x73, 0x8E, 0x38, + 0xE3, 0x8E, 0x18, 0x70, 0xC3, 0x06, 0x08, 0x61, 0x83, 0x0E, 0x38, 0x71, + 0xC7, 0x1C, 0x71, 0xC6, 0x38, 0xE3, 0x18, 0x40, 0x21, 0x3E, 0x45, 0x28, + 0x38, 0x70, 0xE7, 0xFF, 0xE7, 0x0E, 0x1C, 0xFC, 0x9C, 0xFF, 0xC0, 0xFC, + 0x08, 0xC4, 0x23, 0x10, 0x84, 0x62, 0x11, 0x88, 0x00, 0x3E, 0x3F, 0x9D, + 0xDC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3, 0xF1, 0xDD, 0xCF, 0xE3, 0xE0, + 0x08, 0xFF, 0xF3, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x80, 0x3E, 0x3F, 0xB8, + 0xFC, 0x70, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x0F, 0xF7, 0xF8, + 0x3C, 0x7F, 0xE7, 0xE7, 0x07, 0x0C, 0x0E, 0x07, 0x07, 0xE7, 0xE7, 0x7E, + 0x3C, 0x0E, 0x1E, 0x1E, 0x2E, 0x2E, 0x4E, 0x4E, 0x8E, 0xFF, 0xFF, 0x0E, + 0x0E, 0x0E, 0x7F, 0x3F, 0x90, 0x18, 0x0D, 0xE7, 0xFB, 0x9E, 0x07, 0x03, + 0x81, 0xF1, 0xFF, 0xE7, 0xC0, 0x3E, 0x3F, 0x9C, 0xFC, 0x0E, 0xE7, 0xFB, + 0xDF, 0xC7, 0xE3, 0xF1, 0xDD, 0xEF, 0xE3, 0xE0, 0xFF, 0xFF, 0xC0, 0xE0, + 0xE0, 0x60, 0x70, 0x30, 0x38, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x80, 0x3F, + 0x1F, 0xEE, 0x3F, 0x87, 0xE3, 0xCF, 0xC7, 0xFB, 0xCF, 0xE1, 0xF8, 0x7F, + 0x3D, 0xFE, 0x3F, 0x00, 0x3E, 0x3F, 0xBD, 0xDC, 0x7E, 0x3F, 0x1F, 0xDE, + 0xFF, 0x3B, 0x81, 0xF9, 0xCF, 0xE3, 0xC0, 0xFC, 0x00, 0x07, 0xE0, 0xFC, + 0x00, 0x07, 0xE5, 0xE0, 0x00, 0x83, 0xC7, 0xDF, 0x0C, 0x07, 0x80, 0xF8, + 0x1F, 0x01, 0x80, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFC, 0x00, 0x70, + 0x3F, 0x03, 0xE0, 0x38, 0x7D, 0xF1, 0xE0, 0x80, 0x00, 0x3E, 0x3F, 0xB8, + 0xFC, 0x70, 0x38, 0x1C, 0x1C, 0x1C, 0x1C, 0x0E, 0x00, 0x03, 0x81, 0xC0, + 0x03, 0xF0, 0x0F, 0xFC, 0x1E, 0x0E, 0x38, 0x02, 0x70, 0xE9, 0x63, 0x19, + 0xC2, 0x19, 0xC6, 0x11, 0xC6, 0x33, 0xC6, 0x32, 0x63, 0xFE, 0x73, 0xDC, + 0x3C, 0x00, 0x1F, 0xF8, 0x07, 0xF0, 0x07, 0x00, 0xF0, 0x0F, 0x80, 0xF8, + 0x1D, 0x81, 0x9C, 0x19, 0xC3, 0x8C, 0x3F, 0xE7, 0xFE, 0x70, 0x66, 0x07, + 0xE0, 0x70, 0xFF, 0x9F, 0xFB, 0x83, 0xF0, 0x7E, 0x0F, 0xFF, 0x3F, 0xF7, + 0x06, 0xE0, 0xFC, 0x1F, 0x83, 0xFF, 0xEF, 0xF8, 0x1F, 0x83, 0xFE, 0x78, + 0xE7, 0x07, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x07, 0x07, 0x78, + 0xF3, 0xFE, 0x1F, 0x80, 0xFF, 0x8F, 0xFC, 0xE0, 0xEE, 0x0E, 0xE0, 0x7E, + 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x0E, 0xE0, 0xEF, 0xFC, 0xFF, 0x80, + 0xFF, 0xFF, 0xF8, 0x1C, 0x0E, 0x07, 0xFB, 0xFD, 0xC0, 0xE0, 0x70, 0x38, + 0x1F, 0xFF, 0xF8, 0xFF, 0xFF, 0xF8, 0x1C, 0x0E, 0x07, 0xFB, 0xFD, 0xC0, + 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x00, 0x0F, 0x87, 0xF9, 0xE3, 0xB8, 0x3E, + 0x01, 0xC0, 0x38, 0xFF, 0x1F, 0xE0, 0x6E, 0x0D, 0xE3, 0x9F, 0xD0, 0xF2, + 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xFF, 0xFF, 0xFF, 0x07, 0xE0, + 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x07, + 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xE7, 0xE7, 0xE7, 0x7E, 0x3C, + 0xE0, 0xEE, 0x1C, 0xE3, 0x8E, 0x70, 0xEE, 0x0F, 0xC0, 0xFE, 0x0F, 0x70, + 0xE7, 0x0E, 0x38, 0xE1, 0xCE, 0x0E, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, + 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xF8, 0x7F, 0xE1, + 0xFF, 0x87, 0xFE, 0x1F, 0xEC, 0x7F, 0xB3, 0x7E, 0xCD, 0xFB, 0x37, 0xEC, + 0xDF, 0x9E, 0x7E, 0x79, 0xF9, 0xE7, 0xE7, 0x9C, 0xE0, 0xFE, 0x1F, 0xC3, + 0xFC, 0x7F, 0xCF, 0xD9, 0xFB, 0xBF, 0x37, 0xE7, 0xFC, 0x7F, 0x87, 0xF0, + 0xFE, 0x0E, 0x0F, 0x81, 0xFF, 0x1E, 0x3C, 0xE0, 0xEE, 0x03, 0xF0, 0x1F, + 0x80, 0xFC, 0x07, 0xE0, 0x3B, 0x83, 0x9E, 0x3C, 0x7F, 0xC0, 0xF8, 0x00, + 0xFF, 0x9F, 0xFB, 0x87, 0xF0, 0x7E, 0x0F, 0xC3, 0xFF, 0xF7, 0xFC, 0xE0, + 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x00, 0x0F, 0x81, 0xFF, 0x1E, 0x3C, 0xE0, + 0xEE, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE1, 0xBB, 0x8F, 0x9E, 0x3C, + 0x7F, 0xE0, 0xFB, 0x80, 0x08, 0xFF, 0x8F, 0xFC, 0xE0, 0xEE, 0x0E, 0xE0, + 0xEE, 0x0E, 0xFF, 0xCF, 0xFC, 0xE0, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, + 0xF0, 0x3F, 0x0F, 0xFB, 0xC7, 0xF0, 0x7E, 0x01, 0xFC, 0x1F, 0xF0, 0x3F, + 0x00, 0xFC, 0x1D, 0xC7, 0xBF, 0xE1, 0xF8, 0xFF, 0xFF, 0xC7, 0x03, 0x81, + 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0xFC, + 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, + 0xC7, 0xBF, 0xE1, 0xF0, 0x60, 0x67, 0x0E, 0x70, 0xE3, 0x0C, 0x30, 0xC3, + 0x9C, 0x19, 0x81, 0x98, 0x1F, 0x80, 0xF0, 0x0F, 0x00, 0xF0, 0x06, 0x00, + 0x61, 0xC3, 0xB8, 0xE1, 0x9C, 0x70, 0xCE, 0x3C, 0xE3, 0x36, 0x71, 0x9B, + 0x30, 0xED, 0x98, 0x36, 0x7C, 0x1B, 0x3C, 0x0F, 0x1E, 0x07, 0x8F, 0x01, + 0xC3, 0x80, 0xE1, 0x80, 0x70, 0xE7, 0x8E, 0x39, 0xC1, 0xF8, 0x1F, 0x80, + 0xF0, 0x07, 0x00, 0xF0, 0x1F, 0x81, 0x9C, 0x39, 0xC7, 0x0E, 0x70, 0xE0, + 0xE0, 0xFC, 0x39, 0xC7, 0x18, 0xC3, 0xB8, 0x36, 0x07, 0xC0, 0x70, 0x0E, + 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0xFF, 0xFF, 0xC0, 0xE0, 0xE0, 0xF0, + 0x70, 0x70, 0x70, 0x78, 0x38, 0x38, 0x1F, 0xFF, 0xF8, 0xFF, 0xEE, 0xEE, + 0xEE, 0xEE, 0xEE, 0xEE, 0xEF, 0xF0, 0x86, 0x10, 0x86, 0x10, 0x84, 0x30, + 0x84, 0x30, 0x80, 0xFF, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x7F, 0xF0, + 0x18, 0x1C, 0x3C, 0x3E, 0x36, 0x66, 0x63, 0xC3, 0xFF, 0xC0, 0xCC, 0x3F, + 0x1F, 0xEE, 0x38, 0x0E, 0x3F, 0x9E, 0xEE, 0x3B, 0x9E, 0xFF, 0x9E, 0xE0, + 0xE0, 0x38, 0x0E, 0x03, 0xBC, 0xFF, 0xBC, 0xEE, 0x1F, 0x87, 0xE1, 0xF8, + 0x7F, 0x3B, 0xFE, 0xEF, 0x00, 0x1F, 0x3F, 0xDC, 0x7C, 0x0E, 0x07, 0x03, + 0x80, 0xE3, 0x7F, 0x8F, 0x00, 0x03, 0x81, 0xC0, 0xE7, 0x77, 0xFB, 0xBF, + 0x8F, 0xC7, 0xE3, 0xF1, 0xFD, 0xEF, 0xF3, 0xB8, 0x3E, 0x3F, 0x9C, 0xDC, + 0x3F, 0xFF, 0xFF, 0x81, 0xC3, 0x7F, 0x8F, 0x00, 0x3B, 0xDD, 0xFF, 0xB9, + 0xCE, 0x73, 0x9C, 0xE7, 0x00, 0x3B, 0xBF, 0xDD, 0xFC, 0x7E, 0x3F, 0x1F, + 0x8F, 0xEF, 0x7F, 0x9D, 0xC0, 0xFC, 0x77, 0xF1, 0xF0, 0xE0, 0x70, 0x38, + 0x1D, 0xEF, 0xFF, 0x9F, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x38, + 0xFC, 0x7F, 0xFF, 0xFF, 0xFE, 0x77, 0x07, 0x77, 0x77, 0x77, 0x77, 0x77, + 0x7F, 0xE0, 0xE0, 0x70, 0x38, 0x1C, 0x7E, 0x77, 0x73, 0xF1, 0xF8, 0xFE, + 0x77, 0x39, 0xDC, 0x6E, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xEF, 0x7B, + 0xFF, 0xFE, 0x39, 0xF8, 0xE7, 0xE3, 0x9F, 0x8E, 0x7E, 0x39, 0xF8, 0xE7, + 0xE3, 0x9F, 0x8E, 0x70, 0xEF, 0x7F, 0xF8, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, + 0xC7, 0xE3, 0xF1, 0xC0, 0x1E, 0x1F, 0xE7, 0x3B, 0x87, 0xE1, 0xF8, 0x7E, + 0x1D, 0xCE, 0x7F, 0x87, 0x80, 0xEF, 0x3F, 0xEF, 0x3B, 0x87, 0xE1, 0xF8, + 0x7E, 0x1F, 0xCE, 0xFF, 0xBB, 0xCE, 0x03, 0x80, 0xE0, 0x38, 0x00, 0x3B, + 0xBF, 0xFD, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xEF, 0x7F, 0x9D, 0xC0, 0xE0, + 0x70, 0x38, 0x1C, 0xEF, 0xFF, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x3E, + 0x3F, 0xB8, 0xFC, 0x0F, 0xC3, 0xFC, 0x3F, 0xC7, 0xFF, 0x1F, 0x00, 0x73, + 0xBF, 0xF7, 0x39, 0xCE, 0x73, 0x9E, 0x70, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, + 0x3F, 0x1F, 0x8F, 0xC7, 0xFF, 0xBD, 0xC0, 0xE1, 0x98, 0x67, 0x39, 0xCC, + 0x33, 0x0D, 0xC3, 0xE0, 0x78, 0x1E, 0x07, 0x00, 0xE3, 0x1D, 0x9E, 0x66, + 0x79, 0x99, 0xE6, 0x77, 0xB8, 0xD2, 0xC3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, + 0x73, 0x80, 0x73, 0x9C, 0xE3, 0xF0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0xFC, + 0x73, 0x9C, 0xE0, 0xE1, 0xD8, 0x67, 0x39, 0xCE, 0x33, 0x0E, 0xC3, 0xE0, + 0x78, 0x1E, 0x03, 0x00, 0xC0, 0x70, 0x38, 0x0E, 0x00, 0xFE, 0xFE, 0x0E, + 0x1C, 0x38, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x37, 0x66, 0x66, 0x6E, 0xE6, + 0x66, 0x66, 0x67, 0x30, 0xFF, 0xFF, 0x80, 0xCE, 0x66, 0x66, 0x67, 0x76, + 0x66, 0x66, 0x6E, 0xC0, 0x71, 0x8E }; + +const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { + { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' + { 0, 3, 13, 6, 2, -12 }, // 0x21 '!' + { 5, 7, 5, 9, 1, -12 }, // 0x22 '"' + { 10, 10, 12, 10, 0, -11 }, // 0x23 '#' + { 25, 9, 15, 10, 1, -13 }, // 0x24 '$' + { 42, 16, 13, 16, 0, -12 }, // 0x25 '%' + { 68, 12, 13, 13, 1, -12 }, // 0x26 '&' + { 88, 3, 5, 5, 1, -12 }, // 0x27 ''' + { 90, 6, 17, 6, 1, -12 }, // 0x28 '(' + { 103, 6, 17, 6, 0, -12 }, // 0x29 ')' + { 116, 5, 6, 7, 1, -12 }, // 0x2A '*' + { 120, 7, 8, 11, 2, -7 }, // 0x2B '+' + { 127, 3, 5, 4, 1, -1 }, // 0x2C ',' + { 129, 5, 2, 6, 0, -5 }, // 0x2D '-' + { 131, 3, 2, 4, 1, -1 }, // 0x2E '.' + { 132, 5, 13, 5, 0, -12 }, // 0x2F '/' + { 141, 9, 13, 10, 1, -12 }, // 0x30 '0' + { 156, 5, 13, 10, 2, -12 }, // 0x31 '1' + { 165, 9, 13, 10, 1, -12 }, // 0x32 '2' + { 180, 8, 13, 10, 1, -12 }, // 0x33 '3' + { 193, 8, 13, 10, 2, -12 }, // 0x34 '4' + { 206, 9, 13, 10, 1, -12 }, // 0x35 '5' + { 221, 9, 13, 10, 1, -12 }, // 0x36 '6' + { 236, 9, 13, 10, 0, -12 }, // 0x37 '7' + { 251, 10, 13, 10, 0, -12 }, // 0x38 '8' + { 268, 9, 13, 10, 1, -12 }, // 0x39 '9' + { 283, 3, 9, 4, 1, -8 }, // 0x3A ':' + { 287, 3, 12, 4, 1, -8 }, // 0x3B ';' + { 292, 9, 9, 11, 1, -8 }, // 0x3C '<' + { 303, 9, 6, 11, 1, -6 }, // 0x3D '=' + { 310, 9, 9, 11, 1, -8 }, // 0x3E '>' + { 321, 9, 13, 11, 1, -12 }, // 0x3F '?' + { 336, 16, 15, 18, 0, -12 }, // 0x40 '@' + { 366, 12, 13, 13, 0, -12 }, // 0x41 'A' + { 386, 11, 13, 13, 1, -12 }, // 0x42 'B' + { 404, 12, 13, 13, 1, -12 }, // 0x43 'C' + { 424, 12, 13, 13, 1, -12 }, // 0x44 'D' + { 444, 9, 13, 12, 1, -12 }, // 0x45 'E' + { 459, 9, 13, 11, 1, -12 }, // 0x46 'F' + { 474, 11, 13, 14, 1, -12 }, // 0x47 'G' + { 492, 11, 13, 13, 1, -12 }, // 0x48 'H' + { 510, 3, 13, 6, 1, -12 }, // 0x49 'I' + { 515, 8, 13, 10, 1, -12 }, // 0x4A 'J' + { 528, 12, 13, 13, 1, -12 }, // 0x4B 'K' + { 548, 8, 13, 11, 1, -12 }, // 0x4C 'L' + { 561, 14, 13, 16, 1, -12 }, // 0x4D 'M' + { 584, 11, 13, 14, 1, -12 }, // 0x4E 'N' + { 602, 13, 13, 14, 1, -12 }, // 0x4F 'O' + { 624, 11, 13, 12, 1, -12 }, // 0x50 'P' + { 642, 13, 14, 14, 1, -12 }, // 0x51 'Q' + { 665, 12, 13, 13, 1, -12 }, // 0x52 'R' + { 685, 11, 13, 12, 1, -12 }, // 0x53 'S' + { 703, 9, 13, 12, 2, -12 }, // 0x54 'T' + { 718, 11, 13, 13, 1, -12 }, // 0x55 'U' + { 736, 12, 13, 12, 0, -12 }, // 0x56 'V' + { 756, 17, 13, 17, 0, -12 }, // 0x57 'W' + { 784, 12, 13, 12, 0, -12 }, // 0x58 'X' + { 804, 11, 13, 12, 1, -12 }, // 0x59 'Y' + { 822, 9, 13, 11, 1, -12 }, // 0x5A 'Z' + { 837, 4, 17, 6, 1, -12 }, // 0x5B '[' + { 846, 5, 13, 5, 0, -12 }, // 0x5C '\' + { 855, 4, 17, 6, 0, -12 }, // 0x5D ']' + { 864, 8, 8, 11, 1, -12 }, // 0x5E '^' + { 872, 10, 1, 10, 0, 4 }, // 0x5F '_' + { 874, 3, 2, 5, 0, -12 }, // 0x60 '`' + { 875, 10, 10, 10, 1, -9 }, // 0x61 'a' + { 888, 10, 13, 11, 1, -12 }, // 0x62 'b' + { 905, 9, 10, 10, 1, -9 }, // 0x63 'c' + { 917, 9, 13, 11, 1, -12 }, // 0x64 'd' + { 932, 9, 10, 10, 1, -9 }, // 0x65 'e' + { 944, 5, 13, 6, 1, -12 }, // 0x66 'f' + { 953, 9, 14, 11, 1, -9 }, // 0x67 'g' + { 969, 9, 13, 11, 1, -12 }, // 0x68 'h' + { 984, 3, 13, 5, 1, -12 }, // 0x69 'i' + { 989, 4, 17, 5, 0, -12 }, // 0x6A 'j' + { 998, 9, 13, 10, 1, -12 }, // 0x6B 'k' + { 1013, 3, 13, 5, 1, -12 }, // 0x6C 'l' + { 1018, 14, 10, 16, 1, -9 }, // 0x6D 'm' + { 1036, 9, 10, 11, 1, -9 }, // 0x6E 'n' + { 1048, 10, 10, 11, 1, -9 }, // 0x6F 'o' + { 1061, 10, 14, 11, 1, -9 }, // 0x70 'p' + { 1079, 9, 14, 11, 1, -9 }, // 0x71 'q' + { 1095, 6, 10, 7, 1, -9 }, // 0x72 'r' + { 1103, 9, 10, 10, 1, -9 }, // 0x73 's' + { 1115, 5, 12, 6, 1, -11 }, // 0x74 't' + { 1123, 9, 10, 11, 1, -9 }, // 0x75 'u' + { 1135, 10, 10, 10, 0, -9 }, // 0x76 'v' + { 1148, 14, 10, 14, 0, -9 }, // 0x77 'w' + { 1166, 10, 10, 10, 0, -9 }, // 0x78 'x' + { 1179, 10, 14, 10, 0, -9 }, // 0x79 'y' + { 1197, 8, 10, 9, 1, -9 }, // 0x7A 'z' + { 1207, 4, 17, 7, 1, -12 }, // 0x7B '{' + { 1216, 1, 17, 5, 2, -12 }, // 0x7C '|' + { 1219, 4, 17, 7, 2, -12 }, // 0x7D '}' + { 1228, 8, 2, 9, 0, -4 } }; // 0x7E '~' + +const GFXfont FreeSansBold9pt7b PROGMEM = { + (uint8_t *)FreeSansBold9pt7bBitmaps, + (GFXglyph *)FreeSansBold9pt7bGlyphs, + 0x20, 0x7E, 22 }; + +// Approx. 1902 bytes diff --git a/nano_font.cpp b/nano_font.cpp index 9d4803c..9a0265d 100644 --- a/nano_font.cpp +++ b/nano_font.cpp @@ -1,337 +1,6 @@ #include "nano_font.h" #include -const uint8_t ubitxBitmaps[] PROGMEM = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, - 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, - 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0, - 0xFF, 0xFF, 0xFF, 0xFF, 0x21, 0xFF, 0xE0, 0xF3, 0xF9, 0xFC, 0xFE, 0x7E, - 0x3B, 0x1D, 0x84, 0x0E, 0x70, 0x73, 0x83, 0x9C, 0x18, 0xC7, 0xFF, 0xBF, - 0xFD, 0xFF, 0xE3, 0x9C, 0x18, 0xC0, 0xC6, 0x0E, 0x7D, 0xFF, 0xEF, 0xFF, - 0x18, 0xC0, 0xC6, 0x0E, 0x70, 0x73, 0x83, 0x9C, 0x00, 0x04, 0x01, 0xF8, - 0x7F, 0xCF, 0xDE, 0xE4, 0xEE, 0x4E, 0xE4, 0x0F, 0x40, 0x7E, 0x03, 0xFC, - 0x0F, 0xE0, 0x5E, 0x04, 0xFE, 0x4F, 0xE4, 0xFF, 0x4E, 0x7F, 0xE3, 0xFC, - 0x04, 0x00, 0x40, 0x04, 0x00, 0x3C, 0x06, 0x07, 0xE0, 0x60, 0xFF, 0x0C, - 0x0C, 0x30, 0x80, 0xC3, 0x18, 0x0C, 0x31, 0x00, 0xFF, 0x30, 0x07, 0xE6, - 0x00, 0x3C, 0x60, 0x00, 0x0C, 0x7C, 0x00, 0xCF, 0xE0, 0x19, 0xC6, 0x01, - 0x98, 0x70, 0x31, 0x87, 0x03, 0x1C, 0x60, 0x60, 0xFE, 0x04, 0x07, 0xC0, - 0x0F, 0x80, 0x1F, 0xC0, 0x3D, 0xE0, 0x38, 0xE0, 0x3C, 0xE0, 0x1D, 0xC0, - 0x1F, 0xC0, 0x0F, 0x00, 0x3F, 0x8C, 0x7B, 0xDC, 0x71, 0xDC, 0xF1, 0xFC, - 0xF0, 0xF8, 0xF0, 0x78, 0x79, 0xFC, 0x7F, 0xFC, 0x3F, 0x9E, 0x00, 0x00, - 0xFF, 0xFF, 0xE6, 0x60, 0x0C, 0x71, 0x8E, 0x31, 0xC7, 0x38, 0xE3, 0x8E, - 0x38, 0xE3, 0x8E, 0x38, 0x71, 0xC7, 0x0E, 0x38, 0x70, 0xC0, 0xC3, 0x86, - 0x1C, 0x70, 0xE3, 0x8E, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xCE, 0x38, 0xE7, - 0x1C, 0x63, 0x8C, 0x00, 0x10, 0x10, 0x10, 0xFE, 0x7C, 0x38, 0x6C, 0x44, - 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x60, - 0x06, 0x00, 0x60, 0x06, 0x00, 0xFF, 0xF2, 0xFE, 0xFF, 0xFF, 0xC0, 0xFF, - 0xF0, 0x04, 0x08, 0x30, 0x60, 0x83, 0x06, 0x08, 0x10, 0x60, 0xC1, 0x06, - 0x0C, 0x10, 0x20, 0xC0, 0x3F, 0x8F, 0xF9, 0xEF, 0x78, 0xFE, 0x0F, 0xC1, - 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xE3, 0xDE, - 0xF3, 0xFE, 0x3F, 0x80, 0x80, 0x06, 0x1C, 0x7F, 0xFF, 0xE1, 0xC3, 0x87, - 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x3F, 0x8F, 0xFB, 0xEF, - 0xF8, 0x7E, 0x0F, 0xC1, 0xC0, 0x38, 0x0F, 0x03, 0xC0, 0xF0, 0x7C, 0x1F, - 0x07, 0x80, 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xE0, 0x3F, 0x8F, 0xFB, 0xCF, - 0xF0, 0xFE, 0x1E, 0x03, 0xC0, 0x70, 0x7C, 0x0F, 0xC0, 0xFC, 0x03, 0x80, - 0x7E, 0x0F, 0xC1, 0xFC, 0xFB, 0xFE, 0x3F, 0x80, 0x80, 0x07, 0xC0, 0x7C, - 0x0F, 0xC0, 0xFC, 0x1F, 0xC3, 0xBC, 0x33, 0xC7, 0x3C, 0x63, 0xCE, 0x3C, - 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3F, - 0xEF, 0xFD, 0xFF, 0xB8, 0x06, 0x00, 0xC0, 0x1F, 0xE7, 0xFE, 0xF1, 0xE0, - 0x1C, 0x03, 0x80, 0x70, 0x0F, 0xC1, 0xFC, 0xFB, 0xFE, 0x3F, 0x80, 0x80, - 0x1F, 0x87, 0xF9, 0xE7, 0xB8, 0x7E, 0x01, 0xC0, 0x3B, 0xE7, 0xFE, 0xFB, - 0xFE, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xE1, 0xDE, 0xFB, 0xFE, 0x3F, 0x80, - 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0E, 0x01, 0xC0, 0x3C, 0x03, 0x80, - 0x70, 0x0F, 0x00, 0xE0, 0x0E, 0x01, 0xE0, 0x1C, 0x01, 0xC0, 0x1C, 0x03, - 0xC0, 0x3C, 0x00, 0x3F, 0x87, 0xFC, 0xF9, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, - 0x71, 0xC3, 0xF8, 0x7F, 0xCF, 0x1E, 0xE0, 0xEE, 0x0F, 0xE0, 0xFE, 0x0E, - 0xF1, 0xE7, 0xFC, 0x3F, 0x80, 0x40, 0x3F, 0x0F, 0xFB, 0xEF, 0x70, 0xFE, - 0x0F, 0xC1, 0xF8, 0x3F, 0x0F, 0xF3, 0xEF, 0xFC, 0xFB, 0x80, 0x70, 0x0F, - 0xC3, 0xFE, 0xF3, 0xFE, 0x3F, 0x80, 0x80, 0xFF, 0x80, 0x00, 0xFF, 0xF0, - 0xFF, 0x80, 0x00, 0xFF, 0xF2, 0xDE, 0x00, 0x70, 0x1F, 0x0F, 0xE7, 0xF0, - 0xF8, 0x0E, 0x00, 0xFC, 0x03, 0xF8, 0x0F, 0xE0, 0x1F, 0x00, 0x30, 0xFF, - 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, - 0xF0, 0xC0, 0x0F, 0x80, 0x7F, 0x00, 0xFC, 0x03, 0xF0, 0x07, 0x03, 0xF1, - 0xFC, 0xFE, 0x0F, 0x80, 0xC0, 0x00, 0x1F, 0x0F, 0xF3, 0xFF, 0x78, 0xFE, - 0x0F, 0xC1, 0xC0, 0x38, 0x0F, 0x03, 0xE0, 0xF8, 0x3C, 0x07, 0x00, 0xE0, - 0x00, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xFE, - 0x00, 0xF0, 0x3C, 0x07, 0x00, 0x38, 0x38, 0x00, 0x30, 0xC0, 0x00, 0xE6, - 0x0F, 0xF1, 0x98, 0x73, 0xC7, 0xC3, 0x87, 0x0F, 0x0C, 0x1C, 0x3C, 0x30, - 0x61, 0xF1, 0xC1, 0x86, 0xC7, 0x0E, 0x1B, 0x1C, 0x38, 0xEC, 0x3B, 0xEF, - 0x38, 0xFD, 0xF8, 0x70, 0xC1, 0x80, 0xE0, 0x00, 0x01, 0xC0, 0x10, 0x03, - 0xFF, 0xC0, 0x03, 0xFF, 0x00, 0x03, 0xC0, 0x07, 0xC0, 0x07, 0xE0, 0x07, - 0xE0, 0x0F, 0xE0, 0x0E, 0xF0, 0x0E, 0xF0, 0x1E, 0x70, 0x1C, 0x78, 0x1C, - 0x78, 0x3C, 0x38, 0x3F, 0xFC, 0x3F, 0xFC, 0x7F, 0xFC, 0x70, 0x1E, 0xF0, - 0x1E, 0xF0, 0x0E, 0xE0, 0x0F, 0xFF, 0x03, 0xFF, 0xCF, 0xFF, 0xBC, 0x7E, - 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBF, 0xFE, 0xFF, 0xE3, 0xFF, 0xCF, 0x0F, - 0xBC, 0x0F, 0xF0, 0x1F, 0xC0, 0xFF, 0x03, 0xFF, 0xFE, 0xFF, 0xFB, 0xFF, - 0x80, 0x03, 0xC0, 0x1F, 0xF0, 0xFF, 0xF1, 0xF1, 0xE7, 0x81, 0xEF, 0x01, - 0xFC, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F, - 0x00, 0xEF, 0x01, 0xDE, 0x07, 0x9F, 0xFE, 0x1F, 0xFC, 0x1F, 0xE0, 0x04, - 0x00, 0xFE, 0x03, 0xFF, 0x8F, 0xFF, 0x38, 0x7E, 0xE0, 0x7B, 0x80, 0xFE, - 0x03, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x3F, - 0x80, 0xFE, 0x07, 0xBF, 0xFE, 0xFF, 0xF3, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1F, 0xFE, 0xFF, 0xF7, - 0xFF, 0xBC, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1F, 0xFF, 0xFF, - 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xE0, 0x0E, 0x00, - 0xE0, 0x0F, 0xFE, 0xFF, 0xEF, 0xFE, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, - 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x03, 0xE0, 0x0F, 0xF8, 0x1F, 0xFC, - 0x3E, 0x3E, 0x78, 0x0F, 0x70, 0x0F, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, - 0xF0, 0x7F, 0xF0, 0x7F, 0xF0, 0x7F, 0xF0, 0x07, 0x78, 0x0F, 0x7C, 0x1F, - 0x3F, 0xFF, 0x1F, 0xFB, 0x0F, 0xF3, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, - 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, - 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, - 0x80, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x01, 0xE0, 0x3C, - 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, - 0x80, 0xFE, 0x1F, 0xC3, 0xF8, 0x7F, 0xFE, 0xFF, 0xCF, 0xF0, 0x00, 0x00, - 0xE0, 0x3D, 0xC0, 0xFB, 0x83, 0xE7, 0x07, 0x8E, 0x1E, 0x1C, 0x78, 0x39, - 0xE0, 0x77, 0x80, 0xFF, 0x01, 0xFF, 0x03, 0xFE, 0x07, 0x9E, 0x0E, 0x1E, - 0x1C, 0x1E, 0x38, 0x3C, 0x70, 0x3C, 0xE0, 0x3D, 0xC0, 0x3C, 0xF0, 0x0F, - 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, - 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, - 0xFF, 0xF8, 0x1F, 0xFC, 0x0F, 0xFE, 0x07, 0xFF, 0x83, 0xFF, 0xC3, 0xFF, - 0xE1, 0xFF, 0xB0, 0xFF, 0xDC, 0x6F, 0xEE, 0x77, 0xF7, 0x3B, 0xF9, 0x9D, - 0xFC, 0xCC, 0xFE, 0x76, 0x7F, 0x3F, 0x3F, 0x8F, 0x9F, 0xC7, 0xCF, 0xE3, - 0xC7, 0xF1, 0xE3, 0xC0, 0xE0, 0x3F, 0xC0, 0xFF, 0x03, 0xFE, 0x0F, 0xFC, - 0x3F, 0xF0, 0xFE, 0xE3, 0xFB, 0x8F, 0xE7, 0x3F, 0x9E, 0xFE, 0x3B, 0xF8, - 0xFF, 0xE1, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x1F, 0xE0, 0x7F, 0x80, 0xF0, - 0x03, 0xE0, 0x07, 0xFC, 0x07, 0xFF, 0x07, 0xCF, 0xC7, 0x81, 0xF3, 0xC0, - 0x7B, 0xC0, 0x1D, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE, - 0x00, 0xFF, 0x00, 0x73, 0xC0, 0x79, 0xF0, 0x7C, 0x7F, 0xFC, 0x1F, 0xFC, - 0x07, 0xFC, 0x00, 0x20, 0x00, 0xFF, 0x07, 0xFF, 0x3F, 0xFD, 0xC3, 0xFE, - 0x07, 0xF0, 0x1F, 0x80, 0xFC, 0x0F, 0xE0, 0xFF, 0xFF, 0xBF, 0xF9, 0xFF, - 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x03, - 0xE0, 0x07, 0xFC, 0x07, 0xFF, 0x07, 0xCF, 0xC7, 0x80, 0xF3, 0xC0, 0x7B, - 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE, 0x04, - 0xFF, 0x07, 0x73, 0xC3, 0xF9, 0xF0, 0xFC, 0x7F, 0xFC, 0x1F, 0xFF, 0x07, - 0xFF, 0xC0, 0x20, 0xC0, 0xFF, 0x83, 0xFF, 0xCF, 0xFF, 0xBC, 0x3F, 0xF0, - 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xFF, 0xFB, 0xFF, 0x8F, 0xFF, 0xBC, - 0x1E, 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBC, 0x0E, 0xF0, 0x3F, 0xC0, 0xF0, - 0x0F, 0x80, 0xFF, 0xC7, 0xFF, 0xBE, 0x1E, 0xF0, 0x3B, 0xC0, 0xFF, 0x00, - 0x3F, 0x80, 0x7F, 0xE0, 0xFF, 0xE0, 0x3F, 0xC0, 0x0F, 0x00, 0x1F, 0x80, - 0x7F, 0x03, 0xFF, 0x1F, 0x7F, 0xF8, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, - 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, - 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, - 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, - 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0xC0, 0xFF, 0x07, 0x9F, 0xFE, 0x7F, 0xF0, - 0x7F, 0x80, 0x20, 0x00, 0xE0, 0x1F, 0xC0, 0x3B, 0xC0, 0xF3, 0x81, 0xE7, - 0x03, 0x8F, 0x0F, 0x0E, 0x1C, 0x1C, 0x38, 0x3C, 0x70, 0x39, 0xC0, 0x73, - 0x80, 0xE7, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x03, 0xC0, 0x07, 0x80, - 0x0F, 0x00, 0xF0, 0x38, 0x1D, 0xC1, 0xE0, 0xF7, 0x87, 0xC3, 0xDE, 0x1F, - 0x0F, 0x78, 0x7C, 0x38, 0xE3, 0xB0, 0xE3, 0x8E, 0xC7, 0x8F, 0x3B, 0x9C, - 0x1C, 0xEE, 0x70, 0x73, 0x39, 0xC1, 0xDC, 0x67, 0x07, 0x71, 0xB8, 0x0F, - 0xC7, 0xE0, 0x3E, 0x1F, 0x80, 0xF8, 0x3E, 0x01, 0xE0, 0xF0, 0x07, 0x83, - 0xC0, 0x1E, 0x0F, 0x00, 0xF0, 0x3D, 0xF0, 0x79, 0xE1, 0xE1, 0xE3, 0xC3, - 0xCF, 0x03, 0xFC, 0x07, 0xF8, 0x07, 0xE0, 0x07, 0x80, 0x0F, 0x00, 0x3F, - 0x00, 0x7F, 0x01, 0xFE, 0x07, 0x9E, 0x0F, 0x3C, 0x3C, 0x3C, 0xF8, 0x3D, - 0xE0, 0x78, 0xF0, 0x1F, 0xE0, 0x79, 0xE0, 0xF3, 0xC3, 0xC3, 0xC7, 0x87, - 0x9E, 0x07, 0x3C, 0x0F, 0x70, 0x0F, 0xE0, 0x1F, 0x80, 0x1F, 0x00, 0x3C, - 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x80, - 0x78, 0x07, 0x80, 0x78, 0x07, 0x80, 0x7C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, - 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xCE, 0x73, 0x9C, 0xE7, - 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCF, 0xFF, 0xE0, 0xC1, 0x81, 0x02, - 0x06, 0x04, 0x08, 0x18, 0x30, 0x20, 0x60, 0xC0, 0x81, 0x83, 0x02, 0x06, - 0xFF, 0xFF, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, - 0x1C, 0x71, 0xC7, 0xFF, 0xFF, 0xC0, 0x0F, 0x00, 0xF0, 0x0F, 0x01, 0xF8, - 0x1B, 0x83, 0x9C, 0x39, 0xC3, 0x0C, 0x70, 0xE7, 0x0E, 0xE0, 0x70, 0xFF, - 0xFF, 0xFF, 0xFC, 0x71, 0x86, 0x3F, 0x87, 0xFC, 0xFF, 0xEE, 0x1E, 0x01, - 0xE0, 0xFE, 0x7F, 0xEF, 0x8E, 0xE1, 0xEE, 0x1E, 0xF3, 0xEF, 0xFE, 0x7E, - 0xE1, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x7B, 0xE3, - 0xFF, 0x9F, 0xFE, 0xF8, 0xF7, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, - 0x3F, 0xC1, 0xDF, 0x9E, 0xFF, 0xE7, 0xFE, 0x00, 0x40, 0x1F, 0x83, 0xFC, - 0x7F, 0xEF, 0x0E, 0xE0, 0xEE, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0F, 0x0E, - 0x79, 0xE7, 0xFC, 0x3F, 0x80, 0x00, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, - 0x00, 0x71, 0xE7, 0x3F, 0xF7, 0xFF, 0xF0, 0xFE, 0x0F, 0xE0, 0x7E, 0x07, - 0xE0, 0x7E, 0x0F, 0xF0, 0xF7, 0x9F, 0x7F, 0xF3, 0xF7, 0x00, 0x00, 0x1F, - 0x07, 0xFC, 0x7B, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE, 0xFF, 0xFF, 0xFF, 0xE0, - 0x0E, 0x0E, 0xF1, 0xE7, 0xFC, 0x3F, 0x80, 0x40, 0x00, 0x1E, 0x3E, 0x3C, - 0x3C, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, - 0x3C, 0x3C, 0x1E, 0x73, 0xF7, 0x7F, 0xFF, 0x0F, 0xF0, 0xFE, 0x07, 0xE0, - 0x7E, 0x07, 0xE0, 0x7F, 0x0F, 0x79, 0xF7, 0xFF, 0x3F, 0x70, 0x07, 0x00, - 0x7F, 0x0F, 0x7F, 0xE3, 0xFC, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, - 0xDF, 0x3F, 0xF7, 0xFF, 0xF1, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, - 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1C, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFC, 0x39, 0xCE, 0x70, 0x1C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, - 0xCE, 0x7F, 0xFF, 0xC0, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, - 0x0E, 0xF1, 0xEF, 0x3C, 0xF7, 0x8F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x8F, - 0x3C, 0xF3, 0xCF, 0x1E, 0xF1, 0xEF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFC, 0xF7, 0xCF, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0xF8, 0x78, 0xFF, - 0x0E, 0x1F, 0xE1, 0xC3, 0xFC, 0x38, 0x7F, 0x87, 0x0F, 0xF0, 0xE1, 0xFE, - 0x1C, 0x3F, 0xC3, 0x87, 0xF8, 0x70, 0xFF, 0x0E, 0x1E, 0xEF, 0x9F, 0xFB, - 0xFF, 0xF8, 0xFE, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, - 0xF0, 0x7E, 0x0E, 0x1F, 0x81, 0xFF, 0x1F, 0xFD, 0xE1, 0xEF, 0x07, 0x70, - 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x83, 0x9E, 0x3C, 0xFF, 0xC3, 0xFC, - 0x01, 0x00, 0xF7, 0xC7, 0xFF, 0x3F, 0xFD, 0xF1, 0xEF, 0x07, 0xF8, 0x3F, - 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xBE, 0x3D, 0xFF, 0xCF, 0x7C, 0x78, - 0x83, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x00, 0x1E, 0x77, 0xF7, 0x7F, - 0xFF, 0x0F, 0xE0, 0xFE, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0xFF, 0x0F, 0xF9, - 0xF7, 0xFF, 0x3F, 0x70, 0x47, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0xEF, - 0xFF, 0xFF, 0x8E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x00, 0x3F, - 0x8F, 0xFB, 0xEF, 0xF8, 0x7F, 0x01, 0xFE, 0x1F, 0xF0, 0xFF, 0x01, 0xFC, - 0x1F, 0xC3, 0xFF, 0xF7, 0xFC, 0x08, 0x00, 0x38, 0x70, 0xE7, 0xFF, 0xFF, - 0xCE, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0F, 0x8F, 0x04, 0xF0, 0x7F, - 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, - 0x0F, 0x79, 0xF7, 0xFF, 0x3F, 0x70, 0x80, 0xF0, 0x7B, 0x83, 0x9E, 0x1C, - 0x71, 0xE3, 0x8E, 0x1E, 0x70, 0x73, 0x83, 0xB8, 0x1D, 0xC0, 0x7E, 0x03, - 0xE0, 0x1F, 0x00, 0x78, 0x00, 0xF0, 0xE1, 0xDC, 0x78, 0x77, 0x1F, 0x3D, - 0xC7, 0xCE, 0x79, 0xF3, 0x8E, 0xEC, 0xE3, 0xBB, 0x78, 0xEC, 0xFC, 0x1F, - 0x3F, 0x07, 0xCF, 0xC1, 0xF1, 0xE0, 0x7C, 0x78, 0x0E, 0x1E, 0x00, 0x78, - 0xF3, 0xC7, 0x8F, 0x78, 0x3B, 0x81, 0xFC, 0x07, 0xC0, 0x1E, 0x01, 0xF0, - 0x1F, 0xC0, 0xEF, 0x0F, 0x78, 0xF1, 0xE7, 0x87, 0x80, 0xF0, 0x7B, 0x83, - 0x9E, 0x1C, 0xF1, 0xE3, 0x8E, 0x1E, 0x70, 0x73, 0x83, 0xB8, 0x1D, 0xC0, - 0x7E, 0x03, 0xE0, 0x1F, 0x00, 0x78, 0x03, 0x80, 0x1C, 0x01, 0xE0, 0x3E, - 0x01, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x1E, 0x0F, 0x83, 0xC1, 0xE0, - 0xF0, 0x78, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0x3C, 0xF9, 0xC3, - 0x87, 0x0E, 0x1C, 0x38, 0x73, 0xC7, 0x0F, 0x07, 0x0E, 0x1C, 0x38, 0x70, - 0xE1, 0xC3, 0xE7, 0xC7, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xC3, - 0xCF, 0x0C, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0xC7, 0x3C, 0xE3, 0x8E, 0x38, - 0xE3, 0x8E, 0xF3, 0xCE, 0x00, 0x10, 0x0F, 0x85, 0xBD, 0xE1, 0xF0, 0x08, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, - 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, - 0xFC, 0x07, 0xFF, 0xFF, 0xFF, 0xC0 }; +#include "PDQ_MinLib/FreeSansBold9pt7b.h" -const GFXglyph ubitxGlyphs[] PROGMEM = { - { 0, 13, 18, 17, 2, -17 }, // 0x14 - { 30, 13, 18, 17, 2, -17 }, // 0x15 - { 60, 13, 18, 17, 2, -17 }, // 0x16 - { 90, 13, 18, 17, 2, -17 }, // 0x17 - { 120, 13, 18, 17, 2, -17 }, // 0x18 - { 150, 13, 18, 17, 2, -17 }, // 0x19 - { 180, 13, 18, 17, 2, -17 }, // 0x1A - { 210, 13, 18, 17, 2, -17 }, // 0x1B - { 240, 13, 18, 17, 2, -17 }, // 0x1C - { 270, 13, 18, 17, 2, -17 }, // 0x1D - { 300, 13, 18, 17, 2, -17 }, // 0x1E - { 330, 13, 18, 17, 2, -17 }, // 0x1F - { 360, 0, 0, 7, 0, 1 }, // 0x20 ' ' - { 360, 3, 17, 8, 3, -16 }, // 0x21 '!' - { 367, 9, 7, 11, 1, -17 }, // 0x22 '"' - { 375, 13, 18, 13, 0, -16 }, // 0x23 '#' - { 405, 12, 21, 13, 1, -17 }, // 0x24 '$' - { 437, 20, 17, 21, 1, -16 }, // 0x25 '%' - { 480, 16, 18, 17, 1, -16 }, // 0x26 '&' - { 516, 4, 7, 6, 1, -17 }, // 0x27 ''' - { 520, 6, 23, 8, 1, -17 }, // 0x28 '(' - { 538, 6, 23, 8, 1, -17 }, // 0x29 ')' - { 556, 8, 8, 9, 1, -17 }, // 0x2A '*' - { 564, 12, 11, 14, 1, -10 }, // 0x2B '+' - { 581, 3, 8, 7, 2, -3 }, // 0x2C ',' - { 584, 6, 3, 8, 1, -7 }, // 0x2D '-' - { 587, 3, 4, 7, 2, -3 }, // 0x2E '.' - { 589, 7, 17, 7, 0, -16 }, // 0x2F '/' - { 604, 11, 18, 13, 1, -16 }, // 0x30 '0' - { 629, 7, 17, 13, 2, -16 }, // 0x31 '1' - { 644, 11, 17, 13, 1, -16 }, // 0x32 '2' - { 668, 11, 18, 13, 1, -16 }, // 0x33 '3' - { 693, 12, 17, 13, 1, -16 }, // 0x34 '4' - { 719, 11, 18, 13, 1, -16 }, // 0x35 '5' - { 744, 11, 18, 13, 1, -16 }, // 0x36 '6' - { 769, 12, 17, 13, 1, -16 }, // 0x37 '7' - { 795, 12, 18, 13, 1, -16 }, // 0x38 '8' - { 822, 11, 18, 13, 1, -16 }, // 0x39 '9' - { 847, 3, 12, 8, 3, -11 }, // 0x3A ':' - { 852, 3, 16, 8, 3, -11 }, // 0x3B ';' - { 858, 12, 11, 14, 1, -10 }, // 0x3C '<' - { 875, 12, 9, 14, 1, -9 }, // 0x3D '=' - { 889, 12, 11, 14, 1, -10 }, // 0x3E '>' - { 906, 11, 18, 15, 2, -17 }, // 0x3F '?' - { 931, 22, 21, 23, 1, -17 }, // 0x40 '@' - { 989, 16, 18, 17, 1, -17 }, // 0x41 'A' - { 1025, 14, 18, 17, 2, -17 }, // 0x42 'B' - { 1057, 15, 19, 17, 1, -17 }, // 0x43 'C' - { 1093, 14, 18, 17, 2, -17 }, // 0x44 'D' - { 1125, 13, 18, 16, 2, -17 }, // 0x45 'E' - { 1155, 12, 18, 15, 2, -17 }, // 0x46 'F' - { 1182, 16, 18, 19, 1, -17 }, // 0x47 'G' - { 1218, 14, 18, 17, 2, -17 }, // 0x48 'H' - { 1250, 3, 18, 7, 2, -17 }, // 0x49 'I' - { 1257, 11, 19, 13, 1, -17 }, // 0x4A 'J' - { 1284, 15, 18, 17, 2, -17 }, // 0x4B 'K' - { 1318, 12, 18, 15, 2, -17 }, // 0x4C 'L' - { 1345, 17, 18, 20, 2, -17 }, // 0x4D 'M' - { 1384, 14, 18, 17, 2, -17 }, // 0x4E 'N' - { 1416, 17, 19, 19, 1, -17 }, // 0x4F 'O' - { 1457, 13, 18, 16, 2, -17 }, // 0x50 'P' - { 1487, 17, 19, 19, 1, -17 }, // 0x51 'Q' - { 1528, 14, 18, 17, 2, -17 }, // 0x52 'R' - { 1560, 14, 19, 16, 1, -17 }, // 0x53 'S' - { 1594, 14, 18, 15, 0, -17 }, // 0x54 'T' - { 1626, 14, 19, 17, 2, -17 }, // 0x55 'U' - { 1660, 15, 18, 16, 1, -17 }, // 0x56 'V' - { 1694, 22, 18, 23, 0, -17 }, // 0x57 'W' - { 1744, 15, 18, 16, 1, -17 }, // 0x58 'X' - { 1778, 15, 18, 16, 1, -17 }, // 0x59 'Y' - { 1812, 13, 18, 15, 1, -17 }, // 0x5A 'Z' - { 1842, 5, 23, 8, 2, -17 }, // 0x5B '[' - { 1857, 7, 17, 7, 0, -16 }, // 0x5C '\' - { 1872, 6, 23, 8, 0, -17 }, // 0x5D ']' - { 1890, 12, 11, 14, 1, -16 }, // 0x5E '^' - { 1907, 15, 2, 13, -1, 4 }, // 0x5F '_' - { 1911, 5, 3, 8, 0, -17 }, // 0x60 '`' - { 1913, 12, 14, 13, 1, -12 }, // 0x61 'a' - { 1934, 13, 19, 15, 1, -17 }, // 0x62 'b' - { 1965, 12, 14, 13, 1, -12 }, // 0x63 'c' - { 1986, 12, 19, 15, 1, -17 }, // 0x64 'd' - { 2015, 12, 14, 13, 1, -12 }, // 0x65 'e' - { 2036, 8, 18, 8, 0, -17 }, // 0x66 'f' - { 2054, 12, 18, 15, 1, -12 }, // 0x67 'g' - { 2081, 11, 18, 15, 2, -17 }, // 0x68 'h' - { 2106, 3, 18, 7, 2, -17 }, // 0x69 'i' - { 2113, 5, 23, 7, 0, -17 }, // 0x6A 'j' - { 2128, 12, 18, 13, 1, -17 }, // 0x6B 'k' - { 2155, 3, 18, 7, 2, -17 }, // 0x6C 'l' - { 2162, 19, 13, 21, 1, -12 }, // 0x6D 'm' - { 2193, 11, 13, 15, 2, -12 }, // 0x6E 'n' - { 2211, 13, 14, 15, 1, -12 }, // 0x6F 'o' - { 2234, 13, 18, 15, 1, -12 }, // 0x70 'p' - { 2264, 12, 18, 15, 1, -12 }, // 0x71 'q' - { 2291, 7, 13, 9, 2, -12 }, // 0x72 'r' - { 2303, 11, 14, 13, 1, -12 }, // 0x73 's' - { 2323, 7, 17, 8, 0, -15 }, // 0x74 't' - { 2338, 12, 14, 15, 1, -12 }, // 0x75 'u' - { 2359, 13, 13, 13, 0, -12 }, // 0x76 'v' - { 2381, 18, 13, 19, 0, -12 }, // 0x77 'w' - { 2411, 13, 13, 13, 0, -12 }, // 0x78 'x' - { 2433, 13, 18, 13, 0, -12 }, // 0x79 'y' - { 2463, 10, 13, 12, 1, -12 }, // 0x7A 'z' - { 2480, 7, 23, 9, 1, -17 }, // 0x7B '{' - { 2501, 2, 23, 7, 2, -17 }, // 0x7C '|' - { 2507, 6, 23, 9, 2, -17 }, // 0x7D '}' - { 2525, 11, 5, 14, 1, -7 }, // 0x7E '~' - { 2532, 13, 18, 17, 2, -17 } }; // 0x7F - -const GFXfont ubitx_font PROGMEM = { - (uint8_t *)ubitxBitmaps, - (GFXglyph *)ubitxGlyphs, - 0x14, - 0x7F, - 33}; - -// Approx. 3325 bytes +const GFXfont* ubitx_font = &FreeSansBold9pt7b; \ No newline at end of file diff --git a/nano_font.h b/nano_font.h index 1b56f73..9ce554a 100644 --- a/nano_font.h +++ b/nano_font.h @@ -4,6 +4,6 @@ #include #include "PDQ_MinLib/gfxfont.h" -extern const GFXfont ubitx_font; +extern const GFXfont* ubitx_font; #endif //_NANO_FONT \ No newline at end of file diff --git a/nano_gui.cpp b/nano_gui.cpp index 56c693d..a801d58 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -154,7 +154,7 @@ bool xpt2046_Init(){ void displayInit(void){ tft.begin(); - tft.setFont(&ubitx_font); + tft.setFont(ubitx_font); tft.setTextWrap(false); tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK); tft.setTextSize(1); From 9dee71f5bd0495a0d83e535558478e35a75ce229 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 3 Jan 2020 01:07:32 -0800 Subject: [PATCH 018/324] Offload settings to it's own set of files --- settings.cpp | 111 ++++++++++++++++++++++++++++++++++++++ settings.h | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 258 insertions(+) create mode 100644 settings.cpp create mode 100644 settings.h diff --git a/settings.cpp b/settings.cpp new file mode 100644 index 0000000..31b97be --- /dev/null +++ b/settings.cpp @@ -0,0 +1,111 @@ +/** + * These are the "magic" indices where these user changable settinngs are stored in the EEPROM + */ +static const uint8_t EEPROM_ADDR_MASTER_CAL = 0;//int32_t +//4 is currently unused, but may have been LSB_CAL on other versions +static const uint8_t EEPROM_ADDR_USB_CAL = 8;//uint32_t +//12 is currently unused, but may have been CW_SIDETONE on other versions? +static const uint8_t EEPROM_ADDR_VFO_A_FREQ = 16;//uint32_t +static const uint8_t EEPROM_ADDR_VFO_B_FREQ = 20;//uint32_t +static const uint8_t EEPROM_ADDR_CW_SIDETONE = 24;//uint32_t +static const uint8_t EEPROM_ADDR_CW_DIT_TIME = 28;//uint32_t +static const uint8_t EEPROM_ADDR_TOUCH_SLOPE_X = 32;//int16_t +static const uint8_t EEPROM_ADDR_TOUCH_SLOPE_Y = 36;//int16_t +static const uint8_t EEPROM_ADDR_TOUCH_OFFSET_X = 40;//int16_t +static const uint8_t EEPROM_ADDR_TOUCH_OFFSET_Y = 44;//int16_t +static const uint8_t EEPROM_ADDR_CW_DELAYTIME = 48; +static const uint8_t EEPROM_ADDR_VFO_A_MODE = 256; +static const uint8_t EEPROM_ADDR_VFO_B_MODE = 257; +static const uint8_t EEPROM_ADDR_CW_KEY_TYPE = 358; + +template +bool LoadSane(T& dest,uint16_t addr, T min, T max) +{ + T read_value; + EEPROM.get(addr,read_value); + if((min <= read_value) && (read_value <= max)){ + dest = read_value; + return true; + } + return false; +} + +#include +#include "settings.h" + +//This is the non-extern version that actually gets built +SettingsRam globalSettings; + +void LoadDefaultSettings() +{ + memset(&globalSettings,0x00,sizeof(globalSettings)); + + globalSettings.oscillatorCal = 0; + globalSettings.usbCarrierFreq = 11052000L; + + globalSettings.activeVfo = Vfo_e::VFO_A; + globalSettings.vfoA.frequency = 7150000L; + globalSettings.vfoA.mode = VFO_MODE_LSB; + globalSettings.vfoB.frequency = 14150000L; + globalSettings.vfoB.mode = VFO_MODE_USB; + + globalSettings.keyerMode = KEYER_STRAIGHT; + globalSettings.cwSideToneFreq = 800; + globalSettings.cwDitDurationMs = 100; + globalSettings.cwActiveTimeoutMs = 50; + + globalSettings.touchSlopeX = 104; + globalSettings.touchSlopeY = 137; + globalSettings.touchOffsetX = 28; + globalSettings.touchOffsetY = 29; + + globalSettings.ritOn = false; + globalSettings.ritFrequency = globalSettings.vfoA.frequency; + + globalSettings.tuningMode = TuningMode_e::TUNE_VOICE; + + globalSettings.splitOn = false; + + globalSettings.txActive = false; + globalSettings.txCatActive = false; +} + +void LoadSettingsFromEeprom() +{ + LoadSane(globalSettings.usbCarrierFreq,EEPROM_ADDR_USB_CAL,11048000L,11060000L); + LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,3500000L,30000000L); + LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,3500000L,30000000L); + LoadSane(globalSettings.cwSideToneFreq,EEPROM_ADDR_CW_SIDETONE,100,2000); + LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10,1000); + if(LoadSane(globalSettings.cwActiveTimeoutMs,EEPROM_ADDR_CW_DELAYTIME,10,100)){ + globalSettings.cwActiveTimeoutMs *= 10;//scale by 10 for legacy reasons + } + LoadSane(globalSettings.vfoA.mode,EEPROM_ADDR_VFO_A_MODE,VFO_MODE_LSB,VFO_MODE_USB); + LoadSane(globalSettings.vfoB.mode,EEPROM_ADDR_VFO_B_MODE,VFO_MODE_LSB,VFO_MODE_USB); + LoadSane(globalSettings.keyerMode,EEPROM_ADDR_CW_KEY_TYPE,KEYER_STRAIGHT,KEYER_IAMBIC_B); + + //No sanity check on these - cal your heart out + EEPROM.get(EEPROM_ADDR_MASTER_CAL,globalSettings.masterCalibration); + EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX); + EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_Y,globalSettings.touchSlopeY); + EEPROM.get(EEPROM_ADDR_TOUCH_OFFSET_X,globalSettings.touchOffsetX); + EEPROM.get(EEPROM_ADDR_TOUCH_OFFSET_Y,globalSettings.touchOffsetY); +} + +void SaveSettingsToEeprom() +{ + EEPROM.put(EEPROM_ADDR_MASTER_CAL,globalSettings.masterCalibration); + EEPROM.put(EEPROM_ADDR_USB_CAL,globalSettings.usbCarrierFreq); + EEPROM.put(EEPROM_ADDR_VFO_A_FREQ,globalSettings.vfoA.frequency); + EEPROM.put(EEPROM_ADDR_VFO_B_FREQ,globalSettings.vfoB.frequency); + EEPROM.put(EEPROM_ADDR_CW_SIDETONE,globalSettings.cwSideToneFreq); + EEPROM.put(EEPROM_ADDR_CW_DIT_TIME,globalSettings.cwDitDurationMs); + EEPROM.put(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX); + EEPROM.put(EEPROM_ADDR_TOUCH_SLOPE_Y,globalSettings.touchSlopeY); + EEPROM.put(EEPROM_ADDR_TOUCH_OFFSET_X,globalSettings.touchOffsetX); + EEPROM.put(EEPROM_ADDR_TOUCH_OFFSET_Y,globalSettings.touchOffsetY); + EEPROM.put(EEPROM_ADDR_CW_DELAYTIME,globalSettings.cwActiveTimeoutMs/10);//scale by 10 for legacy reasons + EEPROM.put(EEPROM_ADDR_VFO_A_MODE,globalSettings.vfoA.mode); + EEPROM.put(EEPROM_ADDR_VFO_B_MODE,globalSettings.vfoB.mode); + EEPROM.put(EEPROM_ADDR_CW_KEY_TYPE,globalSettings.keyerMode); +} diff --git a/settings.h b/settings.h new file mode 100644 index 0000000..17a0e14 --- /dev/null +++ b/settings.h @@ -0,0 +1,147 @@ +/* + * This class deals with all of the radio settings, + * so that other areas of the code doesn't have to + * + * Example usage: + * LoadSettingsFromEeprom(); + * Serial.println(globalSettings.vfoAFreq); + * globalSettings.vfoAFreq = 12345678; + * SaveSettingsToEeprom(); + * Serial.println(globalSettings.vfoAFreq); + */ + +#pragma once + +/* + * Loads default values for all settings + */ +void LoadDefaultSettings(); + +/* + * Loads all persistent settings from the EEPROM + */ +void LoadSettingsFromEeprom(); + +/* + * Saves all persistent settings to the EEPROM + * + * It's a little CPU-cycle-wasteful to save EVERYTHING + * each time, but keeps things simple + */ +void SaveSettingsToEeprom(); + +/* + * These are all of the settings + * Note that not all settings are saved to the EEPROM + */ +enum Vfo_e : uint8_t +{ + VFO_A, + VFO_B +}; + +enum VfoMode_e : uint16_t +{ + VFO_MODE_LSB = 2, + VFO_MODE_USB = 3 +}; + +struct VfoSettings_t +{ + uint32_t frequency; + VfoMode_e mode; +}; + +enum TuningMode_e : uint8_t +{ + TUNE_SSB, + TUNE_CW +}; + +enum KeyerMode_e : uint8_t +{ + KEYER_STRAIGHT, + KEYER_IAMBIC_A, + KEYER_IAMBIC_B +}; + +/* + * This is the definition of the settings/state variables + */ +struct SettingsRam +{ + uint32_t oscillatorCal; + uint32_t usbCarrierFreq; + + Vfo_e activeVfo; + VfoSettings_t vfoA; + VfoSettings_t vfoB; + + KeyerMode_e keyerMode; + uint32_t cwSideToneFreq; + uint32_t cwDitDurationMs; + uint16_t cwActiveTimeoutMs; + + int16_t touchSlopeX; + int16_t touchSlopeY; + int16_t touchOffsetX; + int16_t touchOffsetY; + + bool ritOn; + uint32_t ritFrequency; + + TuningMode_e tuningMode; + + bool splitOn; + + bool txActive; + bool txCatActive; + + uint32_t cwExpirationTimeMs; +}; + +//This is the shared declaration +extern SettingsRam globalSettings; + +//Some convenience functions +uint32_t GetActiveVfoFreq() +{ + if(VFO_A == globalSettings.activeVfo){ + return globalSettings.vfoA.frequency; + } + else{ + return globalSettings.vfoB.frequency; + } +} + +void SetActiveVfoFreq(uint32_t frequency) +{ + if(VFO_A == globalSettings.activeVfo) + { + globalSettings.vfoA.frequency = frequency; + } + else{ + globalSettings.vfoB.frequency = frequency; + } +} + +VfoMode_e GetActiveVfoMode() +{ + if(VFO_A == globalSettings.activeVfo){ + return globalSettings.vfoA.mode; + } + else{ + return globalSettings.vfoB.mode; + } +} + +void SetActiveVfoMode(VfoMode_e mode) +{ + if(VFO_A == globalSettings.activeVfo) + { + globalSettings.vfoA.mode = mode; + } + else{ + globalSettings.vfoB.mode = mode; + } +} \ No newline at end of file From 0bf8424ab994dcbe636f4501b113e4cf2ed76f96 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 3 Jan 2020 23:11:08 -0800 Subject: [PATCH 019/324] Get settings files compiling --- settings.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++--------- settings.h | 46 +++-------------------------------- 2 files changed, 61 insertions(+), 54 deletions(-) diff --git a/settings.cpp b/settings.cpp index 31b97be..5f5aa0b 100644 --- a/settings.cpp +++ b/settings.cpp @@ -1,3 +1,8 @@ +#include //memset +#include +#include +#include "settings.h" + /** * These are the "magic" indices where these user changable settinngs are stored in the EEPROM */ @@ -30,9 +35,6 @@ bool LoadSane(T& dest,uint16_t addr, T min, T max) return false; } -#include -#include "settings.h" - //This is the non-extern version that actually gets built SettingsRam globalSettings; @@ -62,22 +64,23 @@ void LoadDefaultSettings() globalSettings.ritOn = false; globalSettings.ritFrequency = globalSettings.vfoA.frequency; - globalSettings.tuningMode = TuningMode_e::TUNE_VOICE; + globalSettings.tuningMode = TuningMode_e::TUNE_SSB; globalSettings.splitOn = false; globalSettings.txActive = false; globalSettings.txCatActive = false; + globalSettings.cwExpirationTimeMs = 0; } void LoadSettingsFromEeprom() { - LoadSane(globalSettings.usbCarrierFreq,EEPROM_ADDR_USB_CAL,11048000L,11060000L); - LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,3500000L,30000000L); - LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,3500000L,30000000L); - LoadSane(globalSettings.cwSideToneFreq,EEPROM_ADDR_CW_SIDETONE,100,2000); - LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10,1000); - if(LoadSane(globalSettings.cwActiveTimeoutMs,EEPROM_ADDR_CW_DELAYTIME,10,100)){ + LoadSane(globalSettings.usbCarrierFreq,EEPROM_ADDR_USB_CAL,11048000UL,11060000UL); + LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,3500000UL,30000000UL); + LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,3500000UL,30000000UL); + LoadSane(globalSettings.cwSideToneFreq,EEPROM_ADDR_CW_SIDETONE,100UL,2000UL); + LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10UL,1000UL); + if(LoadSane(globalSettings.cwActiveTimeoutMs,EEPROM_ADDR_CW_DELAYTIME,10U,100U)){ globalSettings.cwActiveTimeoutMs *= 10;//scale by 10 for legacy reasons } LoadSane(globalSettings.vfoA.mode,EEPROM_ADDR_VFO_A_MODE,VFO_MODE_LSB,VFO_MODE_USB); @@ -85,7 +88,7 @@ void LoadSettingsFromEeprom() LoadSane(globalSettings.keyerMode,EEPROM_ADDR_CW_KEY_TYPE,KEYER_STRAIGHT,KEYER_IAMBIC_B); //No sanity check on these - cal your heart out - EEPROM.get(EEPROM_ADDR_MASTER_CAL,globalSettings.masterCalibration); + EEPROM.get(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal); EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX); EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_Y,globalSettings.touchSlopeY); EEPROM.get(EEPROM_ADDR_TOUCH_OFFSET_X,globalSettings.touchOffsetX); @@ -94,7 +97,7 @@ void LoadSettingsFromEeprom() void SaveSettingsToEeprom() { - EEPROM.put(EEPROM_ADDR_MASTER_CAL,globalSettings.masterCalibration); + EEPROM.put(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal); EEPROM.put(EEPROM_ADDR_USB_CAL,globalSettings.usbCarrierFreq); EEPROM.put(EEPROM_ADDR_VFO_A_FREQ,globalSettings.vfoA.frequency); EEPROM.put(EEPROM_ADDR_VFO_B_FREQ,globalSettings.vfoB.frequency); @@ -109,3 +112,45 @@ void SaveSettingsToEeprom() EEPROM.put(EEPROM_ADDR_VFO_B_MODE,globalSettings.vfoB.mode); EEPROM.put(EEPROM_ADDR_CW_KEY_TYPE,globalSettings.keyerMode); } + +uint32_t GetActiveVfoFreq() +{ + if(VFO_A == globalSettings.activeVfo){ + return globalSettings.vfoA.frequency; + } + else{ + return globalSettings.vfoB.frequency; + } +} + +void SetActiveVfoFreq(uint32_t frequency) +{ + if(VFO_A == globalSettings.activeVfo) + { + globalSettings.vfoA.frequency = frequency; + } + else{ + globalSettings.vfoB.frequency = frequency; + } +} + +VfoMode_e GetActiveVfoMode() +{ + if(VFO_A == globalSettings.activeVfo){ + return globalSettings.vfoA.mode; + } + else{ + return globalSettings.vfoB.mode; + } +} + +void SetActiveVfoMode(VfoMode_e mode) +{ + if(VFO_A == globalSettings.activeVfo) + { + globalSettings.vfoA.mode = mode; + } + else{ + globalSettings.vfoB.mode = mode; + } +} diff --git a/settings.h b/settings.h index 17a0e14..4d2bd39 100644 --- a/settings.h +++ b/settings.h @@ -96,7 +96,6 @@ struct SettingsRam bool txActive; bool txCatActive; - uint32_t cwExpirationTimeMs; }; @@ -104,44 +103,7 @@ struct SettingsRam extern SettingsRam globalSettings; //Some convenience functions -uint32_t GetActiveVfoFreq() -{ - if(VFO_A == globalSettings.activeVfo){ - return globalSettings.vfoA.frequency; - } - else{ - return globalSettings.vfoB.frequency; - } -} - -void SetActiveVfoFreq(uint32_t frequency) -{ - if(VFO_A == globalSettings.activeVfo) - { - globalSettings.vfoA.frequency = frequency; - } - else{ - globalSettings.vfoB.frequency = frequency; - } -} - -VfoMode_e GetActiveVfoMode() -{ - if(VFO_A == globalSettings.activeVfo){ - return globalSettings.vfoA.mode; - } - else{ - return globalSettings.vfoB.mode; - } -} - -void SetActiveVfoMode(VfoMode_e mode) -{ - if(VFO_A == globalSettings.activeVfo) - { - globalSettings.vfoA.mode = mode; - } - else{ - globalSettings.vfoB.mode = mode; - } -} \ No newline at end of file +uint32_t GetActiveVfoFreq(); +void SetActiveVfoFreq(uint32_t frequency); +VfoMode_e GetActiveVfoMode(); +void SetActiveVfoMode(VfoMode_e mode); From 39168d663e4558ab766c201b1542ea3155444401 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 3 Jan 2020 23:11:55 -0800 Subject: [PATCH 020/324] Use settings in all files. Compiles, but untested --- keyer.cpp | 164 +++++-------- morse.cpp | 20 +- nano_gui.cpp | 54 ++--- setup.cpp | 145 ++++++------ ubitx.h | 84 +------ ubitx_cat.cpp | 49 ++-- ubitx_si5351.cpp | 5 +- ubitx_ui.cpp | 200 ++++++++-------- ubitx_v6.3.1_code.ino | 519 +++++++++++------------------------------- 9 files changed, 418 insertions(+), 822 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index aa4fdc2..dbbf4e7 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -1,4 +1,5 @@ #include +#include "settings.h" #include "ubitx.h" /** @@ -28,72 +29,27 @@ */ //CW ADC Range -int cwAdcSTFrom = 0; -int cwAdcSTTo = 50; -int cwAdcBothFrom = 51; -int cwAdcBothTo = 300; -int cwAdcDotFrom = 301; -int cwAdcDotTo = 600; -int cwAdcDashFrom = 601; -int cwAdcDashTo = 800; -//byte cwKeyType = 0; //0: straight, 1 : iambica, 2: iambicb +static const unsigned int cwAdcSTFrom = 0; +static const unsigned int cwAdcSTTo = 50; +static const unsigned int cwAdcBothFrom = cwAdcSTTo + 1; +static const unsigned int cwAdcBothTo = 300; +static const unsigned int cwAdcDotFrom = cwAdcBothTo + 1; +static const unsigned int cwAdcDotTo = 600; +static const unsigned int cwAdcDashFrom = cwAdcDotTo + 1; +static const unsigned int cwAdcDashTo = 800; -byte delayBeforeCWStartTime = 50; +static const unsigned int delayBeforeCWStartTime = 50; - - - -// in milliseconds, this is the parameter that determines how long the tx will hold between cw key downs -//#define CW_TIMEOUT (600l) //Change to CW Delaytime for value save to eeprom -#define PADDLE_DOT 1 -#define PADDLE_DASH 2 -#define PADDLE_BOTH 3 -#define PADDLE_STRAIGHT 4 - -//we store the last padde's character -//to alternatively send dots and dashes -//when both are simultaneously pressed -char lastPaddle = 0; - -/* -//reads the analog keyer pin and reports the paddle -byte getPaddle(){ - int paddle = analogRead(ANALOG_KEYER); - //handle the ptt as the straight key - - if (digitalRead(PTT) == 0) - return PADDLE_STRAIGHT; - - if (paddle > 800) // above 4v is up - return 0; - - if (!Iambic_Key) - return PADDLE_STRAIGHT; - - if (paddle > 600) // 4-3v is dot - return PADDLE_DASH; - else if (paddle > 300) //1-2v is dash - return PADDLE_DOT; - else if (paddle > 50) - return PADDLE_BOTH; //both are between 1 and 2v - else - return PADDLE_STRAIGHT; //less than 1v is the straight key -} -*/ /** * Starts transmitting the carrier with the sidetone * It assumes that we have called cwTxStart and not called cwTxStop * each time it is called, the cwTimeOut is pushed further into the future */ void cwKeydown(){ + tone(CW_TONE, globalSettings.cwSideToneFreq); + digitalWrite(CW_KEY, 1); - keyDown = 1; //tracks the CW_KEY - tone(CW_TONE, (int)sideTone); - digitalWrite(CW_KEY, 1); - - //Modified by KD8CEC, for CW Delay Time save to eeprom - //cwTimeout = millis() + CW_TIMEOUT; - cwTimeout = millis() + cwDelayTime * 10; + globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; } /** @@ -101,13 +57,10 @@ void cwKeydown(){ * Pushes the cwTimeout further into the future */ void cwKeyUp(){ - keyDown = 0; //tracks the CW_KEY noTone(CW_TONE); - digitalWrite(CW_KEY, 0); + digitalWrite(CW_KEY, 0); - //Modified by KD8CEC, for CW Delay Time save to eeprom - //cwTimeout = millis() + CW_TIMEOUT; - cwTimeout = millis() + cwDelayTime * 10; + globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; } //Variables for Ron's new logic @@ -119,16 +72,14 @@ void cwKeyUp(){ enum KSTYPE {IDLE, CHK_DIT, CHK_DAH, KEYED_PREP, KEYED, INTER_ELEMENT }; static unsigned long ktimer; unsigned char keyerState = IDLE; +uint8_t keyerControl = 0; //Below is a test to reduce the keying error. do not delete lines //create by KD8CEC for compatible with new CW Logic -char update_PaddleLatch(byte isUpdateKeyState) { +char update_PaddleLatch(bool isUpdateKeyState) { unsigned char tmpKeyerControl = 0; int paddle = analogRead(ANALOG_KEYER); - //diagnostic, VU2ESE - //itoa(paddle, b, 10); - //printLine2(b); //use the PTT as the key for tune up, quick QSOs if (digitalRead(PTT) == 0) @@ -138,18 +89,17 @@ char update_PaddleLatch(byte isUpdateKeyState) { else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo) tmpKeyerControl |= DIT_L; else if (paddle >= cwAdcBothFrom && paddle <= cwAdcBothTo) - tmpKeyerControl |= (DAH_L | DIT_L) ; - else - { - if (Iambic_Key) + tmpKeyerControl |= (DAH_L | DIT_L) ; + else{ + if (KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode) tmpKeyerControl = 0 ; else if (paddle >= cwAdcSTFrom && paddle <= cwAdcSTTo) tmpKeyerControl = DIT_L ; else - tmpKeyerControl = 0 ; + tmpKeyerControl = 0 ; } - if (isUpdateKeyState == 1) + if (isUpdateKeyState) keyerControl |= tmpKeyerControl; return tmpKeyerControl; @@ -160,22 +110,24 @@ char update_PaddleLatch(byte isUpdateKeyState) { // modified by KD8CEC ******************************************************************************/ void cwKeyer(void){ - lastPaddle = 0; bool continue_loop = true; unsigned tmpKeyControl = 0; - if( Iambic_Key ) { - while(continue_loop) { - switch (keyerState) { + if(KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode){ + while(continue_loop){ + switch(keyerState){ case IDLE: tmpKeyControl = update_PaddleLatch(0); - if ( tmpKeyControl == DAH_L || tmpKeyControl == DIT_L || - tmpKeyControl == (DAH_L | DIT_L) || (keyerControl & 0x03)) { - update_PaddleLatch(1); + if((tmpKeyControl == DAH_L)//Currently dah + ||(tmpKeyControl == DIT_L)//Currently dit + ||(tmpKeyControl == (DAH_L | DIT_L))//Currently both + ||( keyerControl & (DAH_L | DIT_L))){//Resolving either + update_PaddleLatch(true); keyerState = CHK_DIT; - }else{ - if (0 < cwTimeout && cwTimeout < millis()){ - cwTimeout = 0; + } + else{ + if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){ + globalSettings.cwExpirationTimeMs = 0; stopTx(); } continue_loop = false; @@ -185,7 +137,7 @@ void cwKeyer(void){ case CHK_DIT: if (keyerControl & DIT_L) { keyerControl |= DIT_PROC; - ktimer = cwSpeed; + ktimer = globalSettings.cwDitDurationMs; keyerState = KEYED_PREP; }else{ keyerState = CHK_DAH; @@ -194,7 +146,7 @@ void cwKeyer(void){ case CHK_DAH: if (keyerControl & DAH_L) { - ktimer = cwSpeed*3; + ktimer = 3*globalSettings.cwDitDurationMs; keyerState = KEYED_PREP; }else{ keyerState = IDLE; @@ -203,13 +155,11 @@ void cwKeyer(void){ case KEYED_PREP: //modified KD8CEC - if (!inTx){ + if (!globalSettings.txActive){ //DelayTime Option active_delay(delayBeforeCWStartTime * 2); - - keyDown = 0; - cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT; - startTx(TX_CW); + globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; + startTx(TuningMode_e::TUNE_CW); } ktimer += millis(); // set ktimer to interval end time keyerControl &= ~(DIT_L + DAH_L); // clear both paddle latch bits @@ -220,10 +170,11 @@ void cwKeyer(void){ case KEYED: if (millis() > ktimer) { // are we at end of key down ? - cwKeyUp(); - ktimer = millis() + cwSpeed; // inter-element time + cwKeyUp(); + ktimer = millis() + (globalSettings.cwDitDurationMs / 10); // inter-element time keyerState = INTER_ELEMENT; // next state - }else if (keyerControl & IAMBICB) { + } + else if(KeyerMode_e::KEYER_IAMBIC_B == globalSettings.keyerMode){ update_PaddleLatch(1); // early paddle latch in Iambic B mode } break; @@ -246,20 +197,19 @@ void cwKeyer(void){ checkCAT(); } //end of while } - else{ + else{//KEYER_STRAIGHT while(1){ char state = update_PaddleLatch(0); - // Serial.println((int)state); + // Serial.println((int)state); if (state == DIT_L) { // if we are here, it is only because the key is pressed - if (!inTx){ - startTx(TX_CW); + if (!globalSettings.txActive){ + startTx(TuningMode_e::TUNE_CW); //DelayTime Option active_delay(delayBeforeCWStartTime * 2); - - keyDown = 0; - cwTimeout = millis() + cwDelayTime * 10; //+ CW_TIMEOUT; + + globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwDitDurationMs; } cwKeydown(); @@ -269,24 +219,16 @@ void cwKeyer(void){ cwKeyUp(); } else{ - if (0 < cwTimeout && cwTimeout < millis()){ - cwTimeout = 0; - keyDown = 0; + if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){ + globalSettings.cwExpirationTimeMs = 0; stopTx(); } - //if (!cwTimeout) //removed by KD8CEC - // return; - // got back to the beginning of the loop, if no further activity happens on straight key - // we will time out, and return out of this routine - //delay(5); - //delay_background(5, 3); //removed by KD8CEC - //continue; //removed by KD8CEC - return; //Tx stop control by Main Loop + return;//Tx stop control by Main Loop } checkCAT(); } //end of while - } //end of elese + }//end of else KEYER_STRAIGHT } diff --git a/morse.cpp b/morse.cpp index d1b6dd5..d052138 100644 --- a/morse.cpp +++ b/morse.cpp @@ -1,5 +1,6 @@ #include #include "ubitx.h" +#include "settings.h" #include "morse.h" /* * Each byte of the morse table stores one letter. @@ -8,10 +9,9 @@ * The first zero after the 1s indicates the start of the letter, it MUST be discarded */ -extern int cwSpeed; struct Morse { char letter; - unsigned char code; + unsigned char code; }; static const PROGMEM struct Morse morse_table[] = { @@ -51,8 +51,8 @@ static const PROGMEM struct Morse morse_table[] = { {'8', 0xdc}, // 11011100 {'9', 0xde}, // 11011110 {'0', 0xdf}, // 11011111 -{'.', 0xd5}, // 110010101 -{',', 0xd3}, // 110110011 //AD7U 20191217 +{'.', 0xd5}, // 11010101 +{',', 0xd3}, // 11010011 //AD7U 20191217 {'?', 0xcc}, // 11001100 //AD7U 20191217 - Added }; @@ -61,7 +61,7 @@ static void morseLetter(char c){ //handle space character as three dashes if (c == ' '){ - active_delay(cwSpeed * 9); + active_delay(9 * globalSettings.cwDitDurationMs); Serial.print(' '); return; } @@ -79,18 +79,18 @@ static void morseLetter(char c){ //now we are at the first zero, skip and carry on mask = mask >> 1; while(mask){ - tone(CW_TONE, sideTone,10000); + tone(CW_TONE, globalSettings.cwSideToneFreq,10000); if (mask & code){ - delay(3 * (int)cwSpeed); + delay(3 * globalSettings.cwDitDurationMs); //Serial.print('-'); } else{ - delay((int)cwSpeed); + delay(globalSettings.cwDitDurationMs); //Serial.print('.'); } //Serial.print('#'); noTone(CW_TONE); - delay((int)cwSpeed); // space between dots and dashes + delay(globalSettings.cwDitDurationMs); // space between dots and dashes mask = mask >> 1; } //Serial.println('@'); @@ -107,7 +107,7 @@ void morseText(char *text){ delay(1000); // } - Serial.println(sideTone); + Serial.println(globalSettings.cwSideToneFreq); while(*text){ morseLetter(*text++); } diff --git a/nano_gui.cpp b/nano_gui.cpp index a801d58..0c532d0 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -1,5 +1,5 @@ #include -#include +#include "settings.h" #include "ubitx.h" #include "nano_gui.h" @@ -8,30 +8,18 @@ struct Point ts_point; -//filled from a test run of calibration routine -int slope_x=104, slope_y=137, offset_x=28, offset_y=29; - void readTouchCalibration(){ - EEPROM.get(SLOPE_X, slope_x); - EEPROM.get(SLOPE_Y, slope_y); - EEPROM.get(OFFSET_X, offset_x); - EEPROM.get(OFFSET_Y, offset_y); - -/* - //for debugging - Serial.print(slope_x); Serial.print(' '); - Serial.print(slope_y); Serial.print(' '); - Serial.print(offset_x); Serial.print(' '); - Serial.println(offset_y); Serial.println(' '); -*/ - + LoadSettingsFromEeprom(); + /* for debugging + Serial.print(globalSettings.touchSlopeX); Serial.print(' '); + Serial.print(globalSettings.touchSlopeY); Serial.print(' '); + Serial.print(globalSettings.touchOffsetX); Serial.print(' '); + Serial.println(globalSettings.touchOffsetY); Serial.println(' '); + //*/ } void writeTouchCalibration(){ - EEPROM.put(SLOPE_X, slope_x); - EEPROM.put(SLOPE_Y, slope_y); - EEPROM.put(OFFSET_X, offset_x); - EEPROM.put(OFFSET_Y, offset_y); + SaveSettingsToEeprom(); } #define Z_THRESHOLD 400 @@ -118,7 +106,7 @@ static void touch_update(){ } -boolean readTouch(){ +bool readTouch(){ touch_update(); if (zraw >= Z_THRESHOLD) { ts_point.x = xraw; @@ -130,8 +118,8 @@ boolean readTouch(){ } void scaleTouch(struct Point *p){ - p->x = ((long)(p->x - offset_x) * 10l)/ (long)slope_x; - p->y = ((long)(p->y - offset_y) * 10l)/ (long)slope_y; + p->x = ((long)(p->x - globalSettings.touchOffsetX) * 10L)/ (long)globalSettings.touchSlopeX; + p->y = ((long)(p->y - globalSettings.touchOffsetY) * 10L)/ (long)globalSettings.touchSlopeY; //Serial.print(p->x); Serial.print(",");Serial.println(p->y); } @@ -176,7 +164,7 @@ void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c tft.drawFastVLine(x,y,l,c); } -void displayClear(unsigned int color){ +void displayClear(unsigned int color){ tft.fillRect(0,0,320,240,color); } @@ -283,14 +271,14 @@ void setupTouch(){ // we average two readings and divide them by half and store them as scaled integers 10 times their actual, fractional value //the x points are located at 20 and 300 on x axis, hence, the delta x is 280, we take 28 instead, to preserve fractional value, //there are two readings (x1,x2) and (x3, x4). Hence, we have to divide by 28 * 2 = 56 - slope_x = ((x4 - x3) + (x2 - x1))/56; + globalSettings.touchSlopeX = ((x4 - x3) + (x2 - x1))/56; //the y points are located at 20 and 220 on the y axis, hence, the delta is 200. we take it as 20 instead, to preserve the fraction value //there are two readings (y1, y2) and (y3, y4). Hence we have to divide by 20 * 2 = 40 - slope_y = ((y3 - y1) + (y4 - y2))/40; + globalSettings.touchSlopeY = ((y3 - y1) + (y4 - y2))/40; //x1, y1 is at 20 pixels - offset_x = x1 + -((20 * slope_x)/10); - offset_y = y1 + -((20 * slope_y)/10); + globalSettings.touchOffsetX = x1 + -((20 * globalSettings.touchSlopeX)/10); + globalSettings.touchOffsetY = y1 + -((20 * globalSettings.touchSlopeY)/10); /* Serial.print(x1);Serial.print(':');Serial.println(y1); @@ -299,10 +287,10 @@ void setupTouch(){ Serial.print(x4);Serial.print(':');Serial.println(y4); //for debugging - Serial.print(slope_x); Serial.print(' '); - Serial.print(slope_y); Serial.print(' '); - Serial.print(offset_x); Serial.print(' '); - Serial.println(offset_y); Serial.println(' '); + Serial.print(globalSettings.touchSlopeX); Serial.print(' '); + Serial.print(globalSettings.touchSlopeY); Serial.print(' '); + Serial.print(globalSettings.touchOffsetX); Serial.print(' '); + Serial.println(globalSettings.touchOffsetY); Serial.println(' '); */ writeTouchCalibration(); displayClear(DISPLAY_BLACK); diff --git a/setup.cpp b/setup.cpp index c37f433..798ae46 100644 --- a/setup.cpp +++ b/setup.cpp @@ -1,6 +1,7 @@ #include #include #include "morse.h" +#include "settings.h" #include "ubitx.h" #include "nano_gui.h" @@ -22,7 +23,6 @@ void setupExit(){ } //this is used by the si5351 routines in the ubitx_5351 file -extern int32_t calibration; extern uint32_t si5351bx_vcoa; void setupFreq(){ @@ -32,12 +32,15 @@ void setupFreq(){ displayDialog("Set Frequency", "Push TUNE to Save"); //round off the the nearest khz - frequency = (frequency/1000l)* 1000l; - setFrequency(frequency); - + { + uint32_t freq = GetActiveVfoFreq(); + freq = (freq/1000l)* 1000l; + setFrequency(freq); + } + displayRawText("You should have a", 20, 50, DISPLAY_CYAN, DISPLAY_NAVY); displayRawText("signal exactly at ", 20, 75, DISPLAY_CYAN, DISPLAY_NAVY); - ltoa(frequency/1000l, c, 10); + ltoa(GetActiveVfoFreq()/1000l, c, 10); strcat(c, " KHz"); displayRawText(c, 20, 100, DISPLAY_CYAN, DISPLAY_NAVY); @@ -47,38 +50,38 @@ void setupFreq(){ active_delay(100); active_delay(100); - prev_calibration = calibration; - calibration = 0; + prev_calibration = globalSettings.oscillatorCal; + globalSettings.oscillatorCal = 0; // ltoa(calibration/8750, c, 10); // strcpy(b, c); // strcat(b, "Hz"); -// printLine2(b); +// printLine2(b); while (!btnDown()) { knob = enc_read(); if (knob != 0) - calibration += knob * 875; + globalSettings.oscillatorCal += knob * 875; /* else if (knob < 0) calibration -= 875; */ else continue; //don't update the frequency or the display - si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off - si5351_set_calibration(calibration); - setFrequency(frequency); + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the cardrier oscillator anyway, cw tx switches it off + si5351_set_calibration(globalSettings.oscillatorCal); + setFrequency(GetActiveVfoFreq()); //displayRawText("Rotate to zerobeat", 20, 120, DISPLAY_CYAN, DISPLAY_NAVY); - ltoa(calibration, b, 10); + ltoa(globalSettings.oscillatorCal, b, 10); displayText(b, 100, 140, 100, 26, DISPLAY_CYAN, DISPLAY_NAVY, DISPLAY_WHITE); } - EEPROM.put(MASTER_CAL, calibration); + SaveSettingsToEeprom(); initOscillators(); - si5351_set_calibration(calibration); - setFrequency(frequency); + si5351_set_calibration(globalSettings.oscillatorCal); + setFrequency(GetActiveVfoFreq()); //debounce and delay while(btnDown()) @@ -90,34 +93,34 @@ void setupBFO(){ int knob = 0; unsigned long prevCarrier; - prevCarrier = usbCarrier; + prevCarrier = globalSettings.usbCarrierFreq; displayDialog("Set BFO", "Press TUNE to Save"); - usbCarrier = 11053000l; - si5351bx_setfreq(0, usbCarrier); - printCarrierFreq(usbCarrier); + globalSettings.usbCarrierFreq = 11053000l; + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); + printCarrierFreq(globalSettings.usbCarrierFreq); while (!btnDown()){ knob = enc_read(); if (knob != 0) - usbCarrier -= 50 * knob; + globalSettings.usbCarrierFreq -= 50 * knob; else continue; //don't update the frequency or the display - si5351bx_setfreq(0, usbCarrier); - setFrequency(frequency); - printCarrierFreq(usbCarrier); + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); + setFrequency(GetActiveVfoFreq()); + printCarrierFreq(globalSettings.usbCarrierFreq); active_delay(100); } - EEPROM.put(USB_CAL, usbCarrier); - si5351bx_setfreq(0, usbCarrier); - setFrequency(frequency); + SaveSettingsToEeprom(); + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); + setFrequency(GetActiveVfoFreq()); updateDisplay(); - menuOn = 0; + setupExit(); } void setupCwDelay(){ @@ -127,93 +130,79 @@ void setupCwDelay(){ displayDialog("Set CW T/R Delay", "Press tune to Save"); active_delay(500); - prev_cw_delay = cwDelayTime; + prev_cw_delay = globalSettings.cwActiveTimeoutMs; - itoa(10 * (int)cwDelayTime, b, 10); + ltoa(globalSettings.cwActiveTimeoutMs, b, 10); strcat(b, " msec"); displayText(b, 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); while (!btnDown()){ knob = enc_read(); - if (knob < 0 && cwDelayTime > 10) - cwDelayTime -= 10; - else if (knob > 0 && cwDelayTime < 100) - cwDelayTime += 10; + if (knob < 0 && globalSettings.cwActiveTimeoutMs > 100) + globalSettings.cwActiveTimeoutMs -= 100; + else if (knob > 0 && globalSettings.cwActiveTimeoutMs < 1000) + globalSettings.cwActiveTimeoutMs += 100; else continue; //don't update the frequency or the display - itoa(10 * (int)cwDelayTime, b, 10); + ltoa(globalSettings.cwActiveTimeoutMs, b, 10); strcat(b, " msec"); displayText(b, 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); } - EEPROM.put(CW_DELAYTIME, cwDelayTime); - - -// cwDelayTime = getValueByKnob(10, 1000, 50, cwDelayTime, "CW Delay>", " msec"); - + SaveSettingsToEeprom(); active_delay(500); - menuOn = 0; + setupExit(); } void setupKeyer(){ - int tmp_key, knob; - displayDialog("Set CW Keyer", "Press tune to Save"); - - if (!Iambic_Key) + + if(KeyerMode_e::KEYER_STRAIGHT == globalSettings.keyerMode){ displayText("< Hand Key >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); - else if (keyerControl & IAMBICB) + } + else if(KeyerMode_e::KEYER_IAMBIC_A == globalSettings.keyerMode){ displayText("< Iambic A >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); - else + } + else{ displayText("< Iambic B >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + } - if (!Iambic_Key) - tmp_key = 0; //hand key - else if (keyerControl & IAMBICB) - tmp_key = 2; //Iambic B - else - tmp_key = 1; - + int knob = 0; + uint32_t tmp_mode = globalSettings.keyerMode; while (!btnDown()) { knob = enc_read(); - if (knob == 0){ + if(knob == 0){ active_delay(50); continue; } - if (knob < 0 && tmp_key > 0) - tmp_key--; - if (knob > 0) - tmp_key++; - if (tmp_key > 2) - tmp_key = 0; - - if (tmp_key == 0) + if(knob < 0 && tmp_mode > KeyerMode_e::KEYER_STRAIGHT){ + tmp_mode--; + } + if(knob > 0 && tmp_mode < KeyerMode_e::KEYER_IAMBIC_B){ + tmp_mode++; + } + + if (KeyerMode_e::KEYER_STRAIGHT == tmp_mode){ displayText("< Hand Key >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); - else if (tmp_key == 1) + } + else if(KeyerMode_e::KEYER_IAMBIC_A == tmp_mode){ displayText("< Iambic A >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); - else if (tmp_key == 2) + } + else if (KeyerMode_e::KEYER_IAMBIC_B == tmp_mode){ displayText("< Iambic B >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + } } active_delay(500); - if (tmp_key == 0) - Iambic_Key = false; - else if (tmp_key == 1){ - Iambic_Key = true; - keyerControl &= ~IAMBICB; - } - else if (tmp_key == 2){ - Iambic_Key = true; - keyerControl |= IAMBICB; - } - - EEPROM.put(CW_KEY_TYPE, tmp_key); + + globalSettings.keyerMode = tmp_mode; + SaveSettingsToEeprom(); - menuOn = 0; + setupExit(); } static const unsigned int COLOR_TEXT = DISPLAY_WHITE; diff --git a/ubitx.h b/ubitx.h index 10fdc63..196e759 100644 --- a/ubitx.h +++ b/ubitx.h @@ -1,3 +1,4 @@ +#include "settings.h" /* The ubitx is powered by an arduino nano. The pin assignment is as folows * @@ -56,7 +57,6 @@ it uses an ILI9341 display controller and an XPT2046 touch controller. * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. */ extern char c[30], b[30]; -extern char printBuff[2][20]; //mirrors what is showing on the two lines of the display /** * The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig. @@ -69,37 +69,6 @@ extern char printBuff[2][20]; //mirrors what is showing on the two lines of the */ -/** - * These are the indices where these user changable settinngs are stored in the EEPROM - */ -#define MASTER_CAL 0 -#define LSB_CAL 4 -#define USB_CAL 8 -#define SIDE_TONE 12 -//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values -#define VFO_A 16 -#define VFO_B 20 -#define CW_SIDETONE 24 -#define CW_SPEED 28 -// the screen calibration parameters : int slope_x=104, slope_y=137, offset_x=28, offset_y=29; -#define SLOPE_X 32 -#define SLOPE_Y 36 -#define OFFSET_X 40 -#define OFFSET_Y 44 -#define CW_DELAYTIME 48 - -//These are defines for the new features back-ported from KD8CEC's software -//these start from beyond 256 as Ian, KD8CEC has kept the first 256 bytes free for the base version -#define VFO_A_MODE 256 // 2: LSB, 3: USB -#define VFO_B_MODE 257 - -//values that are stroed for the VFO modes -#define VFO_MODE_LSB 2 -#define VFO_MODE_USB 3 - -// handkey, iambic a, iambic b : 0,1,2f -#define CW_KEY_TYPE 358 - /** * The uBITX is an upconnversion transceiver. The first IF is at 45 MHz. * The first IF frequency is not exactly at 45 Mhz but about 5 khz lower, @@ -121,62 +90,23 @@ extern char printBuff[2][20]; //mirrors what is showing on the two lines of the // limits the tuning and working range of the ubitx between 3 MHz and 30 MHz #define LOWEST_FREQ (100000l) #define HIGHEST_FREQ (30000000l) +static const uint32_t THRESHOLD_USB_LSB = 10000000L; -//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes -//these are the parameter passed to startTx -#define TX_SSB 0 -#define TX_CW 1 - -extern char ritOn; -extern char vfoActive; -extern unsigned long vfoA, vfoB, sideTone, usbCarrier; -extern char isUsbVfoA, isUsbVfoB; -extern unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial extern unsigned long firstIF; -// if cwMode is flipped on, the rx frequency is tuned down by sidetone hz instead of being zerobeat -extern int cwMode; - - -//these are variables that control the keyer behaviour -extern int cwSpeed; //this is actuall the dot period in milliseconds -extern int32_t calibration; -extern int cwDelayTime; -extern bool Iambic_Key; - -#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B -extern unsigned char keyerControl; -//during CAT commands, we will freeeze the display until CAT is disengaged -extern unsigned char doingCAT; - - -/** - * Raduino needs to keep track of current state of the transceiver. These are a few variables that do it - */ -extern boolean txCAT; //turned on if the transmitting due to a CAT command -extern char inTx; //it is set to 1 if in transmit mode (whatever the reason : cw, ptt or cat) -extern int splitOn; //working split, uses VFO B as the transmit frequency -extern char keyDown; //in cw mode, denotes the carrier is being transmitted -extern char isUSB; //upper sideband was selected, this is reset to the default for the - //frequency when it crosses the frequency border of 10 MHz -extern byte menuOn; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited -extern unsigned long cwTimeout; //milliseconds to go before the cw transmit line is released and the radio goes back to rx mode -extern unsigned long dbgCount; //not used now -extern unsigned char txFilter ; //which of the four transmit filters are in use -extern boolean modeCalibrate;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper - //beat frequency +extern uint8_t menuOn; /* these are functions implemented in the main file named as ubitx_xxx.ino */ void active_delay(int delay_by); void saveVFOs(); void setFrequency(unsigned long f); -void startTx(byte txMode); +void startTx(TuningMode_e tx_mode); void stopTx(); void ritEnable(unsigned long f); void ritDisable(); void checkCAT(); void cwKeyer(void); -void switchVFO(int vfoSelect); +void switchVFO(Vfo_e vfoSelect); int enc_read(void); // returns the number of ticks in a short interval, +ve in clockwise, -ve in anti-clockwise int btnDown(); //returns true if the encoder button is pressed @@ -209,10 +139,6 @@ void checkTouch(); //does the commands with a touch on the buttons - - - - /* these are functiosn implemented in ubitx_si5351.cpp */ void si5351bx_setfreq(uint8_t clknum, uint32_t fout); void initOscillators(); diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index c15bc26..d216b78 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -1,4 +1,5 @@ #include +#include "settings.h" #include "ubitx.h" #include "nano_gui.h" @@ -159,7 +160,7 @@ void catReadEEPRom(void) //5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE //6 : //7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0) - cat[0] = 0x80 + (vfoActive == VFO_B ? 1 : 0); + cat[0] = 0x80 + ((VFO_B == globalSettings.activeVfo) ? 1 : 0); cat[1] = 0x00; break; case 0x57 : // @@ -187,11 +188,11 @@ void catReadEEPRom(void) //5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel //7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW //CAT_BUFF[0] = 0x08; - cat[0] = (sideTone - 300)/50; + cat[0] = (globalSettings.cwSideToneFreq - 300)/50; cat[1] = 0x25; break; - case 0x61 : //Sidetone (Volume) (#44) - cat[0] = sideTone % 50; + case 0x61 : //globalSettings.cwSideToneFreq (Volume) (#44) + cat[0] = globalSettings.cwSideToneFreq % 50; cat[1] = 0x08; break; case 0x5F : // @@ -203,14 +204,14 @@ void catReadEEPRom(void) cat[1] = 0x08; break; case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms - cat[0] = cwDelayTime; + cat[0] = globalSettings.cwActiveTimeoutMs / 10; cat[1] = 0x32; break; case 0x62 : // //5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps) //7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours //CAT_BUFF[0] = 0x08; - cat[0] = 1200 / cwSpeed - 4; + cat[0] = 12000 / globalSettings.cwDitDurationMs - 4; cat[1] = 0xB2; break; case 0x63 : // @@ -226,7 +227,7 @@ void catReadEEPRom(void) cat[1] = 0xB2; break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed case 0x78 : - if (isUSB) + if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) cat[0] = CAT_MODE_USB; else cat[0] = CAT_MODE_LSB; @@ -252,7 +253,7 @@ void catReadEEPRom(void) //7A 6 ? ? //7A 7 SPL On/Off 0 = Off, 1 = On - cat[0] = (splitOn ? 0xFF : 0x7F); + cat[0] = (globalSettings.splitOn ? 0xFF : 0x7F); break; case 0xB3 : // cat[0] = 0x00; @@ -288,16 +289,16 @@ void processCATCommand2(byte* cmd) { case 0x02: //split on - splitOn = 1; + globalSettings.splitOn = 1; break; case 0x82: //split off - splitOn = 0; + globalSettings.splitOn = 0; break; case 0x03: - writeFreq(frequency,response); // Put the frequency into the buffer - if (isUSB) + writeFreq(GetActiveVfoFreq(),response); // Put the frequency into the buffer + if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) response[4] = 0x01; //USB else response[4] = 0x00; //LSB @@ -307,21 +308,21 @@ void processCATCommand2(byte* cmd) { case 0x07: // set mode if (cmd[0] == 0x00 || cmd[0] == 0x03) - isUSB = 0; + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); else - isUSB = 1; + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); response[0] = 0x00; Serial.write(response, 1); - setFrequency(frequency); + setFrequency(GetActiveVfoFreq()); //printLine2("cat: mode changed"); //updateDisplay(); break; case 0x08: // PTT On - if (!inTx) { + if (!globalSettings.txActive) { response[0] = 0; - txCAT = true; - startTx(TX_SSB); + globalSettings.txCatActive = true; + startTx(TuningMode_e::TUNE_SSB); updateDisplay(); } else { response[0] = 0xf0; @@ -331,9 +332,9 @@ void processCATCommand2(byte* cmd) { break; case 0x88 : //PTT OFF - if (inTx) { + if (globalSettings.txActive) { stopTx(); - txCAT = false; + globalSettings.txCatActive = false; } response[0] = 0; Serial.write(response,1); @@ -343,7 +344,7 @@ void processCATCommand2(byte* cmd) { case 0x81: //toggle the VFOs response[0] = 0; - if (vfoActive == VFO_A) + if (VFO_A == globalSettings.activeVfo) switchVFO(VFO_B); else switchVFO(VFO_A); @@ -366,14 +367,14 @@ void processCATCommand2(byte* cmd) { case 0xf7: { boolean isHighSWR = false; - boolean isSplitOn = false; + boolean issplitOn = false; /* Inverted -> *ptt = ((p->tx_status & 0x80) == 0); <-- souce code in ft817.c (hamlib) */ - response[0] = ((inTx ? 0 : 1) << 7) + + response[0] = ((globalSettings.txActive ? 0 : 1) << 7) + ((isHighSWR ? 1 : 0) << 6) + //hi swr off / on - ((isSplitOn ? 1 : 0) << 5) + //Split on / off + ((issplitOn ? 1 : 0) << 5) + //Split on / off (0 << 4) + //dummy data 0x08; //P0 meter data diff --git a/ubitx_si5351.cpp b/ubitx_si5351.cpp index 544648a..3d378ab 100644 --- a/ubitx_si5351.cpp +++ b/ubitx_si5351.cpp @@ -1,5 +1,6 @@ #include #include +#include "settings.h" #include "ubitx.h" // ************* SI5315 routines - tks Jerry Gaffke, KE7ER *********************** @@ -115,14 +116,14 @@ void si5351bx_setfreq(uint8_t clknum, uint32_t fout) { // Set a CLK to fout Hz void si5351_set_calibration(int32_t cal){ si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + cal; // apply the calibration correction factor - si5351bx_setfreq(0, usbCarrier); + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); } void initOscillators(){ //initialize the SI5351 si5351bx_init(); si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor - si5351bx_setfreq(0, usbCarrier); + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); } diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 07e4b4d..7e48a1a 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -1,6 +1,7 @@ #include #include #include "morse.h" +#include "settings.h" #include "ubitx.h" #include "nano_gui.h" @@ -242,13 +243,13 @@ void displayDialog(char *title, char *instructions){ displayRawText(instructions, 20, 200, COLOR_TEXT, COLOR_BACKGROUND); } -void displayVFO(int vfo){ +void displayVFO(Vfo_e vfo){ int x, y; int displayColor, displayBackground, displayBorder; Button button; - if (splitOn){ - if (vfoActive == vfo){ + if (globalSettings.splitOn){ + if (vfo == globalSettings.activeVfo){ c[0] = 'R'; } else{ @@ -269,32 +270,30 @@ void displayVFO(int vfo){ c[1] = ':'; - if (vfo == VFO_A){ + if (VFO_A == vfo){ getButton(BUTTON_VFOA, &button); + formatFreq(globalSettings.vfoA.frequency, c+2); - if (vfoActive == VFO_A){ - formatFreq(frequency, c+2); + if (VFO_A == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; displayBackground = COLOR_ACTIVE_VFO_BACKGROUND; displayBorder = COLOR_ACTIVE_BORDER; }else{ - formatFreq(vfoA, c+2); displayColor = COLOR_INACTIVE_VFO_TEXT; displayBackground = COLOR_INACTIVE_VFO_BACKGROUND; displayBorder = COLOR_INACTIVE_BORDER; } } - if (vfo == VFO_B){ + if (VFO_B == vfo){ getButton(BUTTON_VFOB, &button); + formatFreq(globalSettings.vfoB.frequency, c+2); - if (vfoActive == VFO_B){ - formatFreq(frequency, c+2); + if (VFO_B == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; displayBackground = COLOR_ACTIVE_VFO_BACKGROUND; displayBorder = COLOR_ACTIVE_BORDER; } else { - formatFreq(vfoB, c+2); displayColor = COLOR_INACTIVE_VFO_TEXT; displayBackground = COLOR_INACTIVE_VFO_BACKGROUND; displayBorder = COLOR_INACTIVE_BORDER; @@ -325,7 +324,7 @@ void btnDraw(struct Button *button){ } case BUTTON_RIT: { - if(1 == ritOn){ + if(globalSettings.ritOn){ btnDrawActive(button); } else{ @@ -335,7 +334,7 @@ void btnDraw(struct Button *button){ } case BUTTON_USB: { - if(1 == isUSB){ + if(VFO_MODE_USB == GetActiveVfoMode()){ btnDrawActive(button); } else{ @@ -345,7 +344,7 @@ void btnDraw(struct Button *button){ } case BUTTON_LSB: { - if(0 == isUSB){ + if(VFO_MODE_LSB == GetActiveVfoMode()){ btnDrawActive(button); } else{ @@ -355,7 +354,7 @@ void btnDraw(struct Button *button){ } case BUTTON_SPL: { - if(1 == splitOn){ + if(globalSettings.splitOn){ btnDrawActive(button); } else{ @@ -365,7 +364,7 @@ void btnDraw(struct Button *button){ } case BUTTON_CW: { - if(1 == cwMode){ + if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ btnDrawActive(button); } else{ @@ -385,10 +384,10 @@ void btnDraw(struct Button *button){ void displayRIT(){ c[0] = 0; displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); - if (ritOn){ + if(globalSettings.ritOn){ strcpy_P(c,(const char*)F("TX:")); - formatFreq(ritTxFrequency, c+3); - if (vfoActive == VFO_A) + formatFreq(globalSettings.ritFrequency, c+3); + if (VFO_A == globalSettings.activeVfo) displayText(c, LAYOUT_MODE_TEXT_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); else displayText(c, LAYOUT_MODE_TEXT_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); @@ -396,8 +395,6 @@ void displayRIT(){ } void fastTune(){ - int encoder; - //if the btn is down, wait until it is up while(btnDown()) active_delay(50); @@ -418,15 +415,17 @@ void fastTune(){ return; } - encoder = enc_read(); + int encoder = enc_read(); if (encoder != 0){ - - if (encoder > 0 && frequency < 30000000l) - frequency += 50000l; - else if (encoder < 0 && frequency > 600000l) - frequency -= 50000l; - setFrequency(frequency); - displayVFO(vfoActive); + uint32_t freq = GetActiveVfoFreq(); + if (encoder > 0 && freq < 30000000l){ + freq += 50000l; + } + else if (encoder < 0 && freq > 600000l){ + freq -= 50000l; + } + setFrequency(freq); + displayVFO(globalSettings.activeVfo); } }// end of the event loop } @@ -434,7 +433,6 @@ void fastTune(){ void enterFreq(){ //force the display to refresh everything //display all the buttons - int f; for (int i = 0; i < KEYS_TOTAL; i++){ Button button; @@ -444,7 +442,6 @@ void enterFreq(){ int cursor_pos = 0; memset(c, 0, sizeof(c)); - f = frequency / 1000l; while(1){ @@ -468,14 +465,16 @@ void enterFreq(){ switch(button.id){ case KEYS_OK: { - long f = atol(c); - if(30000 >= f && f > 100){ - frequency = f * 1000l; - setFrequency(frequency); - if (vfoActive == VFO_A) - vfoA = frequency; - else - vfoB = frequency; + long freq = atol(c); + if((LOWEST_FREQ/1000 <= freq) && (freq <= HIGHEST_FREQ/1000)){ + freq *= 1000L; + setFrequency(freq); + if (VFO_A == globalSettings.activeVfo){ + globalSettings.vfoA.frequency = freq; + } + else{ + globalSettings.vfoB.frequency = freq; + } saveVFOs(); } guiUpdate(); @@ -525,7 +524,7 @@ void enterFreq(){ strcpy(b, c); strcat(b, " KHz"); displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - delay(300); + active_delay(300); while(readTouch()) checkCAT(); } // end of event loop : while(1) @@ -533,11 +532,11 @@ void enterFreq(){ void drawCWStatus(){ strcpy(b, " cw: "); - int wpm = 1200/cwSpeed; + int wpm = 12000/globalSettings.cwDitDurationMs; itoa(wpm,c, 10); strcat(b, c); strcat(b, "wpm, "); - itoa(sideTone, c, 10); + itoa(globalSettings.cwSideToneFreq, c, 10); strcat(b, c); strcat(b, "hz"); displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); @@ -545,7 +544,7 @@ void drawCWStatus(){ void drawTx(){ - if (inTx) + if (globalSettings.txActive) displayText("TX", LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND); else displayFillrect(LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_BACKGROUND); @@ -586,7 +585,7 @@ void guiUpdate(){ // this builds up the top line of the display with frequency and mode void updateDisplay() { - displayVFO(vfoActive); + displayVFO(globalSettings.activeVfo); } int enc_prev_state = 3; @@ -653,21 +652,19 @@ int enc_read(void) { } void ritToggle(struct Button *button){ - if (ritOn == 0){ - ritEnable(frequency); + if (globalSettings.ritOn){ + ritEnable(GetActiveVfoFreq()); } - else + else{ ritDisable(); + } btnDraw(button); displayRIT(); } void splitToggle(Button *button){ - if (splitOn) - splitOn = 0; - else - splitOn = 1; + globalSettings.splitOn = !globalSettings.splitOn; btnDraw(button); @@ -685,17 +682,17 @@ void splitToggle(Button *button){ void vfoReset(){ Button button; - if (vfoActive = VFO_A) - vfoB = vfoA; + if (VFO_A == globalSettings.activeVfo) + globalSettings.vfoB.frequency = globalSettings.vfoA.frequency; else - vfoA = vfoB; + globalSettings.vfoA.frequency = globalSettings.vfoB.frequency; - if (splitOn){ + if(globalSettings.splitOn){ getButton(BUTTON_SPL, &button); splitToggle(&button); } - if (ritOn){ + if(globalSettings.ritOn){ getButton(BUTTON_RIT, &button); ritToggle(&button); } @@ -707,21 +704,22 @@ void vfoReset(){ } void cwToggle(struct Button *b){ - if (cwMode == 0){ - cwMode = 1; + if (TuningMode_e::TUNE_SSB == globalSettings.tuningMode){ + globalSettings.tuningMode = TuningMode_e::TUNE_CW; + } + else{ + globalSettings.tuningMode = TuningMode_e::TUNE_SSB; } - else - cwMode = 0; - setFrequency(frequency); + setFrequency(GetActiveVfoFreq()); btnDraw(b); } void sidebandToggle(Button* button){ if(BUTTON_LSB == button->id) - isUSB = 0; + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); else - isUSB = 1; + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); struct Button button2; getButton(BUTTON_USB, &button2); @@ -750,48 +748,46 @@ void redrawVFOs(){ } -void switchBand(long bandfreq){ - long offset; +void switchBand(uint32_t bandfreq){ -// Serial.println(frequency); -// Serial.println(bandfreq); - if (3500000l <= frequency && frequency <= 4000000l) - offset = frequency - 3500000l; - else if (24800000l <= frequency && frequency <= 25000000l) - offset = frequency - 24800000l; + //Serial.println(frequency); + //Serial.println(bandfreq); + uint32_t offset; + uint32_t freq = GetActiveVfoFreq(); + if (3500000L <= freq && freq <= 4000000L) + offset = freq - 3500000l; + else if (24800000L <= freq && freq <= 25000000L) + offset = freq - 24800000L; else - offset = frequency % 1000000l; + offset = freq % 1000000L; -// Serial.println(offset); + //Serial.println(offset); setFrequency(bandfreq + offset); updateDisplay(); saveVFOs(); } -int setCwSpeed(){ - int knob = 0; - int wpm; - - wpm = 1200/cwSpeed; - - wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM"); - - cwSpeed = 1200/wpm; +void setCwSpeed() +{ + int wpm = 12000/globalSettings.cwDitDurationMs; + + wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM"); - EEPROM.put(CW_SPEED, cwSpeed); - active_delay(500); - drawStatusbar(); -// printLine2(""); -// updateDisplay(); + globalSettings.cwDitDurationMs = 12000/wpm; + SaveSettingsToEeprom(); + active_delay(500); + drawStatusbar(); + //printLine2(""); + //updateDisplay(); } void setCwTone(){ int knob = 0; int prev_sideTone; - tone(CW_TONE, sideTone); - itoa(sideTone, c, 10); + tone(CW_TONE, globalSettings.cwSideToneFreq); + itoa(globalSettings.cwSideToneFreq, c, 10); strcpy(b, "CW Tone: "); strcat(b, c); strcat(b, " Hz"); @@ -802,15 +798,15 @@ void setCwTone(){ { knob = enc_read(); - if (knob > 0 && sideTone < 2000) - sideTone += 10; - else if (knob < 0 && sideTone > 100 ) - sideTone -= 10; + if (knob > 0 && globalSettings.cwSideToneFreq < 2000) + globalSettings.cwSideToneFreq += 10; + else if (knob < 0 && globalSettings.cwSideToneFreq > 100 ) + globalSettings.cwSideToneFreq -= 10; else continue; //don't update the frequency or the display - tone(CW_TONE, sideTone); - itoa(sideTone, c, 10); + tone(CW_TONE, globalSettings.cwSideToneFreq); + itoa(globalSettings.cwSideToneFreq, c, 10); strcpy(b, "CW Tone: "); strcat(b, c); strcat(b, " Hz"); @@ -821,14 +817,14 @@ void setCwTone(){ active_delay(20); } noTone(CW_TONE); - //save the setting - EEPROM.put(CW_SIDETONE, sideTone); + + SaveSettingsToEeprom(); b[0] = 0; drawCommandbar(b); drawStatusbar(); -// printLine2(""); -// updateDisplay(); + //printLine2(""); + //updateDisplay(); } void doCommand(Button* button){ @@ -863,7 +859,7 @@ void doCommand(Button* button){ } case BUTTON_VFOA: { - if(VFO_A == vfoActive){ + if(VFO_A == globalSettings.activeVfo){ fastTune(); } else{ @@ -873,7 +869,7 @@ void doCommand(Button* button){ } case BUTTON_VFOB: { - if(VFO_B == vfoActive){ + if(VFO_B == globalSettings.activeVfo){ fastTune(); } else{ @@ -1002,7 +998,7 @@ void doCommands(){ //unfocus the buttons drawFocus(select, COLOR_INACTIVE_BORDER); - if (vfoActive == VFO_A) + if (VFO_A == globalSettings.activeVfo) drawFocus(BUTTON_VFOA, COLOR_ACTIVE_BORDER); else drawFocus(BUTTON_VFOB, COLOR_ACTIVE_BORDER); diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index d2518d1..4e73bf4 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -30,21 +30,10 @@ * Si5351 object to control the clocks. */ #include -#include +#include "settings.h" #include "ubitx.h" #include "nano_gui.h" -/** - The main chip which generates upto three oscillators of various frequencies in the - Raduino is the Si5351a. To learn more about Si5351a you can download the datasheet - from www.silabs.com although, strictly speaking it is not a requirment to understand this code. - - We no longer use the standard SI5351 library because of its huge overhead due to many unused - features consuming a lot of program space. Instead of depending on an external library we now use - Jerry Gaffke's, KE7ER, lightweight standalone mimimalist "si5351bx" routines (see further down the - code). Here are some defines and declarations used by Jerry's routines: -*/ - /** * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. * We have to be very careful with variables that are declared inside the functions as they are @@ -58,102 +47,10 @@ */ char c[30], b[30]; -/** - * These are the indices where these user changable settinngs are stored in the EEPROM - */ -#define MASTER_CAL 0 -#define LSB_CAL 4 -#define USB_CAL 8 -#define SIDE_TONE 12 -//these are ids of the vfos as well as their offset into the eeprom storage, don't change these 'magic' values -#define VFO_A 16 -#define VFO_B 20 -#define CW_SIDETONE 24 -#define CW_SPEED 28 -// the screen calibration parameters : int slope_x=104, slope_y=137, offset_x=28, offset_y=29; -#define SLOPE_X 32 -#define SLOPE_Y 36 -#define OFFSET_X 40 -#define OFFSET_Y 44 -#define CW_DELAYTIME 48 - -//These are defines for the new features back-ported from KD8CEC's software -//these start from beyond 256 as Ian, KD8CEC has kept the first 256 bytes free for the base version -#define VFO_A_MODE 256 // 2: LSB, 3: USB -#define VFO_B_MODE 257 - -//values that are stroed for the VFO modes -#define VFO_MODE_LSB 2 -#define VFO_MODE_USB 3 - -// handkey, iambic a, iambic b : 0,1,2f -#define CW_KEY_TYPE 358 - -/** - * The uBITX is an upconnversion transceiver. The first IF is at 45 MHz. - * The first IF frequency is not exactly at 45 Mhz but about 5 khz lower, - * this shift is due to the loading on the 45 Mhz crystal filter by the matching - * L-network used on it's either sides. - * The first oscillator works between 48 Mhz and 75 MHz. The signal is subtracted - * from the first oscillator to arriive at 45 Mhz IF. Thus, it is inverted : LSB becomes USB - * and USB becomes LSB. - * The second IF of 12 Mhz has a ladder crystal filter. If a second oscillator is used at - * 57 Mhz, the signal is subtracted FROM the oscillator, inverting a second time, and arrives - * at the 12 Mhz ladder filter thus doouble inversion, keeps the sidebands as they originally were. - * If the second oscillator is at 33 Mhz, the oscilaltor is subtracated from the signal, - * thus keeping the signal's sidebands inverted. The USB will become LSB. - * We use this technique to switch sidebands. This is to avoid placing the lsbCarrier close to - * 12 MHz where its fifth harmonic beats with the arduino's 16 Mhz oscillator's fourth harmonic - */ - -#define INIT_USB_FREQ (11059200l) -// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz -#define LOWEST_FREQ (100000l) -#define HIGHEST_FREQ (30000000l) - -//we directly generate the CW by programmin the Si5351 to the cw tx frequency, hence, both are different modes -//these are the parameter passed to startTx -#define TX_SSB 0 -#define TX_CW 1 - -char ritOn = 0; -char vfoActive = VFO_A; -int8_t meter_reading = 0; // a -1 on meter makes it invisible -unsigned long vfoA=7150000L, vfoB=14200000L, sideTone=800, usbCarrier; -char isUsbVfoA=0, isUsbVfoB=1; -unsigned long frequency, ritRxFrequency, ritTxFrequency; //frequency is the current frequency on the dial -unsigned long firstIF = 45005000L; - -// if cwMode is flipped on, the rx frequency is tuned down by sidetone hz instead of being zerobeat -int cwMode = 0; - - -//these are variables that control the keyer behaviour -int cwSpeed = 100; //this is actuall the dot period in milliseconds -extern int32_t calibration; -int cwDelayTime = 60; -bool Iambic_Key = true; -#define IAMBICB 0x10 // 0 for Iambic A, 1 for Iambic B -unsigned char keyerControl = IAMBICB; //during CAT commands, we will freeeze the display until CAT is disengaged unsigned char doingCAT = 0; - - -/** - * Raduino needs to keep track of current state of the transceiver. These are a few variables that do it - */ -boolean txCAT = false; //turned on if the transmitting due to a CAT command -char inTx = 0; //it is set to 1 if in transmit mode (whatever the reason : cw, ptt or cat) -int splitOn = 0; //working split, uses VFO B as the transmit frequency -char keyDown = 0; //in cw mode, denotes the carrier is being transmitted -char isUSB = 0; //upper sideband was selected, this is reset to the default for the - //frequency when it crosses the frequency border of 10 MHz byte menuOn = 0; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited -unsigned long cwTimeout = 0; //milliseconds to go before the cw transmit line is released and the radio goes back to rx mode -unsigned long dbgCount = 0; //not used now -unsigned char txFilter = 0; //which of the four transmit filters are in use -boolean modeCalibrate = false;//this mode of menus shows extended menus to calibrate the oscillators and choose the proper - //beat frequency + /** * Below are the basic functions that control the uBitx. Understanding the functions before @@ -168,32 +65,14 @@ void active_delay(int delay_by){ unsigned long timeStart = millis(); while (millis() - timeStart <= (unsigned long)delay_by) { delay(10); - //Background Work + //Background Work checkCAT(); } } -void saveVFOs(){ - - if (vfoActive == VFO_A) - EEPROM.put(VFO_A, frequency); - else - EEPROM.put(VFO_A, vfoA); - - if (isUsbVfoA) - EEPROM.put(VFO_A_MODE, VFO_MODE_USB); - else - EEPROM.put(VFO_A_MODE, VFO_MODE_LSB); - - if (vfoActive == VFO_B) - EEPROM.put(VFO_B, frequency); - else - EEPROM.put(VFO_B, vfoB); - - if (isUsbVfoB) - EEPROM.put(VFO_B_MODE, VFO_MODE_USB); - else - EEPROM.put(VFO_B_MODE, VFO_MODE_LSB); +void saveVFOs() +{ + SaveSettingsToEeprom(); } /** @@ -227,12 +106,12 @@ void setTXFilters(unsigned long freq){ else if (freq > 7000000L){ digitalWrite(TX_LPF_A, 0); digitalWrite(TX_LPF_B, 1); - digitalWrite(TX_LPF_C, 0); + digitalWrite(TX_LPF_C, 0); } else { digitalWrite(TX_LPF_A, 0); digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 1); + digitalWrite(TX_LPF_C, 1); } } @@ -252,12 +131,12 @@ void setTXFilters_v5(unsigned long freq){ else if (freq > 7000000L){ digitalWrite(TX_LPF_A, 0); digitalWrite(TX_LPF_B, 1); - digitalWrite(TX_LPF_C, 0); + digitalWrite(TX_LPF_C, 0); } else { digitalWrite(TX_LPF_A, 0); digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 1); + digitalWrite(TX_LPF_C, 1); } } @@ -275,38 +154,31 @@ void setTXFilters_v5(unsigned long freq){ * through mixing of the second local oscillator. */ -void setFrequency(unsigned long f){ - uint64_t osc_f, firstOscillator, secondOscillator; +void setFrequency(unsigned long freq){ + static const unsigned long firstIF = 45005000L; - setTXFilters(f); + setTXFilters(freq); -/* - if (isUSB){ - si5351bx_setfreq(2, firstIF + f); - si5351bx_setfreq(1, firstIF + usbCarrier); + uint32_t primary_osc_freq; + if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + primary_osc_freq = firstIF + globalSettings.usbCarrierFreq; } else{ - si5351bx_setfreq(2, firstIF + f); - si5351bx_setfreq(1, firstIF - usbCarrier); - } -*/ - //alternative to reduce the intermod spur - if (isUSB){ - if (cwMode) - si5351bx_setfreq(2, firstIF + f + sideTone); - else - si5351bx_setfreq(2, firstIF + f); - si5351bx_setfreq(1, firstIF + usbCarrier); + primary_osc_freq = firstIF - globalSettings.usbCarrierFreq; + } + + uint32_t secondary_osc_freq; + if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ + secondary_osc_freq = firstIF + freq + globalSettings.cwSideToneFreq; } else{ - if (cwMode) - si5351bx_setfreq(2, firstIF + f + sideTone); - else - si5351bx_setfreq(2, firstIF + f); - si5351bx_setfreq(1, firstIF - usbCarrier); + secondary_osc_freq = firstIF + freq; } - - frequency = f; + + si5351bx_setfreq(2, secondary_osc_freq); + si5351bx_setfreq(1, primary_osc_freq); + + SetActiveVfoFreq(freq); } /** @@ -316,81 +188,72 @@ void setFrequency(unsigned long f){ * CW offest is calculated as lower than the operating frequency when in LSB mode, and vice versa in USB mode */ -void startTx(byte txMode){ - unsigned long tx_freq = 0; - - digitalWrite(TX_RX, 1); - inTx = 1; - - if (ritOn){ +void startTx(TuningMode_e tx_mode){ + globalSettings.tuningMode = tx_mode; + + if (globalSettings.ritOn){ //save the current as the rx frequency - ritRxFrequency = frequency; - setFrequency(ritTxFrequency); - } - else - { - if (splitOn == 1) { - if (vfoActive == VFO_B) { - vfoActive = VFO_A; - isUSB = isUsbVfoA; - frequency = vfoA; + uint32_t rit_tx_freq = globalSettings.ritFrequency; + globalSettings.ritFrequency = GetActiveVfoFreq(); + setFrequency(rit_tx_freq); + } + else{ + if(globalSettings.splitOn){ + if(Vfo_e::VFO_B == globalSettings.activeVfo){ + globalSettings.activeVfo = Vfo_e::VFO_A; } - else if (vfoActive == VFO_A){ - vfoActive = VFO_B; - frequency = vfoB; - isUSB = isUsbVfoB; + else{ + globalSettings.activeVfo = Vfo_e::VFO_B; } } - setFrequency(frequency); + setFrequency(GetActiveVfoFreq()); } - if (txMode == TX_CW){ - digitalWrite(TX_RX, 0); - + if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ //turn off the second local oscillator and the bfo si5351bx_setfreq(0, 0); si5351bx_setfreq(1, 0); - //shif the first oscillator to the tx frequency directly + //shift the first oscillator to the tx frequency directly //the key up and key down will toggle the carrier unbalancing //the exact cw frequency is the tuned frequency + sidetone - if (isUSB) - si5351bx_setfreq(2, frequency + sideTone); - else - si5351bx_setfreq(2, frequency - sideTone); + if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + si5351bx_setfreq(2, GetActiveVfoFreq() + globalSettings.cwSideToneFreq); + } + else{ + si5351bx_setfreq(2, GetActiveVfoFreq() - globalSettings.cwSideToneFreq); + } delay(20); - digitalWrite(TX_RX, 1); } + digitalWrite(TX_RX, 1);//turn on the tx + globalSettings.txActive = true; drawTx(); - //updateDisplay(); } void stopTx(){ - inTx = 0; + digitalWrite(TX_RX, 0);//turn off the tx + globalSettings.txActive = false; - digitalWrite(TX_RX, 0); //turn off the tx - si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off + //set back the carrier oscillator - cw tx switches it off + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); - if (ritOn) - setFrequency(ritRxFrequency); + if(globalSettings.ritOn){ + uint32_t rit_rx_freq = globalSettings.ritFrequency; + globalSettings.ritFrequency = GetActiveVfoFreq(); + setFrequency(rit_rx_freq); + } else{ - if (splitOn == 1) { - //vfo Change - if (vfoActive == VFO_B){ - vfoActive = VFO_A; - frequency = vfoA; - isUSB = isUsbVfoA; + if(globalSettings.splitOn){ + if(Vfo_e::VFO_B == globalSettings.activeVfo){ + globalSettings.activeVfo = Vfo_e::VFO_A; } - else if (vfoActive == VFO_A){ - vfoActive = VFO_B; - frequency = vfoB; - isUSB = isUsbVfoB; + else{ + globalSettings.activeVfo = Vfo_e::VFO_B; } } - setFrequency(frequency); + setFrequency(GetActiveVfoFreq()); } - //updateDisplay(); drawTx(); } @@ -398,18 +261,18 @@ void stopTx(){ * ritEnable is called with a frequency parameter that determines * what the tx frequency will be */ -void ritEnable(unsigned long f){ - ritOn = 1; +void ritEnable(unsigned long freq){ + globalSettings.ritOn = true; //save the non-rit frequency back into the VFO memory //as RIT is a temporary shift, this is not saved to EEPROM - ritTxFrequency = f; + globalSettings.ritFrequency = freq; } // this is called by the RIT menu routine void ritDisable(){ - if (ritOn){ - ritOn = 0; - setFrequency(ritTxFrequency); + if(globalSettings.ritOn){ + globalSettings.ritOn = false; + setFrequency(globalSettings.ritFrequency); updateDisplay(); } } @@ -424,17 +287,18 @@ void ritDisable(){ * flip the T/R line to T and update the display to denote transmission */ -void checkPTT(){ +void checkPTT(){ //we don't check for ptt when transmitting cw - if (cwTimeout > 0) + if (globalSettings.cwExpirationTimeMs > 0){ return; + } - if (digitalRead(PTT) == 0 && inTx == 0){ - startTx(TX_SSB); + if(digitalRead(PTT) == 0 && !globalSettings.txActive){ + startTx(TuningMode_e::TUNE_SSB); active_delay(50); //debounce the PTT } - if (digitalRead(PTT) == 1 && inTx == 1) + if (digitalRead(PTT) == 1 && globalSettings.txActive) stopTx(); } @@ -471,41 +335,11 @@ void checkButton(){ active_delay(50);//debounce } -void switchVFO(int vfoSelect){ - if (vfoSelect == VFO_A){ - if (vfoActive == VFO_B){ - vfoB = frequency; - isUsbVfoB = isUSB; - EEPROM.put(VFO_B, frequency); - if (isUsbVfoB) - EEPROM.put(VFO_B_MODE, VFO_MODE_USB); - else - EEPROM.put(VFO_B_MODE, VFO_MODE_LSB); - } - vfoActive = VFO_A; -// printLine2("Selected VFO A "); - frequency = vfoA; - isUSB = isUsbVfoA; - } - else { - if (vfoActive == VFO_A){ - vfoA = frequency; - isUsbVfoA = isUSB; - EEPROM.put(VFO_A, frequency); - if (isUsbVfoA) - EEPROM.put(VFO_A_MODE, VFO_MODE_USB); - else - EEPROM.put(VFO_A_MODE, VFO_MODE_LSB); - } - vfoActive = VFO_B; -// printLine2("Selected VFO B "); - frequency = vfoB; - isUSB = isUsbVfoB; - } - - setFrequency(frequency); - redrawVFOs(); - saveVFOs(); +void switchVFO(Vfo_e new_vfo){ + globalSettings.activeVfo = new_vfo; + setFrequency(GetActiveVfoFreq()); + redrawVFOs(); + saveVFOs(); } /** @@ -516,46 +350,46 @@ void switchVFO(int vfoSelect){ */ void doTuning(){ - int s; static unsigned long prev_freq; static unsigned long nextFrequencyUpdate = 0; unsigned long now = millis(); - if (now >= nextFrequencyUpdate && prev_freq != frequency){ + if (now >= nextFrequencyUpdate && prev_freq != GetActiveVfoFreq()){ updateDisplay(); nextFrequencyUpdate = now + 500; - prev_freq = frequency; + prev_freq = GetActiveVfoFreq(); } - s = enc_read(); + int s = enc_read(); if (!s) return; doingCAT = 0; // go back to manual mode if you were doing CAT - prev_freq = frequency; - - - if (s > 10) - frequency += 200l * s; - else if (s > 5) - frequency += 100l * s; - else if (s > 0) - frequency += 50l * s; - else if (s < -10) - frequency += 200l * s; - else if (s < -5) - frequency += 100l * s; - else if (s < 0) - frequency += 50l * s; - - if (prev_freq < 10000000l && frequency > 10000000l) - isUSB = true; - - if (prev_freq > 10000000l && frequency < 10000000l) - isUSB = false; + prev_freq = GetActiveVfoFreq(); + uint32_t new_freq = prev_freq; + + if (s > 10 || s < -10){ + new_freq += 200L * s; + } + else if (s > 5 || s < -5){ + new_freq += 100L * s; + } + else{ + new_freq += 50L * s; + } + + //Transition from below to above the traditional threshold for USB + if(prev_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + } + + //Transition from aboveo to below the traditional threshold for USB + if(prev_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + } - setFrequency(frequency); + setFrequency(new_freq); } @@ -563,18 +397,17 @@ void doTuning(){ * RIT only steps back and forth by 100 hz at a time */ void doRIT(){ - unsigned long newFreq; - int knob = enc_read(); - unsigned long old_freq = frequency; + uint32_t old_freq = GetActiveVfoFreq(); + uint32_t new_freq = old_freq; if (knob < 0) - frequency -= 100l; + new_freq -= 100l; else if (knob > 0) - frequency += 100; + new_freq += 100; - if (old_freq != frequency){ - setFrequency(frequency); + if (old_freq != new_freq){ + setFrequency(new_freq); updateDisplay(); } } @@ -585,87 +418,7 @@ void doRIT(){ * variables. */ void initSettings(){ - byte x; - //read the settings from the eeprom and restore them - //if the readings are off, then set defaults - EEPROM.get(MASTER_CAL, calibration); - EEPROM.get(USB_CAL, usbCarrier); - EEPROM.get(VFO_A, vfoA); - EEPROM.get(VFO_B, vfoB); - EEPROM.get(CW_SIDETONE, sideTone); - EEPROM.get(CW_SPEED, cwSpeed); - EEPROM.get(CW_DELAYTIME, cwDelayTime); - -// the screen calibration parameters : int slope_x=104, slope_y=137, offset_x=28, offset_y=29; - - if (usbCarrier > 11060000l || usbCarrier < 11048000l) - usbCarrier = 11052000l; - if (vfoA > 35000000l || 3500000l > vfoA) - vfoA = 7150000l; - if (vfoB > 35000000l || 3500000l > vfoB) - vfoB = 14150000l; - if (sideTone < 100 || 2000 < sideTone) - sideTone = 800; - if (cwSpeed < 10 || 1000 < cwSpeed) - cwSpeed = 100; - if (cwDelayTime < 10 || cwDelayTime > 100) - cwDelayTime = 50; - - /* - * The VFO modes are read in as either 2 (USB) or 3(LSB), 0, the default - * is taken as 'uninitialized - */ - - EEPROM.get(VFO_A_MODE, x); - - switch(x){ - case VFO_MODE_USB: - isUsbVfoA = 1; - break; - case VFO_MODE_LSB: - isUsbVfoA = 0; - break; - default: - if (vfoA > 10000000l) - isUsbVfoA = 1; - else - isUsbVfoA = 0; - } - - EEPROM.get(VFO_B_MODE, x); - switch(x){ - case VFO_MODE_USB: - isUsbVfoB = 1; - break; - case VFO_MODE_LSB: - isUsbVfoB = 0; - break; - default: - if (vfoA > 10000000l) - isUsbVfoB = 1; - else - isUsbVfoB = 0; - } - - //set the current mode - isUSB = isUsbVfoA; - - /* - * The keyer type splits into two variables - */ - EEPROM.get(CW_KEY_TYPE, x); - - if (x == 0) - Iambic_Key = false; - else if (x == 1){ - Iambic_Key = true; - keyerControl &= ~IAMBICB; - } - else if (x == 2){ - Iambic_Key = true; - keyerControl |= IAMBICB; - } - + LoadSettingsFromEeprom(); } void initPorts(){ @@ -708,22 +461,22 @@ void setup() displayInit(); initSettings(); - initPorts(); + initPorts(); initOscillators(); - frequency = vfoA; - setFrequency(vfoA); + setFrequency(globalSettings.vfoA.frequency); - if (btnDown()){ + //Run initial calibration routine if button is pressed during power up + if(btnDown()){ setupTouch(); - isUSB = 1; + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); setFrequency(10000000l); setupFreq(); - isUSB = 0; + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); setFrequency(7100000l); setupBFO(); } - guiUpdate(); + guiUpdate(); } @@ -731,23 +484,23 @@ void setup() * The loop checks for keydown, ptt, function button and tuning. */ -byte flasher = 0; -boolean wastouched = false; - -void loop(){ - - if (cwMode) - cwKeyer(); - else if (!txCAT) +void loop(){ + if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ + cwKeyer(); + } + else if(!globalSettings.txCatActive){ checkPTT(); + } checkButton(); //tune only when not tranmsitting - if (!inTx){ - if (ritOn) + if(!globalSettings.txActive){ + if(globalSettings.ritOn){ doRIT(); - else + } + else{ doTuning(); + } checkTouch(); } From e9702bd955627f2a9871b2b42aa5d176cd865a5f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 3 Jan 2020 23:43:06 -0800 Subject: [PATCH 021/324] Fix settings - some variables weren't being read quite right --- settings.cpp | 46 +++++++++++++++++++++++++++------------------- settings.h | 4 ++-- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/settings.cpp b/settings.cpp index 5f5aa0b..ffd4c0e 100644 --- a/settings.cpp +++ b/settings.cpp @@ -2,26 +2,27 @@ #include #include #include "settings.h" +#include /** * These are the "magic" indices where these user changable settinngs are stored in the EEPROM */ -static const uint8_t EEPROM_ADDR_MASTER_CAL = 0;//int32_t +static const uint16_t EEPROM_ADDR_MASTER_CAL = 0;//int32_t //4 is currently unused, but may have been LSB_CAL on other versions -static const uint8_t EEPROM_ADDR_USB_CAL = 8;//uint32_t +static const uint16_t EEPROM_ADDR_USB_CAL = 8;//uint32_t //12 is currently unused, but may have been CW_SIDETONE on other versions? -static const uint8_t EEPROM_ADDR_VFO_A_FREQ = 16;//uint32_t -static const uint8_t EEPROM_ADDR_VFO_B_FREQ = 20;//uint32_t -static const uint8_t EEPROM_ADDR_CW_SIDETONE = 24;//uint32_t -static const uint8_t EEPROM_ADDR_CW_DIT_TIME = 28;//uint32_t -static const uint8_t EEPROM_ADDR_TOUCH_SLOPE_X = 32;//int16_t -static const uint8_t EEPROM_ADDR_TOUCH_SLOPE_Y = 36;//int16_t -static const uint8_t EEPROM_ADDR_TOUCH_OFFSET_X = 40;//int16_t -static const uint8_t EEPROM_ADDR_TOUCH_OFFSET_Y = 44;//int16_t -static const uint8_t EEPROM_ADDR_CW_DELAYTIME = 48; -static const uint8_t EEPROM_ADDR_VFO_A_MODE = 256; -static const uint8_t EEPROM_ADDR_VFO_B_MODE = 257; -static const uint8_t EEPROM_ADDR_CW_KEY_TYPE = 358; +static const uint16_t EEPROM_ADDR_VFO_A_FREQ = 16;//uint32_t +static const uint16_t EEPROM_ADDR_VFO_B_FREQ = 20;//uint32_t +static const uint16_t EEPROM_ADDR_CW_SIDETONE = 24;//uint32_t +static const uint16_t EEPROM_ADDR_CW_DIT_TIME = 28;//uint32_t +static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_X = 32;//int16_t +static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_Y = 36;//int16_t +static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_X = 40;//int16_t +static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_Y = 44;//int16_t +static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48; +static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256; +static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257; +static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358; template bool LoadSane(T& dest,uint16_t addr, T min, T max) @@ -30,8 +31,14 @@ bool LoadSane(T& dest,uint16_t addr, T min, T max) EEPROM.get(addr,read_value); if((min <= read_value) && (read_value <= max)){ dest = read_value; + //Serial.print(addr); + //Serial.print(F(":")); + //Serial.println(dest); return true; } + //Serial.print(addr); + //Serial.print(F(": Not valid: ")); + //Serial.println(read_value); return false; } @@ -42,13 +49,13 @@ void LoadDefaultSettings() { memset(&globalSettings,0x00,sizeof(globalSettings)); - globalSettings.oscillatorCal = 0; - globalSettings.usbCarrierFreq = 11052000L; + globalSettings.oscillatorCal = 0L; + globalSettings.usbCarrierFreq = 11052000UL; globalSettings.activeVfo = Vfo_e::VFO_A; - globalSettings.vfoA.frequency = 7150000L; + globalSettings.vfoA.frequency = 7150000UL; globalSettings.vfoA.mode = VFO_MODE_LSB; - globalSettings.vfoB.frequency = 14150000L; + globalSettings.vfoB.frequency = 14150000UL; globalSettings.vfoB.mode = VFO_MODE_USB; globalSettings.keyerMode = KEYER_STRAIGHT; @@ -79,7 +86,7 @@ void LoadSettingsFromEeprom() LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,3500000UL,30000000UL); LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,3500000UL,30000000UL); LoadSane(globalSettings.cwSideToneFreq,EEPROM_ADDR_CW_SIDETONE,100UL,2000UL); - LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10UL,1000UL); + LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10U,1000U); if(LoadSane(globalSettings.cwActiveTimeoutMs,EEPROM_ADDR_CW_DELAYTIME,10U,100U)){ globalSettings.cwActiveTimeoutMs *= 10;//scale by 10 for legacy reasons } @@ -97,6 +104,7 @@ void LoadSettingsFromEeprom() void SaveSettingsToEeprom() { + //Serial.println(F("Saving...")); EEPROM.put(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal); EEPROM.put(EEPROM_ADDR_USB_CAL,globalSettings.usbCarrierFreq); EEPROM.put(EEPROM_ADDR_VFO_A_FREQ,globalSettings.vfoA.frequency); diff --git a/settings.h b/settings.h index 4d2bd39..efd90ba 100644 --- a/settings.h +++ b/settings.h @@ -40,7 +40,7 @@ enum Vfo_e : uint8_t VFO_B }; -enum VfoMode_e : uint16_t +enum VfoMode_e : uint8_t { VFO_MODE_LSB = 2, VFO_MODE_USB = 3 @@ -79,7 +79,7 @@ struct SettingsRam KeyerMode_e keyerMode; uint32_t cwSideToneFreq; - uint32_t cwDitDurationMs; + uint16_t cwDitDurationMs; uint16_t cwActiveTimeoutMs; int16_t touchSlopeX; From 4cefa08eaf7b489643b9b0f5101a73443c7af5b8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 3 Jan 2020 23:43:33 -0800 Subject: [PATCH 022/324] Fix WPM calculations --- ubitx_cat.cpp | 2 +- ubitx_ui.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index d216b78..815c18b 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -211,7 +211,7 @@ void catReadEEPRom(void) //5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps) //7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours //CAT_BUFF[0] = 0x08; - cat[0] = 12000 / globalSettings.cwDitDurationMs - 4; + cat[0] = 1200 / globalSettings.cwDitDurationMs - 4; cat[1] = 0xB2; break; case 0x63 : // diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 7e48a1a..aff1be5 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -532,7 +532,7 @@ void enterFreq(){ void drawCWStatus(){ strcpy(b, " cw: "); - int wpm = 12000/globalSettings.cwDitDurationMs; + int wpm = 1200/globalSettings.cwDitDurationMs; itoa(wpm,c, 10); strcat(b, c); strcat(b, "wpm, "); @@ -770,11 +770,11 @@ void switchBand(uint32_t bandfreq){ void setCwSpeed() { - int wpm = 12000/globalSettings.cwDitDurationMs; + int wpm = 1200/globalSettings.cwDitDurationMs; wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM"); - globalSettings.cwDitDurationMs = 12000/wpm; + globalSettings.cwDitDurationMs = 1200/wpm; SaveSettingsToEeprom(); active_delay(500); drawStatusbar(); From 9ebdf8b213dd6c4996796ec35b294ccc86016c2e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 00:53:00 -0800 Subject: [PATCH 023/324] Render setup menus better --- setup.cpp | 108 ++++++++++++++++++++++++++++++++++++--------------- ubitx.h | 7 ---- ubitx_ui.cpp | 24 ------------ 3 files changed, 77 insertions(+), 62 deletions(-) diff --git a/setup.cpp b/setup.cpp index c37f433..90ea02a 100644 --- a/setup.cpp +++ b/setup.cpp @@ -25,6 +25,67 @@ void setupExit(){ extern int32_t calibration; extern uint32_t si5351bx_vcoa; +static const unsigned int COLOR_TEXT = DISPLAY_WHITE; +static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK; +static const unsigned int COLOR_TITLE_BACKGROUND = DISPLAY_NAVY; +static const unsigned int COLOR_SETTING_BACKGROUND = DISPLAY_NAVY; +static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; +static const unsigned int COLOR_INACTIVE_BORDER = COLOR_BACKGROUND; + +static const unsigned int LAYOUT_OUTER_BORDER_X = 10; +static const unsigned int LAYOUT_OUTER_BORDER_Y = 10; +static const unsigned int LAYOUT_OUTER_BORDER_WIDTH = 300; +static const unsigned int LAYOUT_OUTER_BORDER_HEIGHT = 220; + +static const unsigned int LAYOUT_INNER_BORDER_X = 12; +static const unsigned int LAYOUT_INNER_BORDER_Y = 12; +static const unsigned int LAYOUT_INNER_BORDER_WIDTH = 296; +static const unsigned int LAYOUT_INNER_BORDER_HEIGHT = 216; + +static const unsigned int LAYOUT_TITLE_X = LAYOUT_INNER_BORDER_X; +static const unsigned int LAYOUT_TITLE_Y = LAYOUT_INNER_BORDER_Y; +static const unsigned int LAYOUT_TITLE_WIDTH = LAYOUT_INNER_BORDER_WIDTH; +static const unsigned int LAYOUT_TITLE_HEIGHT = 35; + +static const unsigned int LAYOUT_ITEM_X = 30; +static const unsigned int LAYOUT_ITEM_Y = LAYOUT_TITLE_Y + LAYOUT_TITLE_HEIGHT + 5; +static const unsigned int LAYOUT_ITEM_WIDTH = 260; +static const unsigned int LAYOUT_ITEM_HEIGHT = 30; +static const unsigned int LAYOUT_ITEM_PITCH_Y = LAYOUT_ITEM_HEIGHT + 1; + +static const unsigned int LAYOUT_SETTING_VALUE_X = LAYOUT_ITEM_X; +static const unsigned int LAYOUT_SETTING_VALUE_Y = LAYOUT_ITEM_Y + 3*LAYOUT_ITEM_PITCH_Y; +static const unsigned int LAYOUT_SETTING_VALUE_WIDTH = LAYOUT_ITEM_WIDTH; +static const unsigned int LAYOUT_SETTING_VALUE_HEIGHT = LAYOUT_ITEM_HEIGHT; + +static const unsigned int LAYOUT_INSTRUCTION_TEXT_X = 20; +static const unsigned int LAYOUT_INSTRUCTION_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_ITEM_PITCH_Y; +static const unsigned int LAYOUT_INSTRUCTION_TEXT_WIDTH = LAYOUT_ITEM_WIDTH; +static const unsigned int LAYOUT_INSTRUCTION_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT; + +void displayDialog(char *title, char *instructions){ + displayClear(COLOR_BACKGROUND); + displayRect(LAYOUT_OUTER_BORDER_X,LAYOUT_OUTER_BORDER_Y,LAYOUT_OUTER_BORDER_WIDTH,LAYOUT_OUTER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); + displayRect(LAYOUT_INNER_BORDER_X,LAYOUT_INNER_BORDER_Y,LAYOUT_INNER_BORDER_WIDTH,LAYOUT_INNER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); + displayText(title, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); + displayText(instructions, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); +} + +void printCarrierFreq(unsigned long freq){ + + memset(c, 0, sizeof(c)); + memset(b, 0, sizeof(b)); + + ultoa(freq, b, DEC); + + strncat(c, b, 2); + strcat(c, "."); + strncat(c, &b[2], 3); + strcat(c, "."); + strncat(c, &b[5], 1); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); +} + void setupFreq(){ int knob = 0; int32_t prev_calibration; @@ -35,13 +96,15 @@ void setupFreq(){ frequency = (frequency/1000l)* 1000l; setFrequency(frequency); - displayRawText("You should have a", 20, 50, DISPLAY_CYAN, DISPLAY_NAVY); - displayRawText("signal exactly at ", 20, 75, DISPLAY_CYAN, DISPLAY_NAVY); + displayText("You should have a", LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText("signal exactly at ", LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 1*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); ltoa(frequency/1000l, c, 10); strcat(c, " KHz"); - displayRawText(c, 20, 100, DISPLAY_CYAN, DISPLAY_NAVY); - - displayRawText("Rotate to zerobeat", 20, 180, DISPLAY_CYAN, DISPLAY_NAVY); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 2*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText("Rotate to zerobeat", LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + + ltoa(calibration, b, 10); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); //keep clear of any previous button press while (btnDown()) active_delay(100); @@ -72,7 +135,7 @@ void setupFreq(){ //displayRawText("Rotate to zerobeat", 20, 120, DISPLAY_CYAN, DISPLAY_NAVY); ltoa(calibration, b, 10); - displayText(b, 100, 140, 100, 26, DISPLAY_CYAN, DISPLAY_NAVY, DISPLAY_WHITE); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); } EEPROM.put(MASTER_CAL, calibration); @@ -131,7 +194,7 @@ void setupCwDelay(){ itoa(10 * (int)cwDelayTime, b, 10); strcat(b, " msec"); - displayText(b, 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); while (!btnDown()){ knob = enc_read(); @@ -145,7 +208,7 @@ void setupCwDelay(){ itoa(10 * (int)cwDelayTime, b, 10); strcat(b, " msec"); - displayText(b, 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); } @@ -164,11 +227,11 @@ void setupKeyer(){ displayDialog("Set CW Keyer", "Press tune to Save"); if (!Iambic_Key) - displayText("< Hand Key >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText("< Hand Key >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); else if (keyerControl & IAMBICB) - displayText("< Iambic A >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText("< Iambic A >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); else - displayText("< Iambic B >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText("< Iambic B >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); if (!Iambic_Key) tmp_key = 0; //hand key @@ -192,11 +255,11 @@ void setupKeyer(){ tmp_key = 0; if (tmp_key == 0) - displayText("< Hand Key >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText("< Hand Key >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); else if (tmp_key == 1) - displayText("< Iambic A >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText("< Iambic A >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); else if (tmp_key == 2) - displayText("< Iambic B >", 100, 100, 120, 26, DISPLAY_CYAN, DISPLAY_BLACK, DISPLAY_BLACK); + displayText("< Iambic B >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); } active_delay(500); @@ -216,23 +279,6 @@ void setupKeyer(){ menuOn = 0; } -static const unsigned int COLOR_TEXT = DISPLAY_WHITE; -static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK; -static const unsigned int COLOR_TITLE_BACKGROUND = DISPLAY_NAVY; -static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; -static const unsigned int COLOR_INACTIVE_BORDER = DISPLAY_DARKGREY; - -static const unsigned int LAYOUT_TITLE_X = 10; -static const unsigned int LAYOUT_TITLE_Y = 10; -static const unsigned int LAYOUT_TITLE_WIDTH = 300; -static const unsigned int LAYOUT_TITLE_HEIGHT = 35; - -static const unsigned int LAYOUT_ITEM_X = 30; -static const unsigned int LAYOUT_ITEM_Y = LAYOUT_TITLE_Y + LAYOUT_TITLE_HEIGHT + 5; -static const unsigned int LAYOUT_ITEM_WIDTH = 260; -static const unsigned int LAYOUT_ITEM_HEIGHT = 30; -static const unsigned int LAYOUT_ITEM_PITCH_Y = 31; - const char MI_SET_FREQ [] PROGMEM = "Set Freq..."; const char MI_SET_BFO [] PROGMEM = "Set BFO..."; const char MI_CW_DELAY [] PROGMEM = "CW Delay..."; diff --git a/ubitx.h b/ubitx.h index 10fdc63..15bf3a5 100644 --- a/ubitx.h +++ b/ubitx.h @@ -196,13 +196,6 @@ void doSetup2(); //main setup function, displays the setup menu, calls various d void setupBFO(); void setupFreq(); - - -//displays a nice dialog box with a title and instructions as footnotes -void displayDialog(char *title, char *instructions); -void printCarrierFreq(unsigned long freq); //used to display the frequency in the command area (ex: fast tuning) - - //main functions to check if any button is pressed and other user interface events void doCommands(); //does the commands with encoder to jump from button to button void checkTouch(); //does the commands with a touch on the buttons diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 07e4b4d..ac8c817 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -218,30 +218,6 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* return knob_value; } -void printCarrierFreq(unsigned long freq){ - - memset(c, 0, sizeof(c)); - memset(b, 0, sizeof(b)); - - ultoa(freq, b, DEC); - - strncat(c, b, 2); - strcat(c, "."); - strncat(c, &b[2], 3); - strcat(c, "."); - strncat(c, &b[5], 1); - displayText(c, 110, 100, 100, 30, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); -} - -void displayDialog(char *title, char *instructions){ - displayClear(COLOR_BACKGROUND); - displayRect(10,10,300,220, COLOR_TEXT); - displayHline(20,45,280,COLOR_TEXT); - displayRect(12,12,296,216, COLOR_TEXT); - displayRawText(title, 20, 20, COLOR_TEXT, COLOR_BACKGROUND); - displayRawText(instructions, 20, 200, COLOR_TEXT, COLOR_BACKGROUND); -} - void displayVFO(int vfo){ int x, y; int displayColor, displayBackground, displayBorder; From 29aa76edf5dd79c907f1e77b464fc58858a430a2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 01:10:10 -0800 Subject: [PATCH 024/324] Make strings progmem, saving ~200 bytes of RAM --- setup.cpp | 81 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/setup.cpp b/setup.cpp index 90ea02a..f6d74d9 100644 --- a/setup.cpp +++ b/setup.cpp @@ -63,12 +63,14 @@ static const unsigned int LAYOUT_INSTRUCTION_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_I static const unsigned int LAYOUT_INSTRUCTION_TEXT_WIDTH = LAYOUT_ITEM_WIDTH; static const unsigned int LAYOUT_INSTRUCTION_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT; -void displayDialog(char *title, char *instructions){ +void displayDialog(const __FlashStringHelper* title, const __FlashStringHelper* instructions){ + strcpy_P(b,(const char*)title); + strcpy_P(c,(const char*)instructions); displayClear(COLOR_BACKGROUND); displayRect(LAYOUT_OUTER_BORDER_X,LAYOUT_OUTER_BORDER_Y,LAYOUT_OUTER_BORDER_WIDTH,LAYOUT_OUTER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); displayRect(LAYOUT_INNER_BORDER_X,LAYOUT_INNER_BORDER_Y,LAYOUT_INNER_BORDER_WIDTH,LAYOUT_INNER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); - displayText(title, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); - displayText(instructions, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); + displayText(c, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } void printCarrierFreq(unsigned long freq){ @@ -79,9 +81,9 @@ void printCarrierFreq(unsigned long freq){ ultoa(freq, b, DEC); strncat(c, b, 2); - strcat(c, "."); + strcat_P(c,(const char*)F(".")); strncat(c, &b[2], 3); - strcat(c, "."); + strcat(c,(const char*)F(".")); strncat(c, &b[5], 1); displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); } @@ -90,18 +92,21 @@ void setupFreq(){ int knob = 0; int32_t prev_calibration; - displayDialog("Set Frequency", "Push TUNE to Save"); + displayDialog(F("Set Frequency"),F("Push TUNE to Save")); //round off the the nearest khz frequency = (frequency/1000l)* 1000l; setFrequency(frequency); - displayText("You should have a", LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - displayText("signal exactly at ", LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 1*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + strcpy_P(c,(const char*)F("You should have a")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + strcpy_P(c,(const char*)F("signal exactly at")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 1*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); ltoa(frequency/1000l, c, 10); - strcat(c, " KHz"); + strcat_P(c,(const char*)F(" KHz")); displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 2*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - displayText("Rotate to zerobeat", LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + strcpy_P(c,(const char*)F("Rotate to zerobeat")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); ltoa(calibration, b, 10); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); @@ -113,11 +118,6 @@ void setupFreq(){ prev_calibration = calibration; calibration = 0; -// ltoa(calibration/8750, c, 10); -// strcpy(b, c); -// strcat(b, "Hz"); -// printLine2(b); - while (!btnDown()) { knob = enc_read(); @@ -131,8 +131,6 @@ void setupFreq(){ si5351bx_setfreq(0, usbCarrier); //set back the cardrier oscillator anyway, cw tx switches it off si5351_set_calibration(calibration); setFrequency(frequency); - - //displayRawText("Rotate to zerobeat", 20, 120, DISPLAY_CYAN, DISPLAY_NAVY); ltoa(calibration, b, 10); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); @@ -155,7 +153,7 @@ void setupBFO(){ prevCarrier = usbCarrier; - displayDialog("Set BFO", "Press TUNE to Save"); + displayDialog(F("Set BFO"),F("Press TUNE to Save")); usbCarrier = 11053000l; si5351bx_setfreq(0, usbCarrier); @@ -187,13 +185,13 @@ void setupCwDelay(){ int knob = 0; int prev_cw_delay; - displayDialog("Set CW T/R Delay", "Press tune to Save"); + displayDialog(F("Set CW T/R Delay"),F("Press tune to Save")); active_delay(500); prev_cw_delay = cwDelayTime; itoa(10 * (int)cwDelayTime, b, 10); - strcat(b, " msec"); + strcat_P(b,(const char*)F(" msec")); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); while (!btnDown()){ @@ -207,16 +205,13 @@ void setupCwDelay(){ continue; //don't update the frequency or the display itoa(10 * (int)cwDelayTime, b, 10); - strcat(b, " msec"); + strcat_P(b,(const char*)F(" msec")); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); } EEPROM.put(CW_DELAYTIME, cwDelayTime); - -// cwDelayTime = getValueByKnob(10, 1000, 50, cwDelayTime, "CW Delay>", " msec"); - active_delay(500); menuOn = 0; } @@ -224,14 +219,20 @@ void setupCwDelay(){ void setupKeyer(){ int tmp_key, knob; - displayDialog("Set CW Keyer", "Press tune to Save"); + displayDialog(F("Set CW Keyer"),F("Press tune to Save")); - if (!Iambic_Key) - displayText("< Hand Key >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - else if (keyerControl & IAMBICB) - displayText("< Iambic A >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - else - displayText("< Iambic B >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + if (!Iambic_Key){ + strcpy_P(c,(const char*)F("< Hand Key >")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } + else if (keyerControl & IAMBICB){ + strcpy_P(c,(const char*)F("< Iambic A >")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } + else{ + strcpy_P(c,(const char*)F("< Iambic B >")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } if (!Iambic_Key) tmp_key = 0; //hand key @@ -254,12 +255,18 @@ void setupKeyer(){ if (tmp_key > 2) tmp_key = 0; - if (tmp_key == 0) - displayText("< Hand Key >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - else if (tmp_key == 1) - displayText("< Iambic A >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - else if (tmp_key == 2) - displayText("< Iambic B >", LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + if (tmp_key == 0){ + strcpy_P(c,(const char*)F("< Hand Key >")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } + else if (tmp_key == 1){ + strcpy_P(c,(const char*)F("< Iambic A >")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } + else if (tmp_key == 2){ + strcpy_P(c,(const char*)F("< Iambic B >")); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } } active_delay(500); From fbfb7c89d6920a7e21ea45f51305282f6c2eb4f5 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 01:50:17 -0800 Subject: [PATCH 025/324] Fix merge issue --- setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cpp b/setup.cpp index 7e9b3d2..fa4915c 100644 --- a/setup.cpp +++ b/setup.cpp @@ -111,7 +111,7 @@ void setupFreq(){ strcpy_P(c,(const char*)F("Rotate to zerobeat")); displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - ltoa(calibration, b, 10); + ltoa(globalSettings.oscillatorCal, b, 10); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); //keep clear of any previous button press while (btnDown()) From 8d34a3461b7ed7deb282d218a315f79361f1f732 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 01:56:05 -0800 Subject: [PATCH 026/324] Fix ritToggle logic --- ubitx_ui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index f27abdf..9aa6e75 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -628,7 +628,7 @@ int enc_read(void) { } void ritToggle(struct Button *button){ - if (globalSettings.ritOn){ + if(!globalSettings.ritOn){ ritEnable(GetActiveVfoFreq()); } else{ From 7f3eee899a3b8934fe26fc7c4214e3df8cc8100a Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 02:05:39 -0800 Subject: [PATCH 027/324] Fix RIT frequency rendering --- ubitx_ui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index ac8c817..ec29dd3 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -365,9 +365,9 @@ void displayRIT(){ strcpy_P(c,(const char*)F("TX:")); formatFreq(ritTxFrequency, c+3); if (vfoActive == VFO_A) - displayText(c, LAYOUT_MODE_TEXT_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(c, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); else - displayText(c, LAYOUT_MODE_TEXT_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(c, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } } From a2109de63f4b5253523f43705ddbe86eb1d8cd98 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 02:14:21 -0800 Subject: [PATCH 028/324] Fix issue with RIT restore during VFO change --- ubitx_v6.3.1_code.ino | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 4e73bf4..a25964d 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -336,6 +336,8 @@ void checkButton(){ } void switchVFO(Vfo_e new_vfo){ + ritDisable();//If we are in RIT mode, we need to disable it before setting the active VFO so that the correct VFO gets it's frequency restored + globalSettings.activeVfo = new_vfo; setFrequency(GetActiveVfoFreq()); redrawVFOs(); From 4674230f513ee60c76c5d02c73d1585ba24d2f9a Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 02:41:06 -0800 Subject: [PATCH 029/324] Make more strings progmem. Probably should consolidate strings at some point so that we don't have lots of duplicate '.' and 'Hz' floating around --- ubitx_ui.cpp | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 8ea3067..0e6fc11 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -165,12 +165,12 @@ void formatFreq(long f, char *buff) { if (f < 10000000l){ buff[0] = ' '; strncat(buff, b, 4); - strcat(buff, "."); + strcat_P(buff,(const char*)F(".")); strncat(buff, &b[4], 2); } else { strncat(buff, b, 5); - strcat(buff, "."); + strcat_P(buff,(const char*)F(".")); strncat(buff, &b[5], 2); } } @@ -181,7 +181,7 @@ inline void drawCommandbar(char* text){ /** A generic control to read variable values */ -int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix) +int getValueByKnob(int minimum, int maximum, int step_size, int initial, const __FlashStringHelper* prefix, const __FlashStringHelper* postfix) { int knob = 0; int knob_value; @@ -192,10 +192,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* active_delay(200); knob_value = initial; - strcpy(b, prefix); + strcpy_P(b,(const char*)prefix); itoa(knob_value, c, 10); strcat(b, c); - strcat(b, postfix); + strcat_P(b, (const char*)postfix); drawCommandbar(b); while(!btnDown() && digitalRead(PTT) == HIGH){ @@ -206,10 +206,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* if (knob_value < maximum && knob > 0) knob_value += step_size; - strcpy(b, prefix); + strcpy_P(b,(const char*)prefix); itoa(knob_value, c, 10); strcat(b, c); - strcat(b, postfix); + strcat_P(b,(const char*)postfix); drawCommandbar(b); } checkCAT(); @@ -376,7 +376,8 @@ void fastTune(){ active_delay(50); active_delay(300); - displayText("Fast tune", LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + strcpy_P(c,(const char*)F("Fast tune")); + displayText(c, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); while(1){ checkCAT(); @@ -498,7 +499,7 @@ void enterFreq(){ }//if button hit test }// end of the button scanning loop strcpy(b, c); - strcat(b, " KHz"); + strcat_P(b,(const char*)F(" KHz")); displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); active_delay(300); while(readTouch()) @@ -507,23 +508,26 @@ void enterFreq(){ } void drawCWStatus(){ - strcpy(b, " cw: "); + strcpy_P(b,(const char*)F(" cw: ")); int wpm = 1200/globalSettings.cwDitDurationMs; itoa(wpm,c, 10); strcat(b, c); - strcat(b, "wpm, "); + strcat_P(b,(const char*)F("wpm, ")); itoa(globalSettings.cwSideToneFreq, c, 10); strcat(b, c); - strcat(b, "hz"); + strcat_P(b,(const char*)F("hz")); displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } void drawTx(){ - if (globalSettings.txActive) - displayText("TX", LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND); - else + if (globalSettings.txActive){ + strcpy_P(b,(const char*)F("TX")); + displayText(b, LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND); + } + else{ displayFillrect(LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_BACKGROUND); + } } void drawStatusbar(){ drawCWStatus(); @@ -748,7 +752,7 @@ void setCwSpeed() { int wpm = 1200/globalSettings.cwDitDurationMs; - wpm = getValueByKnob(1, 100, 1, wpm, "CW: ", " WPM"); + wpm = getValueByKnob(1, 100, 1, wpm,F("CW: "),F(" WPM")); globalSettings.cwDitDurationMs = 1200/wpm; SaveSettingsToEeprom(); @@ -764,9 +768,9 @@ void setCwTone(){ tone(CW_TONE, globalSettings.cwSideToneFreq); itoa(globalSettings.cwSideToneFreq, c, 10); - strcpy(b, "CW Tone: "); + strcpy_P(b,(const char*)F("CW Tone: ")); strcat(b, c); - strcat(b, " Hz"); + strcat_P(b,(const char*)F(" Hz")); drawCommandbar(b); //disable all clock 1 and clock 2 @@ -783,9 +787,9 @@ void setCwTone(){ tone(CW_TONE, globalSettings.cwSideToneFreq); itoa(globalSettings.cwSideToneFreq, c, 10); - strcpy(b, "CW Tone: "); + strcpy_P(b,(const char*)F("CW Tone: ")); strcat(b, c); - strcat(b, " Hz"); + strcat_P(b,(const char*)F(" Hz")); drawCommandbar(b); //printLine2(b); From a0abe466c0efd6c2fb1e20c3f9eb289a1acecf69 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 02:52:56 -0800 Subject: [PATCH 030/324] Redraw VFO after mode change so that UI will reflect active setting --- settings.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/settings.cpp b/settings.cpp index ffd4c0e..eb95c18 100644 --- a/settings.cpp +++ b/settings.cpp @@ -1,8 +1,9 @@ #include //memset #include #include +#include //only needed for debugging's Serial.print stuff #include "settings.h" -#include +#include "ubitx.h"//redrawVFOs() function /** * These are the "magic" indices where these user changable settinngs are stored in the EEPROM @@ -161,4 +162,5 @@ void SetActiveVfoMode(VfoMode_e mode) else{ globalSettings.vfoB.mode = mode; } + redrawVFOs(); } From b655704264d7160a1d1ee4c2d2b11386173ed324 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 02:53:33 -0800 Subject: [PATCH 031/324] Update side band when band buttons are used --- ubitx_ui.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 0e6fc11..1f63bc1 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -744,7 +744,15 @@ void switchBand(uint32_t bandfreq){ //Serial.println(offset); setFrequency(bandfreq + offset); - updateDisplay(); + + if(bandfreq >= THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + } + else{ + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + } + + updateDisplay(); saveVFOs(); } From 9a68846b5814ca716f311801b05a3bffeb0987d2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 4 Jan 2020 22:51:29 -0800 Subject: [PATCH 032/324] Use correct version of strcat for flash strings --- setup.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cpp b/setup.cpp index fa4915c..f8f5feb 100644 --- a/setup.cpp +++ b/setup.cpp @@ -83,7 +83,7 @@ void printCarrierFreq(unsigned long freq){ strncat(c, b, 2); strcat_P(c,(const char*)F(".")); strncat(c, &b[2], 3); - strcat(c,(const char*)F(".")); + strcat_P(c,(const char*)F(".")); strncat(c, &b[5], 1); displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); } From ef8036ee19414a87d0e2db523d10688eeba5cad8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 6 Jan 2020 21:50:21 -0800 Subject: [PATCH 033/324] Fix 'F' morse code representation - currently is same as 'L'. First noticed by K7OME --- morse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/morse.cpp b/morse.cpp index d1b6dd5..0311c5e 100644 --- a/morse.cpp +++ b/morse.cpp @@ -20,7 +20,7 @@ static const PROGMEM struct Morse morse_table[] = { {'c', 0xea}, // 11101010 {'d', 0xf4}, // 11110100 {'e', 0xfc}, // 11111100 -{'f', 0xe4}, // 11100100 +{'f', 0xe2}, // 11100010 {'g', 0xf6}, // 11110110 {'h', 0xe0}, // 11100000 {'i', 0xf8}, // 11111000 From f1ea1fd081d128895f336d0ca16de6246a422f2f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 7 Jan 2020 23:07:44 -0800 Subject: [PATCH 034/324] Eliminate white screen syndrome by using the 'exit deep sleep' command sequence --- nano_gui.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/nano_gui.cpp b/nano_gui.cpp index a801d58..b566c71 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -153,6 +153,14 @@ bool xpt2046_Init(){ } void displayInit(void){ + //Pulling this low 6 times should exit deep sleep mode + pinMode(TFT_CS,OUTPUT); + for(uint8_t i = 0; i < 6; ++i){ + digitalWrite(TFT_CS,HIGH); + digitalWrite(TFT_CS,LOW); + } + digitalWrite(TFT_CS,HIGH);//Disable writing for now + tft.begin(); tft.setFont(ubitx_font); tft.setTextWrap(false); From 228b5d95896eacef67f0143a7510eb0744abb05d Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Sat, 11 Jan 2020 11:00:44 -0800 Subject: [PATCH 035/324] Merged in @SmittyHalibut's interrupt driven encoder routines. --- ubitx.h | 1 + ubitx_ui.cpp | 91 ++++++++++++++++++++++++++++++++++++++++++- ubitx_v6.3.1_code.ino | 39 +++++++++++-------- 3 files changed, 112 insertions(+), 19 deletions(-) diff --git a/ubitx.h b/ubitx.h index 15bf3a5..90fa571 100644 --- a/ubitx.h +++ b/ubitx.h @@ -179,6 +179,7 @@ void cwKeyer(void); void switchVFO(int vfoSelect); int enc_read(void); // returns the number of ticks in a short interval, +ve in clockwise, -ve in anti-clockwise +void enc_setup(void); // Setups up initial values and interrupts. int btnDown(); //returns true if the encoder button is pressed /* these functions are called universally to update the display */ diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index ec29dd3..8501f4d 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -565,7 +565,6 @@ void updateDisplay() { displayVFO(vfoActive); } -int enc_prev_state = 3; /** * The A7 And A6 are purely analog lines on the Arduino Nano @@ -585,11 +584,15 @@ int enc_prev_state = 3; * at which the enccoder was spun */ +/* +int enc_prev_state = 3; + byte enc_state (void) { //Serial.print(digitalRead(ENC_A)); Serial.print(":");Serial.println(digitalRead(ENC_B)); return (digitalRead(ENC_A) == 1 ? 1 : 0) + (digitalRead(ENC_B) == 1 ? 2: 0); } + int enc_read(void) { int result = 0; byte newState; @@ -627,6 +630,91 @@ int enc_read(void) { // Serial.println(result); return(result); } +*/ + +/* + * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. + */ +int enc_count; +uint8_t prev_enc; + +uint8_t enc_state (void) { + return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0); +} + +/* + * Setup the encoder interrupts and global variables. + */ +void pci_setup(byte pin) { + *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin + PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt + PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group +} + +void enc_setup(void) { + enc_count = 0; + // This is already done in setup() ? + //pinMode(ENC_A, INPUT); + //pinMode(ENC_B, INPUT); + prev_enc = enc_state(); + + // Setup Pin Change Interrupts for the encoder inputs + pci_setup(ENC_A); + pci_setup(ENC_B); +} + +/* + * The Interrupt Service Routine for Pin Change Interrupts on A0-A5. + */ +ISR (PCINT1_vect) { + uint8_t cur_enc = enc_state(); + if (prev_enc == cur_enc) { + //Serial.println("unnecessary ISR"); + return; + } + //Serial.print(prev_enc); + //Serial.println(cur_enc); + + //these transitions point to the enccoder being rotated anti-clockwise + if ((prev_enc == 0 && cur_enc == 2) || + (prev_enc == 2 && cur_enc == 3) || + (prev_enc == 3 && cur_enc == 1) || + (prev_enc == 1 && cur_enc == 0)) + { + enc_count-=1; + } + //these transitions point to the enccoder being rotated clockwise + else if ((prev_enc == 0 && cur_enc == 1) || + (prev_enc == 1 && cur_enc == 3) || + (prev_enc == 3 && cur_enc == 2) || + (prev_enc == 2 && cur_enc == 0)) + { + enc_count+=1; + } + else { + // A change to two states, we can't tell whether it was forward or backward, so we skip it. + //Serial.println("skip"); + } + prev_enc = cur_enc; // Record state for next pulse interpretation +} + +int enc_read(void) { + int ret = enc_count; + enc_count = 0; + if (ret == 255 || ret == -256) { + // FIXME I (@SmittyHalibut) can't figure out why we occasionally get + // either a 255 or -256 return value here. It's like it's occasionally + // treating an int as an unsigned value while incrementing or decrementing. + // I can't figure out why, but I can detect it and skip it. So that's + // what we're doing. + //Serial.println("255 error in encoder."); + return 0; + } + return ret; +} + + + void ritToggle(struct Button *button){ if (ritOn == 0){ @@ -1021,4 +1109,3 @@ void doCommands(){ checkCAT(); } - diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index d2518d1..3c32faf 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -522,32 +522,30 @@ void doTuning(){ unsigned long now = millis(); - if (now >= nextFrequencyUpdate && prev_freq != frequency){ - updateDisplay(); - nextFrequencyUpdate = now + 500; - prev_freq = frequency; - } - s = enc_read(); if (!s) return; + //Serial.print(s); + doingCAT = 0; // go back to manual mode if you were doing CAT prev_freq = frequency; - - if (s > 10) - frequency += 200l * s; - else if (s > 5) - frequency += 100l * s; - else if (s > 0) + // TODO With the new more responsive tuning, 5 and 10 are nearly useless + // thresholds for acceleration. I rarely see above 2 or 3 even when turning + // the knob quickly. + if (s < 5 && s > -5) { frequency += 50l * s; - else if (s < -10) - frequency += 200l * s; - else if (s < -5) + //Serial.println(" 5"); + } + else if (s < 10 && s > -10) { frequency += 100l * s; - else if (s < 0) - frequency += 50l * s; + //Serial.println(" 10"); + } + else { // if (s >= 10 || s <= -10) + frequency += 200l * s; + //Serial.println(" <"); + } if (prev_freq < 10000000l && frequency > 10000000l) isUSB = true; @@ -556,6 +554,12 @@ void doTuning(){ isUSB = false; setFrequency(frequency); + + if (now >= nextFrequencyUpdate && prev_freq != frequency){ + updateDisplay(); + nextFrequencyUpdate = now + 100; + prev_freq = frequency; + } } @@ -676,6 +680,7 @@ void initPorts(){ pinMode(ENC_A, INPUT_PULLUP); pinMode(ENC_B, INPUT_PULLUP); pinMode(FBUTTON, INPUT_PULLUP); + enc_setup(); //configure the function button to use the external pull-up // pinMode(FBUTTON, INPUT); From 858205b4cdeb41c746d811909bb3a58e7ec2f523 Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Sat, 11 Jan 2020 11:15:47 -0800 Subject: [PATCH 036/324] Fixed 255/-256 encoder bug. --- ubitx_ui.cpp | 15 +++------------ ubitx_v6.3.1_code.ino | 2 +- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 8501f4d..49b49bd 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -635,7 +635,7 @@ int enc_read(void) { /* * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. */ -int enc_count; +int8_t enc_count; uint8_t prev_enc; uint8_t enc_state (void) { @@ -699,18 +699,9 @@ ISR (PCINT1_vect) { } int enc_read(void) { - int ret = enc_count; + int8_t ret = enc_count; enc_count = 0; - if (ret == 255 || ret == -256) { - // FIXME I (@SmittyHalibut) can't figure out why we occasionally get - // either a 255 or -256 return value here. It's like it's occasionally - // treating an int as an unsigned value while incrementing or decrementing. - // I can't figure out why, but I can detect it and skip it. So that's - // what we're doing. - //Serial.println("255 error in encoder."); - return 0; - } - return ret; + return int(ret); } diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 3c32faf..338e1e2 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -526,7 +526,7 @@ void doTuning(){ if (!s) return; - //Serial.print(s); + //Serial.println(s); doingCAT = 0; // go back to manual mode if you were doing CAT prev_freq = frequency; From 50a00ffb52ca8251b3c4744bf95f7ca74c943283 Mon Sep 17 00:00:00 2001 From: Mark Smith Date: Sat, 11 Jan 2020 11:22:42 -0800 Subject: [PATCH 037/324] moved display update back to where it'll update on non-encoder-wheel changes. --- ubitx_v6.3.1_code.ino | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 338e1e2..e00a47a 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -522,6 +522,12 @@ void doTuning(){ unsigned long now = millis(); + if (now >= nextFrequencyUpdate && prev_freq != frequency){ + updateDisplay(); + nextFrequencyUpdate = now + 100; + prev_freq = frequency; + } + s = enc_read(); if (!s) return; @@ -554,12 +560,6 @@ void doTuning(){ isUSB = false; setFrequency(frequency); - - if (now >= nextFrequencyUpdate && prev_freq != frequency){ - updateDisplay(); - nextFrequencyUpdate = now + 100; - prev_freq = frequency; - } } From 227cbe9b071caaf2564323ff262c1bf14a05a285 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 13 Jan 2020 23:38:12 -0800 Subject: [PATCH 038/324] Load EEPROM settings immediately, and load defaults prior to loading EEPROM values so that we fall back on defaults rather than 0's --- nano_gui.cpp | 1 - ubitx_v6.3.1_code.ino | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index a3932ac..938ccee 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -157,7 +157,6 @@ void displayInit(void){ tft.setRotation(1); xpt2046_Init(); - readTouchCalibration(); } void displayPixel(unsigned int x, unsigned int y, unsigned int c){ diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index a25964d..4af8c35 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -420,6 +420,7 @@ void doRIT(){ * variables. */ void initSettings(){ + LoadDefaultSettings(); LoadSettingsFromEeprom(); } @@ -461,8 +462,8 @@ void setup() Serial.begin(38400); Serial.flush(); - displayInit(); initSettings(); + displayInit(); initPorts(); initOscillators(); setFrequency(globalSettings.vfoA.frequency); From f6894e03f817eb65eeb5123e63bc6eda8b4a0138 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 13 Jan 2020 23:38:43 -0800 Subject: [PATCH 039/324] Add more debugging context (commented out) --- settings.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/settings.cpp b/settings.cpp index eb95c18..dac384a 100644 --- a/settings.cpp +++ b/settings.cpp @@ -39,7 +39,9 @@ bool LoadSane(T& dest,uint16_t addr, T min, T max) } //Serial.print(addr); //Serial.print(F(": Not valid: ")); - //Serial.println(read_value); + //Serial.print(read_value); + //Serial.print(F(" Leaving value at ")); + //Serial.println(dest); return false; } From 6e797adc7021fbb1dc1661beab3371e3b275168d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 14 Jan 2020 22:07:24 -0800 Subject: [PATCH 040/324] Expand range of allowed sane frequencies to anything the tuner driver will actually tune --- settings.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/settings.cpp b/settings.cpp index dac384a..2c395a1 100644 --- a/settings.cpp +++ b/settings.cpp @@ -86,8 +86,8 @@ void LoadDefaultSettings() void LoadSettingsFromEeprom() { LoadSane(globalSettings.usbCarrierFreq,EEPROM_ADDR_USB_CAL,11048000UL,11060000UL); - LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,3500000UL,30000000UL); - LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,3500000UL,30000000UL); + LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver + LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver LoadSane(globalSettings.cwSideToneFreq,EEPROM_ADDR_CW_SIDETONE,100UL,2000UL); LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10U,1000U); if(LoadSane(globalSettings.cwActiveTimeoutMs,EEPROM_ADDR_CW_DELAYTIME,10U,100U)){ From 9a205522d90722d75e253c1ea1150aa5a9ff5115 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 14 Jan 2020 22:22:26 -0800 Subject: [PATCH 041/324] Don't reset cals to fixed values when starting cal routine --- setup.cpp | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/setup.cpp b/setup.cpp index f8f5feb..7be7b14 100644 --- a/setup.cpp +++ b/setup.cpp @@ -89,9 +89,6 @@ void printCarrierFreq(unsigned long freq){ } void setupFreq(){ - int knob = 0; - int32_t prev_calibration; - displayDialog(F("Set Frequency"),F("Push TUNE to Save")); //round off the the nearest khz @@ -105,7 +102,7 @@ void setupFreq(){ displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); strcpy_P(c,(const char*)F("signal exactly at")); displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 1*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - ltoa(GetActiveVfoFreq()/1000l, c, 10); + ltoa(GetActiveVfoFreq()/1000L, c, 10); strcat_P(c,(const char*)F(" KHz")); displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 2*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); strcpy_P(c,(const char*)F("Rotate to zerobeat")); @@ -117,21 +114,18 @@ void setupFreq(){ while (btnDown()) active_delay(100); active_delay(100); - - prev_calibration = globalSettings.oscillatorCal; - globalSettings.oscillatorCal = 0; while (!btnDown()) { - knob = enc_read(); - if (knob != 0) + int knob = enc_read(); + if(knob != 0){ globalSettings.oscillatorCal += knob * 875; - /* else if (knob < 0) - calibration -= 875; */ - else + } + else{ continue; //don't update the frequency or the display - - si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the cardrier oscillator anyway, cw tx switches it off + } + + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator anyway, cw tx switches it off si5351_set_calibration(globalSettings.oscillatorCal); setFrequency(GetActiveVfoFreq()); @@ -151,24 +145,19 @@ void setupFreq(){ } void setupBFO(){ - int knob = 0; - unsigned long prevCarrier; - - prevCarrier = globalSettings.usbCarrierFreq; - displayDialog(F("Set BFO"),F("Press TUNE to Save")); - - globalSettings.usbCarrierFreq = 11053000l; + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); printCarrierFreq(globalSettings.usbCarrierFreq); while (!btnDown()){ - knob = enc_read(); - - if (knob != 0) + int knob = enc_read(); + if(knob != 0){ globalSettings.usbCarrierFreq -= 50 * knob; - else + } + else{ continue; //don't update the frequency or the display + } si5351bx_setfreq(0, globalSettings.usbCarrierFreq); setFrequency(GetActiveVfoFreq()); @@ -180,8 +169,6 @@ void setupBFO(){ SaveSettingsToEeprom(); si5351bx_setfreq(0, globalSettings.usbCarrierFreq); setFrequency(GetActiveVfoFreq()); - updateDisplay(); - setupExit(); } void setupCwDelay(){ From 9a2a25abe9cdfdec885c02031ea5dc12a69c90d2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 14 Jan 2020 22:47:53 -0800 Subject: [PATCH 042/324] Fix rendering of BFO --- setup.cpp | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/setup.cpp b/setup.cpp index 7be7b14..13cc06e 100644 --- a/setup.cpp +++ b/setup.cpp @@ -80,11 +80,27 @@ void printCarrierFreq(unsigned long freq){ ultoa(freq, b, DEC); - strncat(c, b, 2); - strcat_P(c,(const char*)F(".")); - strncat(c, &b[2], 3); - strcat_P(c,(const char*)F(".")); - strncat(c, &b[5], 1); + unsigned int characters_remaining = strlen(b); + char* destination = c; + char* source = b; + while(characters_remaining > 0){ + if(characters_remaining > 3){ + unsigned int characters_to_read = characters_remaining % 3; + if(0 == characters_to_read){ + characters_to_read = 3; + } + memcpy(destination,source,characters_to_read); + source += characters_to_read; + destination += characters_to_read; + characters_remaining -= characters_to_read; + memcpy_P(destination,(const char*)F("."),1); + destination += 1; + } + else{ + memcpy(destination,source,characters_remaining); + characters_remaining -= characters_remaining; + } + } displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); } From d62ff59c90295d387ca79cdec4d1d03fd48899d7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 14 Jan 2020 23:27:42 -0800 Subject: [PATCH 043/324] Fix frequency display for VFOs --- ubitx_ui.cpp | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 0481a56..f339fba 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -152,26 +152,27 @@ boolean getButton(btn_set_e index, Button* button){ /* * This formats the frequency given in f */ -void formatFreq(long f, char *buff) { - // tks Jack Purdum W8TEE - // replaced fsprint commmands by str commands for code size reduction +void formatFreq(uint32_t freq, char* buff, uint16_t buff_size) { + memset(buff, 0, buff_size); - memset(buff, 0, 10); - memset(b, 0, sizeof(b)); + ultoa(freq, buff, DEC); + uint8_t num_digits = strlen(buff); + const uint8_t num_spacers = (num_digits-1) / 3; + const uint8_t num_leading_digits_raw = num_digits % 3; + const uint8_t num_leading_digits = (0 == num_leading_digits_raw) ? 3 : num_leading_digits_raw; - ultoa(f, b, DEC); + if(0 == num_spacers){ + return; + } - //one mhz digit if less than 10 M, two digits if more - if (f < 10000000l){ - buff[0] = ' '; - strncat(buff, b, 4); - strcat_P(buff,(const char*)F(".")); - strncat(buff, &b[4], 2); + buff += num_leading_digits; + num_digits -= num_leading_digits; + for(int i = num_digits-1; i >= 0; --i){ + buff[i + (i/3 + 1)] = buff[i]; } - else { - strncat(buff, b, 5); - strcat_P(buff,(const char*)F(".")); - strncat(buff, &b[5], 2); + for(unsigned int i = 0; i < num_spacers; ++i){ + memcpy_P(buff,F("."),1); + buff += 4; } } @@ -248,7 +249,7 @@ void displayVFO(Vfo_e vfo){ if (VFO_A == vfo){ getButton(BUTTON_VFOA, &button); - formatFreq(globalSettings.vfoA.frequency, c+2); + formatFreq(globalSettings.vfoA.frequency, c+2, sizeof(c)-2); if (VFO_A == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; @@ -263,7 +264,7 @@ void displayVFO(Vfo_e vfo){ if (VFO_B == vfo){ getButton(BUTTON_VFOB, &button); - formatFreq(globalSettings.vfoB.frequency, c+2); + formatFreq(globalSettings.vfoB.frequency, c+2, sizeof(c)-2); if (VFO_B == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; @@ -362,7 +363,7 @@ void displayRIT(){ displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); if(globalSettings.ritOn){ strcpy_P(c,(const char*)F("TX:")); - formatFreq(globalSettings.ritFrequency, c+3); + formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-3); if (VFO_A == globalSettings.activeVfo) displayText(c, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); else From afeb056667eb32de232cd8ee3a79fa72d8facc05 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 14 Jan 2020 23:33:11 -0800 Subject: [PATCH 044/324] Move formatFreq to nano_gui so that both ubitx_ui and setup can use the single function --- nano_gui.cpp | 27 +++++++++++++++++++++++++++ nano_gui.h | 2 ++ setup.cpp | 31 +++---------------------------- ubitx_ui.cpp | 28 ---------------------------- 4 files changed, 32 insertions(+), 56 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index 938ccee..6ca1ddb 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -8,6 +8,33 @@ struct Point ts_point; +/* + * This formats the frequency given in f + */ +void formatFreq(uint32_t freq, char* buff, uint16_t buff_size) { + memset(buff, 0, buff_size); + + ultoa(freq, buff, DEC); + uint8_t num_digits = strlen(buff); + const uint8_t num_spacers = (num_digits-1) / 3; + const uint8_t num_leading_digits_raw = num_digits % 3; + const uint8_t num_leading_digits = (0 == num_leading_digits_raw) ? 3 : num_leading_digits_raw; + + if(0 == num_spacers){ + return; + } + + buff += num_leading_digits; + num_digits -= num_leading_digits; + for(int i = num_digits-1; i >= 0; --i){ + buff[i + (i/3 + 1)] = buff[i]; + } + for(unsigned int i = 0; i < num_spacers; ++i){ + memcpy_P(buff,F("."),1); + buff += 4; + } +} + void readTouchCalibration(){ LoadSettingsFromEeprom(); /* for debugging diff --git a/nano_gui.h b/nano_gui.h index efb163b..f58cf02 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -18,6 +18,8 @@ void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t void displayRawText(char *text, int x1, int y1, int color, int background); void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border); +void formatFreq(uint32_t freq, char* buff, uint16_t buff_size); + /* touch functions */ boolean readTouch(); diff --git a/setup.cpp b/setup.cpp index 13cc06e..10bace7 100644 --- a/setup.cpp +++ b/setup.cpp @@ -73,34 +73,9 @@ void displayDialog(const __FlashStringHelper* title, const __FlashStringHelper* displayText(c, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } -void printCarrierFreq(unsigned long freq){ - - memset(c, 0, sizeof(c)); - memset(b, 0, sizeof(b)); - - ultoa(freq, b, DEC); - - unsigned int characters_remaining = strlen(b); - char* destination = c; - char* source = b; - while(characters_remaining > 0){ - if(characters_remaining > 3){ - unsigned int characters_to_read = characters_remaining % 3; - if(0 == characters_to_read){ - characters_to_read = 3; - } - memcpy(destination,source,characters_to_read); - source += characters_to_read; - destination += characters_to_read; - characters_remaining -= characters_to_read; - memcpy_P(destination,(const char*)F("."),1); - destination += 1; - } - else{ - memcpy(destination,source,characters_remaining); - characters_remaining -= characters_remaining; - } - } +void printCarrierFreq(unsigned long freq) +{ + formatFreq(freq,c,sizeof(c)); displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); } diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index f339fba..5e4e52b 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -148,34 +148,6 @@ boolean getButton(btn_set_e index, Button* button){ return true; } - -/* - * This formats the frequency given in f - */ -void formatFreq(uint32_t freq, char* buff, uint16_t buff_size) { - memset(buff, 0, buff_size); - - ultoa(freq, buff, DEC); - uint8_t num_digits = strlen(buff); - const uint8_t num_spacers = (num_digits-1) / 3; - const uint8_t num_leading_digits_raw = num_digits % 3; - const uint8_t num_leading_digits = (0 == num_leading_digits_raw) ? 3 : num_leading_digits_raw; - - if(0 == num_spacers){ - return; - } - - buff += num_leading_digits; - num_digits -= num_leading_digits; - for(int i = num_digits-1; i >= 0; --i){ - buff[i + (i/3 + 1)] = buff[i]; - } - for(unsigned int i = 0; i < num_spacers; ++i){ - memcpy_P(buff,F("."),1); - buff += 4; - } -} - inline void drawCommandbar(char* text){ displayText(text, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } From 79fd056af0c5fbbd883f138641e3988bab2963da Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 14 Jan 2020 23:49:44 -0800 Subject: [PATCH 045/324] Rename oscillator variables so it's clear which is which not just from the math --- ubitx_v6.3.1_code.ino | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 2fb6ead..8871f4f 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -159,24 +159,24 @@ void setFrequency(unsigned long freq){ setTXFilters(freq); - uint32_t primary_osc_freq; - if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ - primary_osc_freq = firstIF + globalSettings.usbCarrierFreq; + uint32_t local_osc_freq; + if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ + local_osc_freq = firstIF + freq + globalSettings.cwSideToneFreq; } else{ - primary_osc_freq = firstIF - globalSettings.usbCarrierFreq; + local_osc_freq = firstIF + freq; } - uint32_t secondary_osc_freq; - if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ - secondary_osc_freq = firstIF + freq + globalSettings.cwSideToneFreq; + uint32_t ssb_osc_freq; + if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + ssb_osc_freq = firstIF + globalSettings.usbCarrierFreq; } else{ - secondary_osc_freq = firstIF + freq; + ssb_osc_freq = firstIF - globalSettings.usbCarrierFreq; } - si5351bx_setfreq(2, secondary_osc_freq); - si5351bx_setfreq(1, primary_osc_freq); + si5351bx_setfreq(2, local_osc_freq); + si5351bx_setfreq(1, ssb_osc_freq); SetActiveVfoFreq(freq); } From c17136279e581209693107c01070dab090476414 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Thu, 16 Jan 2020 23:36:58 -0800 Subject: [PATCH 046/324] Fix .,? morse encodings, and use correct letter spacing based on settings, not hard coded --- morse.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/morse.cpp b/morse.cpp index 4d7b8d4..2afaeaa 100644 --- a/morse.cpp +++ b/morse.cpp @@ -2,18 +2,18 @@ #include "ubitx.h" #include "settings.h" #include "morse.h" -/* - * Each byte of the morse table stores one letter. - * The 0 is a dot, a 1 is a dash - * From the Most significant byte onwards, the letter is padded with 1s. - * The first zero after the 1s indicates the start of the letter, it MUST be discarded - */ struct Morse { char letter; unsigned char code; }; +/* + * Each byte of the morse table stores one letter. + * The 0 is a dot, a 1 is a dash + * From the Most significant byte onwards, the letter is padded with 1s. + * The first zero after the 1s indicates the start of the letter, it MUST be discarded + */ static const PROGMEM struct Morse morse_table[] = { {'a', 0xf9}, // 11111001 {'b', 0xe8}, // 11101000 @@ -51,9 +51,9 @@ static const PROGMEM struct Morse morse_table[] = { {'8', 0xdc}, // 11011100 {'9', 0xde}, // 11011110 {'0', 0xdf}, // 11011111 -{'.', 0xd5}, // 11010101 -{',', 0xd3}, // 11010011 //AD7U 20191217 -{'?', 0xcc}, // 11001100 //AD7U 20191217 - Added +{'.', 0x95}, // 10010101 +{',', 0xb3}, // 10110011 +{'?', 0x8c}, // 10001100 }; static void morseLetter(char c){ @@ -62,7 +62,7 @@ static void morseLetter(char c){ //handle space character as three dashes if (c == ' '){ active_delay(9 * globalSettings.cwDitDurationMs); - Serial.print(' '); + //Serial.print(' '); return; } @@ -94,7 +94,8 @@ static void morseLetter(char c){ mask = mask >> 1; } //Serial.println('@'); - delay(200); // space between letters is a dash (3 dots), one dot's space has already been sent + delay(2*globalSettings.cwDitDurationMs); // space between letters is a dash (3 dots), one dot's space has already been sent + break;//We've played the letter, so don't bother checking the rest of the list } } } @@ -107,7 +108,7 @@ void morseText(char *text){ delay(1000); // } - Serial.println(globalSettings.cwSideToneFreq); + //Serial.println(globalSettings.cwSideToneFreq); while(*text){ morseLetter(*text++); } From 692c862b6eb8c6eab746f7616389d43038745ba1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 00:16:31 -0800 Subject: [PATCH 047/324] Load actual setting, not just the defaulted 0 --- ubitx_si5351.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ubitx_si5351.cpp b/ubitx_si5351.cpp index 3d378ab..8e900e0 100644 --- a/ubitx_si5351.cpp +++ b/ubitx_si5351.cpp @@ -49,7 +49,6 @@ uint32_t si5351bx_vcoa = (SI5351BX_XTAL*SI5351BX_MSA); // 25mhzXtal calibrate uint8_t si5351bx_rdiv = 0; // 0-7, CLK pin sees fout/(2**rdiv) uint8_t si5351bx_drive[3] = {3, 3, 3}; // 0=2ma 1=4ma 2=6ma 3=8ma for CLK 0,1,2 uint8_t si5351bx_clken = 0xFF; // Private, all CLK output drivers off -int32_t calibration = 0; void i2cWrite(uint8_t reg, uint8_t val) { // write reg via i2c Wire.beginTransmission(SI5351BX_ADDR); @@ -122,8 +121,7 @@ void si5351_set_calibration(int32_t cal){ void initOscillators(){ //initialize the SI5351 si5351bx_init(); - si5351bx_vcoa = (SI5351BX_XTAL * SI5351BX_MSA) + calibration; // apply the calibration correction factor - si5351bx_setfreq(0, globalSettings.usbCarrierFreq); + si5351_set_calibration(globalSettings.oscillatorCal); } From 6fe6185b1953e3d24a94b58f2bc679e429e32ae7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 18:53:18 -0800 Subject: [PATCH 048/324] Remove unused extern --- setup.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/setup.cpp b/setup.cpp index 10bace7..fefd615 100644 --- a/setup.cpp +++ b/setup.cpp @@ -22,9 +22,6 @@ void setupExit(){ menuOn = 0; } - //this is used by the si5351 routines in the ubitx_5351 file -extern uint32_t si5351bx_vcoa; - static const unsigned int COLOR_TEXT = DISPLAY_WHITE; static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK; static const unsigned int COLOR_TITLE_BACKGROUND = DISPLAY_NAVY; From f0e06401150a2d5609e15eb4445ec3b7718ee01b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 19:05:16 -0800 Subject: [PATCH 049/324] Swap tone button for menu button for faster dev --- ubitx_ui.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 5e4e52b..14f8536 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -66,7 +66,7 @@ enum btn_set_e { BUTTON_15, BUTTON_10, BUTTON_WPM, - BUTTON_TON, + BUTTON_MNU, BUTTON_FRQ, BUTTON_TOTAL }; @@ -85,7 +85,7 @@ constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = { {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R'}, {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U'}, {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L'}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'M'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C'}, {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S'}, {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8'}, @@ -97,7 +97,7 @@ constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = { {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5'}, {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1'}, {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_WPM, "WPM", 'W'}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_TON, "TON", 'T'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "MNU", 'M'}, {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F'}, }; @@ -962,9 +962,9 @@ void doCommand(Button* button){ setCwSpeed(); break; } - case BUTTON_TON: + case BUTTON_MNU: { - setCwTone(); + doSetup2(); break; } default: From ebaf7c44de4e3476f962c3b50d3d0cc4bb338cc0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 21:41:52 -0800 Subject: [PATCH 050/324] Do most of the refactoring required to make menus easy to expand --- setup.cpp | 184 ++++++++++++++++++++++++++---------------------------- 1 file changed, 88 insertions(+), 96 deletions(-) diff --git a/setup.cpp b/setup.cpp index fefd615..097feb0 100644 --- a/setup.cpp +++ b/setup.cpp @@ -18,10 +18,6 @@ * - If the menu item is NOT clicked on, then the menu's prompt is to be displayed */ -void setupExit(){ - menuOn = 0; -} - static const unsigned int COLOR_TEXT = DISPLAY_WHITE; static const unsigned int COLOR_BACKGROUND = DISPLAY_BLACK; static const unsigned int COLOR_TITLE_BACKGROUND = DISPLAY_NAVY; @@ -190,7 +186,6 @@ void setupCwDelay(){ SaveSettingsToEeprom(); active_delay(500); - setupExit(); } void setupKeyer(){ @@ -243,89 +238,108 @@ void setupKeyer(){ globalSettings.keyerMode = tmp_mode; SaveSettingsToEeprom(); - - setupExit(); } +struct MenuItem_t { + const char* const ItemName; + const void (*OnSelect)(); +}; + +void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); +#define RUN_MENU(menu) runMenu(menu,sizeof(menu)/sizeof(menu[0])) + +const char MT_CAL [] PROGMEM = "Calibrations"; const char MI_SET_FREQ [] PROGMEM = "Set Freq..."; const char MI_SET_BFO [] PROGMEM = "Set BFO..."; -const char MI_CW_DELAY [] PROGMEM = "CW Delay..."; -const char MI_CW_KEYER [] PROGMEM = "CW Keyer..."; const char MI_TOUCH [] PROGMEM = "Touch Screen..."; -const char MI_EXIT [] PROGMEM = "Exit"; +const MenuItem_t calibrationMenu [] PROGMEM { + {MT_CAL,nullptr},//Title + {MI_SET_FREQ,setupFreq}, + {MI_SET_BFO,setupBFO}, + {MI_TOUCH,setupTouch}, +}; +void runCalibrationMenu(){RUN_MENU(calibrationMenu);} -enum MenuIds { - MENU_SET_FREQ, - MENU_SET_BFO, - MENU_CW_DELAY, - MENU_CW_KEYER, - MENU_TOUCH, - MENU_EXIT, - MENU_TOTAL +const char MT_CW [] PROGMEM = "CW/Morse Setup"; +const char MI_CW_DELAY [] PROGMEM = "CW Delay..."; +const char MI_CW_KEYER [] PROGMEM = "CW Keyer..."; +const MenuItem_t cwMenu [] PROGMEM { + {MT_CW,nullptr},//Title + {MI_CW_DELAY,setupCwDelay}, + {MI_CW_KEYER,setupKeyer}, }; +void runCwMenu(){RUN_MENU(cwMenu);} -const char* const menuItems [MENU_TOTAL] PROGMEM { - MI_SET_FREQ, - MI_SET_BFO, - MI_CW_DELAY, - MI_CW_KEYER, - MI_TOUCH, - MI_EXIT +const char MT_SETTINGS [] PROGMEM = "Settings"; +const MenuItem_t mainMenu [] PROGMEM { + {MT_SETTINGS,nullptr},//Title + {MT_CAL,runCalibrationMenu}, + {MT_CW,runCwMenu}, }; -void drawSetupMenu(){ +const char MI_EXIT [] PROGMEM = "Exit"; +const MenuItem_t exitMenu PROGMEM = {MI_EXIT,nullptr}; + +void drawMenu(const MenuItem_t* const items, const uint16_t num_items) +{ displayClear(COLOR_BACKGROUND); - strcpy_P(b,(const char*)F("Setup")); + MenuItem_t mi = {"",nullptr}; + memcpy_P(&mi,&items[0],sizeof(mi)); + strcpy_P(b,mi.ItemName); displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); - for(unsigned int i = 0; i < MENU_TOTAL; ++i){ - strcpy_P(b,(const char*)pgm_read_word(&(menuItems[i]))); - displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + i*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); + for(unsigned int i = 1; i < num_items; ++i){ + memcpy_P(&mi,&items[i],sizeof(mi)); + strcpy_P(b,mi.ItemName); + displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); } + memcpy_P(&mi,&exitMenu,sizeof(mi)); + strcpy_P(b,mi.ItemName); + displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (num_items-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); } -void movePuck(int i){ - static int prevPuck = 1;//Start value at 1 so that on init, when we get called with 0, we'll update - +void movePuck(unsigned int old_index, unsigned int new_index) +{ //Don't update if we're already on the right selection - if(prevPuck == i){ + if(old_index == new_index){ return; } - - //Clear old - displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (prevPuck*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_INACTIVE_BORDER); + else if(((unsigned int)-1) != old_index){ + //Clear old + displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (old_index*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_INACTIVE_BORDER); + } //Draw new - displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_ACTIVE_BORDER); - prevPuck = i; - + displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (new_index*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_ACTIVE_BORDER); } -void doSetup2(){ +void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items) +{ static const unsigned int COUNTS_PER_ITEM = 10; - int select=0, i, btnState; + const unsigned int MAX_KNOB_VALUE = num_items*COUNTS_PER_ITEM - 1; + int knob_sum = 0; + unsigned int old_index = 0; - drawSetupMenu(); - movePuck(select); + drawMenu(menu_items,num_items); + movePuck(1,0);//Force draw of puck //wait for the button to be raised up - while(btnDown()) + while(btnDown()){ active_delay(50); + } active_delay(50); //debounce - - menuOn = 2; - while (menuOn){ - i = enc_read(); - - if (i > 0){ - if (select + i < MENU_TOTAL*COUNTS_PER_ITEM) - select += i; - movePuck(select/COUNTS_PER_ITEM); + while (true){ + knob_sum += enc_read(); + if(knob_sum < 0){ + knob_sum = 0; } - if (i < 0 && select + i >= 0){ - select += i; //caught ya, i is already -ve here, so you add it - movePuck(select/COUNTS_PER_ITEM); + else if(MAX_KNOB_VALUE < knob_sum){ + knob_sum = MAX_KNOB_VALUE; } + uint16_t index = knob_sum/COUNTS_PER_ITEM; + movePuck(old_index,index); + old_index = index; + if (!btnDown()){ active_delay(50); continue; @@ -335,50 +349,28 @@ void doSetup2(){ while(btnDown()){ active_delay(50); } - active_delay(300); + active_delay(50);//debounce - switch(select/COUNTS_PER_ITEM){ - case MENU_SET_FREQ: - { - setupFreq(); - break; - } - case MENU_SET_BFO: - { - setupBFO(); - break; - } - case MENU_CW_DELAY: - { - setupCwDelay(); - break; - } - case MENU_CW_KEYER: - { - setupKeyer(); - break; - } - case MENU_TOUCH: - { - setupTouch(); - break; - } - case MENU_EXIT: - default: - { - menuOn = 0; - break; - } - }//switch - //redraw - drawSetupMenu(); + if(num_items-1 > index){ + MenuItem_t mi = {"",nullptr}; + memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 + mi.OnSelect(); + drawMenu(menu_items,num_items);//Need to re-render, since whatever ran just now is assumed to have drawn something + old_index = -1;//Force redraw + } + else{ + break; + } } //debounce the button - while(btnDown()) + while(btnDown()){ active_delay(50); - active_delay(50); + } + active_delay(50);//debounce +} - checkCAT(); +void doSetup2(){ + RUN_MENU(mainMenu); guiUpdate(); } From e0bc5999c8bd9e73cca19ac52aa6d5c9e1716e2d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 22:22:06 -0800 Subject: [PATCH 051/324] De-duplicate keyer strings --- setup.cpp | 39 ++++++++++++++++----------------------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/setup.cpp b/setup.cpp index 097feb0..c1e1208 100644 --- a/setup.cpp +++ b/setup.cpp @@ -188,24 +188,27 @@ void setupCwDelay(){ active_delay(500); } -void setupKeyer(){ - displayDialog(F("Set CW Keyer"),F("Press tune to Save")); - - if(KeyerMode_e::KEYER_STRAIGHT == globalSettings.keyerMode){ - strcpy_P(c,(const char*)F("< Hand Key >")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); +void formatKeyerEnum(char* output, const KeyerMode_e mode) +{ + if(KeyerMode_e::KEYER_STRAIGHT == mode){ + strcpy_P(output,(const char*)F("< Hand Key >")); } - else if(KeyerMode_e::KEYER_IAMBIC_A == globalSettings.keyerMode){ - strcpy_P(c,(const char*)F("< Iambic A >")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + else if(KeyerMode_e::KEYER_IAMBIC_A == mode){ + strcpy_P(output,(const char*)F("< Iambic A >")); } else{ - strcpy_P(c,(const char*)F("< Iambic B >")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + strcpy_P(output,(const char*)F("< Iambic B >")); } +} + +void setupKeyer(){ + displayDialog(F("Set CW Keyer"),F("Press tune to Save")); int knob = 0; uint32_t tmp_mode = globalSettings.keyerMode; + formatKeyerEnum(c, tmp_mode); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + while (!btnDown()) { knob = enc_read(); @@ -220,18 +223,8 @@ void setupKeyer(){ tmp_mode++; } - if (KeyerMode_e::KEYER_STRAIGHT == tmp_mode){ - strcpy_P(c,(const char*)F("< Hand Key >")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - } - else if(KeyerMode_e::KEYER_IAMBIC_A == tmp_mode){ - strcpy_P(c,(const char*)F("< Iambic A >")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - } - else if (KeyerMode_e::KEYER_IAMBIC_B == tmp_mode){ - strcpy_P(c,(const char*)F("< Iambic B >")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - } + formatKeyerEnum(c,tmp_mode); + displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); } active_delay(500); From b100da145ecac69476a435bf020746b81ae04f3c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 22:27:12 -0800 Subject: [PATCH 052/324] Rename some of the menu items --- setup.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/setup.cpp b/setup.cpp index c1e1208..145edf7 100644 --- a/setup.cpp +++ b/setup.cpp @@ -242,9 +242,9 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); #define RUN_MENU(menu) runMenu(menu,sizeof(menu)/sizeof(menu[0])) const char MT_CAL [] PROGMEM = "Calibrations"; -const char MI_SET_FREQ [] PROGMEM = "Set Freq..."; -const char MI_SET_BFO [] PROGMEM = "Set BFO..."; -const char MI_TOUCH [] PROGMEM = "Touch Screen..."; +const char MI_SET_FREQ [] PROGMEM = "Local Osc Frequency"; +const char MI_SET_BFO [] PROGMEM = "Beat Osc Frequency"; +const char MI_TOUCH [] PROGMEM = "Touch Screen"; const MenuItem_t calibrationMenu [] PROGMEM { {MT_CAL,nullptr},//Title {MI_SET_FREQ,setupFreq}, @@ -254,8 +254,8 @@ const MenuItem_t calibrationMenu [] PROGMEM { void runCalibrationMenu(){RUN_MENU(calibrationMenu);} const char MT_CW [] PROGMEM = "CW/Morse Setup"; -const char MI_CW_DELAY [] PROGMEM = "CW Delay..."; -const char MI_CW_KEYER [] PROGMEM = "CW Keyer..."; +const char MI_CW_DELAY [] PROGMEM = "Tx/Rx Switching Delay"; +const char MI_CW_KEYER [] PROGMEM = "Keyer Type"; const MenuItem_t cwMenu [] PROGMEM { {MT_CW,nullptr},//Title {MI_CW_DELAY,setupCwDelay}, From bc83bcd5d185f3c7d88f9e37c0d8be986ee40ede Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 22:57:41 -0800 Subject: [PATCH 053/324] Move CW WPM and Hz to setup menu --- setup.cpp | 63 ++++++++++++++++++++++++++++++++++++++++++++---- ubitx_ui.cpp | 68 ++-------------------------------------------------- 2 files changed, 61 insertions(+), 70 deletions(-) diff --git a/setup.cpp b/setup.cpp index 145edf7..97d6f5f 100644 --- a/setup.cpp +++ b/setup.cpp @@ -161,7 +161,6 @@ void setupCwDelay(){ displayDialog(F("Set CW T/R Delay"),F("Press tune to Save")); - active_delay(500); prev_cw_delay = globalSettings.cwActiveTimeoutMs; ltoa(globalSettings.cwActiveTimeoutMs, b, 10); @@ -185,7 +184,6 @@ void setupCwDelay(){ } SaveSettingsToEeprom(); - active_delay(500); } void formatKeyerEnum(char* output, const KeyerMode_e mode) @@ -233,6 +231,59 @@ void setupKeyer(){ SaveSettingsToEeprom(); } +void setupCwSpeed() +{ + displayDialog(F("Set CW Speed (WPM)"),F("Press tune to Save")); + + unsigned int wpm = 1200/globalSettings.cwDitDurationMs; + + itoa(wpm, b, 10); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + + while (!btnDown()){ + int knob = enc_read(); + + if (knob < 0 && wpm > 1) + --wpm; + else if (knob > 0 && wpm < 100) + ++wpm; + else + continue;//don't update the frequency or the display + + itoa(wpm, b, 10); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } + + globalSettings.cwDitDurationMs = 1200/wpm; + SaveSettingsToEeprom(); +} + +void setupCwTone(){ + displayDialog(F("Set CW Tone (Hz)"),F("Press tune to Save")); + + tone(CW_TONE, globalSettings.cwSideToneFreq); + itoa(globalSettings.cwSideToneFreq, b, 10); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + + while(!btnDown()){ + int knob = enc_read(); + + if (knob > 0 && globalSettings.cwSideToneFreq < 2000) + globalSettings.cwSideToneFreq += 10; + else if (knob < 0 && globalSettings.cwSideToneFreq > 100 ) + globalSettings.cwSideToneFreq -= 10; + else + continue; //don't update the frequency or the display + + tone(CW_TONE, globalSettings.cwSideToneFreq); + itoa(globalSettings.cwSideToneFreq, b, 10); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } + noTone(CW_TONE); + + SaveSettingsToEeprom(); +} + struct MenuItem_t { const char* const ItemName; const void (*OnSelect)(); @@ -242,8 +293,8 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); #define RUN_MENU(menu) runMenu(menu,sizeof(menu)/sizeof(menu[0])) const char MT_CAL [] PROGMEM = "Calibrations"; -const char MI_SET_FREQ [] PROGMEM = "Local Osc Frequency"; -const char MI_SET_BFO [] PROGMEM = "Beat Osc Frequency"; +const char MI_SET_FREQ [] PROGMEM = "Local Oscillator"; +const char MI_SET_BFO [] PROGMEM = "Beat Frequency Osc (BFO)"; const char MI_TOUCH [] PROGMEM = "Touch Screen"; const MenuItem_t calibrationMenu [] PROGMEM { {MT_CAL,nullptr},//Title @@ -254,10 +305,14 @@ const MenuItem_t calibrationMenu [] PROGMEM { void runCalibrationMenu(){RUN_MENU(calibrationMenu);} const char MT_CW [] PROGMEM = "CW/Morse Setup"; +const char MI_CW_SPEED [] PROGMEM = "Play Speed (WPM)"; +const char MI_CW_TONE [] PROGMEM = "Tone Frequency"; const char MI_CW_DELAY [] PROGMEM = "Tx/Rx Switching Delay"; const char MI_CW_KEYER [] PROGMEM = "Keyer Type"; const MenuItem_t cwMenu [] PROGMEM { {MT_CW,nullptr},//Title + {MI_CW_SPEED,setupCwSpeed}, + {MI_CW_TONE,setupCwTone}, {MI_CW_DELAY,setupCwDelay}, {MI_CW_KEYER,setupKeyer}, }; diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 14f8536..8457f11 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -65,7 +65,7 @@ enum btn_set_e { BUTTON_17, BUTTON_15, BUTTON_10, - BUTTON_WPM, + BUTTON_BLANK_1, BUTTON_MNU, BUTTON_FRQ, BUTTON_TOTAL @@ -96,7 +96,7 @@ constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = { {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5'}, {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1'}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_WPM, "WPM", 'W'}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0'}, {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "MNU", 'M'}, {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F'}, }; @@ -808,65 +808,6 @@ void switchBand(uint32_t bandfreq){ saveVFOs(); } -void setCwSpeed() -{ - int wpm = 1200/globalSettings.cwDitDurationMs; - - wpm = getValueByKnob(1, 100, 1, wpm,F("CW: "),F(" WPM")); - - globalSettings.cwDitDurationMs = 1200/wpm; - SaveSettingsToEeprom(); - active_delay(500); - drawStatusbar(); - //printLine2(""); - //updateDisplay(); -} - -void setCwTone(){ - int knob = 0; - int prev_sideTone; - - tone(CW_TONE, globalSettings.cwSideToneFreq); - itoa(globalSettings.cwSideToneFreq, c, 10); - strcpy_P(b,(const char*)F("CW Tone: ")); - strcat(b, c); - strcat_P(b,(const char*)F(" Hz")); - drawCommandbar(b); - - //disable all clock 1 and clock 2 - while (digitalRead(PTT) == HIGH && !btnDown()) - { - knob = enc_read(); - - if (knob > 0 && globalSettings.cwSideToneFreq < 2000) - globalSettings.cwSideToneFreq += 10; - else if (knob < 0 && globalSettings.cwSideToneFreq > 100 ) - globalSettings.cwSideToneFreq -= 10; - else - continue; //don't update the frequency or the display - - tone(CW_TONE, globalSettings.cwSideToneFreq); - itoa(globalSettings.cwSideToneFreq, c, 10); - strcpy_P(b,(const char*)F("CW Tone: ")); - strcat(b, c); - strcat_P(b,(const char*)F(" Hz")); - drawCommandbar(b); - //printLine2(b); - - checkCAT(); - active_delay(20); - } - noTone(CW_TONE); - - SaveSettingsToEeprom(); - - b[0] = 0; - drawCommandbar(b); - drawStatusbar(); - //printLine2(""); - //updateDisplay(); -} - void doCommand(Button* button){ //Serial.print(F("Doing command: ")); //Serial.print(button->text); @@ -957,11 +898,6 @@ void doCommand(Button* button){ enterFreq(); break; } - case BUTTON_WPM: - { - setCwSpeed(); - break; - } case BUTTON_MNU: { doSetup2(); From e1d0ee1c4343defb37e8a943d5d6cd162e75de1e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 23:10:38 -0800 Subject: [PATCH 054/324] If button is down, load defaults and go from there --- ubitx_v6.3.1_code.ino | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 8871f4f..0d18816 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -473,12 +473,13 @@ void setup() //Run initial calibration routine if button is pressed during power up if(btnDown()){ + LoadDefaultSettings(); setupTouch(); SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); - setFrequency(10000000l); + setFrequency(10000000L); setupFreq(); SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - setFrequency(7100000l); + setFrequency(7100000L); setupBFO(); } From 897b5c5de55f60c68251a854b3b58cafa511e597 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 23:10:53 -0800 Subject: [PATCH 055/324] Add reset option --- setup.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/setup.cpp b/setup.cpp index 97d6f5f..037d926 100644 --- a/setup.cpp +++ b/setup.cpp @@ -284,6 +284,17 @@ void setupCwTone(){ SaveSettingsToEeprom(); } +void setupResetAll() +{ + LoadDefaultSettings(); + SaveSettingsToEeprom(); + while(btnDown()){ + active_delay(50); + } + active_delay(50); + setup(); +} + struct MenuItem_t { const char* const ItemName; const void (*OnSelect)(); @@ -319,10 +330,12 @@ const MenuItem_t cwMenu [] PROGMEM { void runCwMenu(){RUN_MENU(cwMenu);} const char MT_SETTINGS [] PROGMEM = "Settings"; +const char MI_RESET [] PROGMEM = "Reset all Cals/Settings"; const MenuItem_t mainMenu [] PROGMEM { {MT_SETTINGS,nullptr},//Title {MT_CAL,runCalibrationMenu}, {MT_CW,runCwMenu}, + {MI_RESET,setupResetAll}, }; const char MI_EXIT [] PROGMEM = "Exit"; From f79ca7c693623966434ccf4339cb6221cce00ad1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 17 Jan 2020 23:23:56 -0800 Subject: [PATCH 056/324] Give a reset dialog so it can't be a single mistake to reset --- setup.cpp | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/setup.cpp b/setup.cpp index 037d926..12e7afd 100644 --- a/setup.cpp +++ b/setup.cpp @@ -286,13 +286,44 @@ void setupCwTone(){ void setupResetAll() { - LoadDefaultSettings(); - SaveSettingsToEeprom(); + displayDialog(F("Reset all cals and settings?"),F("Press tune to Confirm")); + strcpy_P(b,(const char*)F("No")); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + + bool reset_all = false; + while(!btnDown()){ + int knob = enc_read(); + + if(knob > 0){ + reset_all = true; + } + else if(knob < 0){ + reset_all = false; + } + else{ + continue; + } + + if(reset_all){ + strcpy_P(b,(const char*)F("Yes")); + } + else{ + strcpy_P(b,(const char*)F("No")); + } + + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + } + while(btnDown()){ active_delay(50); } active_delay(50); - setup(); + + if(reset_all){ + LoadDefaultSettings(); + SaveSettingsToEeprom(); + setup(); + } } struct MenuItem_t { From 8212ecf1e9f1286d474548b8a49046354c80d09a Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 18 Jan 2020 23:34:41 -0800 Subject: [PATCH 057/324] Proof of concept generic setting menu for cw tone --- setup.cpp | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 87 insertions(+), 1 deletion(-) diff --git a/setup.cpp b/setup.cpp index 12e7afd..158b0c7 100644 --- a/setup.cpp +++ b/setup.cpp @@ -66,6 +66,92 @@ void displayDialog(const __FlashStringHelper* title, const __FlashStringHelper* displayText(c, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } +struct SettingScreen_t { + const char* const Title; + const char* const AdditionalText; + const uint16_t KnobDivider; + const uint16_t StepSize; + void (*Initialize)(long int* start_value_out); + void (*Validate)(const long int candidate_value_in, long int* validated_value_out); + void (*OnValueChange)(const long int new_value, char* buff_out, const size_t buff_out_size); + void (*Finalize)(const long int final_value); +}; + +#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) +const char SS_EMPTY [] PROGMEM = ""; +const char SS_CW_TONE [] PROGMEM = "Set CW Tone (Hz)"; +const SettingScreen_t SettingCwTone = { + SS_CW_TONE, + SS_EMPTY, + 1, + 10, + [](long int* svo){*svo = globalSettings.cwSideToneFreq;}, + [](const long int cvi, long int* vvo){*vvo = LIMIT(cvi,100,2000);}, + [](const long int nv, char* buf, const size_t buf_size){ + globalSettings.cwSideToneFreq = nv; + tone(CW_TONE, globalSettings.cwSideToneFreq); + ltoa(globalSettings.cwSideToneFreq,buf,10); + }, + [](const long int fv){ + noTone(CW_TONE); + globalSettings.cwSideToneFreq = fv; + SaveSettingsToEeprom(); + } +}; +void runSetting(const SettingScreen_t* const screen); +void runToneSetting(){runSetting(&SettingCwTone);} + +void runSetting(const SettingScreen_t* const screen) +{ + displayDialog(reinterpret_cast(screen->Title),F("Push Tune to Save")); + + //Wait for button to stop being pressed + while(btnDown()){ + active_delay(10); + } + active_delay(10); + + long int raw_value = 0; + long int last_value = 0; + + screen->Initialize(&last_value); + screen->OnValueChange(last_value,b,sizeof(b)); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); + + raw_value = last_value * screen->KnobDivider; + + while (!btnDown()) + { + int knob = enc_read(); + if(knob != 0){ + raw_value += knob * (int32_t)screen->StepSize; + } + else{ + continue; + } + + const long int candidate_value = raw_value / (int32_t)screen->KnobDivider; + long int value = 0; + screen->Validate(candidate_value,&value); + + //If we're going out of bounds, prevent the raw value from going too far out + if(candidate_value != value){ + raw_value = value * (int32_t)screen->KnobDivider; + } + + if(value == last_value){ + continue; + } + else{ + screen->OnValueChange(value,b,sizeof(b)); + displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); + last_value = value; + } + } + + screen->Finalize(last_value); +} + void printCarrierFreq(unsigned long freq) { formatFreq(freq,c,sizeof(c)); @@ -354,7 +440,7 @@ const char MI_CW_KEYER [] PROGMEM = "Keyer Type"; const MenuItem_t cwMenu [] PROGMEM { {MT_CW,nullptr},//Title {MI_CW_SPEED,setupCwSpeed}, - {MI_CW_TONE,setupCwTone}, + {MI_CW_TONE,runToneSetting}, {MI_CW_DELAY,setupCwDelay}, {MI_CW_KEYER,setupKeyer}, }; From 03fd8463eb8ef37216a4f01deea1e77941809d12 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 10:48:07 -0800 Subject: [PATCH 058/324] Switch to named functions instead of lambdas, because apparently PROGMEM doesn't like lambdas --- setup.cpp | 64 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/setup.cpp b/setup.cpp index 158b0c7..f09724f 100644 --- a/setup.cpp +++ b/setup.cpp @@ -78,32 +78,46 @@ struct SettingScreen_t { }; #define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) +ssCwToneInitialize(long int* start_value_out) +{ + *start_value_out = globalSettings.cwSideToneFreq; +} +ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,100,2000); +} +ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + globalSettings.cwSideToneFreq = new_value; + tone(CW_TONE, globalSettings.cwSideToneFreq); + ltoa(globalSettings.cwSideToneFreq,buff_out,10); +} +ssCwToneFinalize(const long int final_value) +{ + noTone(CW_TONE); + globalSettings.cwSideToneFreq = final_value; + SaveSettingsToEeprom(); +} const char SS_EMPTY [] PROGMEM = ""; const char SS_CW_TONE [] PROGMEM = "Set CW Tone (Hz)"; -const SettingScreen_t SettingCwTone = { +const SettingScreen_t settingScreens [] PROGMEM = { SS_CW_TONE, SS_EMPTY, 1, 10, - [](long int* svo){*svo = globalSettings.cwSideToneFreq;}, - [](const long int cvi, long int* vvo){*vvo = LIMIT(cvi,100,2000);}, - [](const long int nv, char* buf, const size_t buf_size){ - globalSettings.cwSideToneFreq = nv; - tone(CW_TONE, globalSettings.cwSideToneFreq); - ltoa(globalSettings.cwSideToneFreq,buf,10); - }, - [](const long int fv){ - noTone(CW_TONE); - globalSettings.cwSideToneFreq = fv; - SaveSettingsToEeprom(); - } + ssCwToneInitialize, + ssCwToneValidate, + ssCwToneChange, + ssCwToneFinalize }; void runSetting(const SettingScreen_t* const screen); -void runToneSetting(){runSetting(&SettingCwTone);} +void runToneSetting(){runSetting(&settingScreens[0]);} -void runSetting(const SettingScreen_t* const screen) +void runSetting(const SettingScreen_t* const p_screen) { - displayDialog(reinterpret_cast(screen->Title),F("Push Tune to Save")); + SettingScreen_t screen = {0}; + memcpy_P(&screen,p_screen,sizeof(screen)); + displayDialog(reinterpret_cast(screen.Title),F("Push Tune to Save")); //Wait for button to stop being pressed while(btnDown()){ @@ -114,42 +128,42 @@ void runSetting(const SettingScreen_t* const screen) long int raw_value = 0; long int last_value = 0; - screen->Initialize(&last_value); - screen->OnValueChange(last_value,b,sizeof(b)); + screen.Initialize(&last_value); + screen.OnValueChange(last_value,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); - raw_value = last_value * screen->KnobDivider; + raw_value = last_value * screen.KnobDivider; while (!btnDown()) { int knob = enc_read(); if(knob != 0){ - raw_value += knob * (int32_t)screen->StepSize; + raw_value += knob * (int32_t)screen.StepSize; } else{ continue; } - const long int candidate_value = raw_value / (int32_t)screen->KnobDivider; + const long int candidate_value = raw_value / (int32_t)screen.KnobDivider; long int value = 0; - screen->Validate(candidate_value,&value); + screen.Validate(candidate_value,&value); //If we're going out of bounds, prevent the raw value from going too far out if(candidate_value != value){ - raw_value = value * (int32_t)screen->KnobDivider; + raw_value = value * (int32_t)screen.KnobDivider; } if(value == last_value){ continue; } else{ - screen->OnValueChange(value,b,sizeof(b)); + screen.OnValueChange(value,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); last_value = value; } } - screen->Finalize(last_value); + screen.Finalize(last_value); } void printCarrierFreq(unsigned long freq) From e65f4d57a4e8c54c7c126f96c47da779c0a07df8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 12:56:14 -0800 Subject: [PATCH 059/324] Implement the instructions text --- setup.cpp | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/setup.cpp b/setup.cpp index f09724f..953a0dd 100644 --- a/setup.cpp +++ b/setup.cpp @@ -51,19 +51,27 @@ static const unsigned int LAYOUT_SETTING_VALUE_Y = LAYOUT_ITEM_Y + 3*LAYOUT_ITEM static const unsigned int LAYOUT_SETTING_VALUE_WIDTH = LAYOUT_ITEM_WIDTH; static const unsigned int LAYOUT_SETTING_VALUE_HEIGHT = LAYOUT_ITEM_HEIGHT; -static const unsigned int LAYOUT_INSTRUCTION_TEXT_X = 20; -static const unsigned int LAYOUT_INSTRUCTION_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_ITEM_PITCH_Y; -static const unsigned int LAYOUT_INSTRUCTION_TEXT_WIDTH = LAYOUT_ITEM_WIDTH; -static const unsigned int LAYOUT_INSTRUCTION_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT; - -void displayDialog(const __FlashStringHelper* title, const __FlashStringHelper* instructions){ - strcpy_P(b,(const char*)title); - strcpy_P(c,(const char*)instructions); +static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_X = 20; +static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_Y = LAYOUT_ITEM_Y; +static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_WIDTH = LAYOUT_ITEM_WIDTH; +static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_HEIGHT = LAYOUT_SETTING_VALUE_Y - LAYOUT_ITEM_Y - 1; + +static const unsigned int LAYOUT_CONFIRM_TEXT_X = 20; +static const unsigned int LAYOUT_CONFIRM_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_ITEM_PITCH_Y; +static const unsigned int LAYOUT_CONFIRM_TEXT_WIDTH = LAYOUT_ITEM_WIDTH; +static const unsigned int LAYOUT_CONFIRM_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT; + +void displayDialog(const char* title, + const char* instructions){ displayClear(COLOR_BACKGROUND); displayRect(LAYOUT_OUTER_BORDER_X,LAYOUT_OUTER_BORDER_Y,LAYOUT_OUTER_BORDER_WIDTH,LAYOUT_OUTER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); displayRect(LAYOUT_INNER_BORDER_X,LAYOUT_INNER_BORDER_Y,LAYOUT_INNER_BORDER_WIDTH,LAYOUT_INNER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); + strcpy_P(b,title); displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); - displayText(c, LAYOUT_INSTRUCTION_TEXT_X, LAYOUT_INSTRUCTION_TEXT_Y, LAYOUT_INSTRUCTION_TEXT_WIDTH, LAYOUT_INSTRUCTION_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + strcpy_P(b,instructions); + displayText(b, LAYOUT_INSTRUCTIONS_TEXT_X, LAYOUT_INSTRUCTIONS_TEXT_Y, LAYOUT_INSTRUCTIONS_TEXT_WIDTH, LAYOUT_INSTRUCTIONS_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + strcpy_P(b,(const char*)F("Push Tune to Save")); + displayText(b, LAYOUT_CONFIRM_TEXT_X, LAYOUT_CONFIRM_TEXT_Y, LAYOUT_CONFIRM_TEXT_WIDTH, LAYOUT_CONFIRM_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } struct SettingScreen_t { @@ -100,9 +108,10 @@ ssCwToneFinalize(const long int final_value) } const char SS_EMPTY [] PROGMEM = ""; const char SS_CW_TONE [] PROGMEM = "Set CW Tone (Hz)"; +const char SS_LONG_TEXT [] PROGMEM = "This is a long string of text that should be wrapped at least once, possibly more."; const SettingScreen_t settingScreens [] PROGMEM = { SS_CW_TONE, - SS_EMPTY, + SS_LONG_TEXT, 1, 10, ssCwToneInitialize, @@ -117,7 +126,8 @@ void runSetting(const SettingScreen_t* const p_screen) { SettingScreen_t screen = {0}; memcpy_P(&screen,p_screen,sizeof(screen)); - displayDialog(reinterpret_cast(screen.Title),F("Push Tune to Save")); + displayDialog(screen.Title, + screen.AdditionalText); //Wait for button to stop being pressed while(btnDown()){ @@ -173,7 +183,7 @@ void printCarrierFreq(unsigned long freq) } void setupFreq(){ - displayDialog(F("Set Frequency"),F("Push TUNE to Save")); + //displayDialog(F("Set Frequency"),F("Push TUNE to Save")); //round off the the nearest khz { @@ -229,7 +239,7 @@ void setupFreq(){ } void setupBFO(){ - displayDialog(F("Set BFO"),F("Press TUNE to Save")); + //displayDialog(F("Set BFO"),F("Press TUNE to Save")); si5351bx_setfreq(0, globalSettings.usbCarrierFreq); printCarrierFreq(globalSettings.usbCarrierFreq); @@ -259,7 +269,7 @@ void setupCwDelay(){ int knob = 0; int prev_cw_delay; - displayDialog(F("Set CW T/R Delay"),F("Press tune to Save")); + //displayDialog(F("Set CW T/R Delay"),F("Press tune to Save")); prev_cw_delay = globalSettings.cwActiveTimeoutMs; @@ -300,7 +310,7 @@ void formatKeyerEnum(char* output, const KeyerMode_e mode) } void setupKeyer(){ - displayDialog(F("Set CW Keyer"),F("Press tune to Save")); + //displayDialog(F("Set CW Keyer"),F("Press tune to Save")); int knob = 0; uint32_t tmp_mode = globalSettings.keyerMode; @@ -333,7 +343,7 @@ void setupKeyer(){ void setupCwSpeed() { - displayDialog(F("Set CW Speed (WPM)"),F("Press tune to Save")); + //displayDialog(F("Set CW Speed (WPM)"),F("Press tune to Save")); unsigned int wpm = 1200/globalSettings.cwDitDurationMs; @@ -359,7 +369,7 @@ void setupCwSpeed() } void setupCwTone(){ - displayDialog(F("Set CW Tone (Hz)"),F("Press tune to Save")); + //displayDialog(F("Set CW Tone (Hz)"),F("Press tune to Save")); tone(CW_TONE, globalSettings.cwSideToneFreq); itoa(globalSettings.cwSideToneFreq, b, 10); @@ -386,7 +396,7 @@ void setupCwTone(){ void setupResetAll() { - displayDialog(F("Reset all cals and settings?"),F("Press tune to Confirm")); + //displayDialog(F("Reset all cals and settings?"),F("Press tune to Confirm")); strcpy_P(b,(const char*)F("No")); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); From 00f5d2691d2dcbf4ba2ea4d1019815e2a928dd92 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 12:56:47 -0800 Subject: [PATCH 060/324] Make text wrap work nicely --- PDQ_MinLib/PDQ_GFX.h | 44 ++++++++++++++++++++++++++++++++------------ nano_gui.cpp | 35 ++++++++++++++++++++++++++++++----- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/PDQ_MinLib/PDQ_GFX.h b/PDQ_MinLib/PDQ_GFX.h index 5b225ef..49370f0 100644 --- a/PDQ_MinLib/PDQ_GFX.h +++ b/PDQ_MinLib/PDQ_GFX.h @@ -145,6 +145,7 @@ class PDQ_GFX : public Print { static void drawChar(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size); static void drawCharGFX(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size); static inline void setCursor(coord_t x, coord_t y); + static inline void setBound(coord_t x, coord_t y); static inline void setTextColor(color_t c); static inline void setTextColor(color_t c, color_t bg); static inline void setTextSize(uint8_t s); @@ -157,8 +158,8 @@ class PDQ_GFX : public Print { static inline uint8_t getRotation() __attribute__ ((always_inline)) { return rotation; } static inline coord_t getCursorX() __attribute__ ((always_inline)) { return cursor_x; } static inline coord_t getCursorY() __attribute__ ((always_inline)) { return cursor_y; } - static inline void getTextBounds(char *string, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); - static inline void getTextBounds(const __FlashStringHelper *s, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h); + static inline void getTextBounds(char *string, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi = _width); + static inline void getTextBounds(const __FlashStringHelper *s, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi = _width); virtual size_t write(uint8_t); // used by Arduino "Print.h" (and the one required virtual function) @@ -167,6 +168,7 @@ class PDQ_GFX : public Print { static coord_t WIDTH, HEIGHT; // This is the 'raw' display w/h - never changes static coord_t _width, _height; // Display w/h as modified by current rotation static coord_t cursor_x, cursor_y; + static coord_t bound_x1, bound_x2; static color_t textcolor, textbgcolor; static uint8_t textsize; static uint8_t rotation; @@ -216,6 +218,10 @@ int16_t PDQ_GFX::cursor_x; template int16_t PDQ_GFX::cursor_y; template +int16_t PDQ_GFX::bound_x1; +template +int16_t PDQ_GFX::bound_x2; +template color_t PDQ_GFX::textcolor; template color_t PDQ_GFX::textbgcolor; @@ -239,6 +245,8 @@ PDQ_GFX::PDQ_GFX(coord_t w, coord_t h) _height = (int16_t)h; cursor_x = 0; cursor_y = 0; + bound_x1 = 0; + bound_x2 = WIDTH; rotation = 0; textsize = 1; textcolor = 0xffff; @@ -756,10 +764,10 @@ size_t PDQ_GFX::write(uint8_t c) if ((w > 0) && (h > 0)) { coord_t xo = (int8_t)pgm_read_byte(&glyph->xOffset); // sic - if(wrap && ((cursor_x + textsize * (xo + w)) >= _width)) + if(wrap && ((cursor_x + textsize * (xo + w)) >= bound_x2)) { // Drawing character would go off right edge; wrap to new line - cursor_x = 0; + cursor_x = bound_x1; cursor_y += (coord_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } @@ -970,6 +978,13 @@ void PDQ_GFX::setCursor(coord_t x, coord_t y) cursor_y = (int16_t)y; } +template +void PDQ_GFX::setBound(coord_t x1, coord_t x2) +{ + bound_x1 = (int16_t)x1; + bound_x2 = (int16_t)x2; +} + template void PDQ_GFX::setTextSize(uint8_t s) { @@ -1046,10 +1061,13 @@ void PDQ_GFX::setFont(const GFXfont *f) // Pass string and a cursor position, returns UL corner and W,H. template -void PDQ_GFX::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) +void PDQ_GFX::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi) { uint8_t c; // Current character + coord_t xs = x; + coord_t xe = xs+wi; + *x1 = x; *y1 = y; *w = *h = 0; @@ -1080,9 +1098,9 @@ void PDQ_GFX::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, in xa = pgm_read_byte(&glyph->xAdvance); xo = pgm_read_byte(&glyph->xOffset); yo = pgm_read_byte(&glyph->yOffset); - if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) // Line wrap + if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= xe)) // Line wrap { - x = 0; // Reset x to 0 + x = xs; // Reset x to 0 y += ya; // Advance y by 1 line } gx1 = x + xo * ts; @@ -1103,7 +1121,7 @@ void PDQ_GFX::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, in } else // Newline { - x = 0; // Reset x + x = xs; // Reset x y += ya; // Advance y by 1 line } } @@ -1158,10 +1176,12 @@ void PDQ_GFX::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, in // Same as above, but for PROGMEM strings template -void PDQ_GFX::getTextBounds(const __FlashStringHelper *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h) +void PDQ_GFX::getTextBounds(const __FlashStringHelper *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi) { uint8_t *s = (uint8_t *)str; uint8_t c; + coord_t xs = x; + coord_t xe = xs+wi; *x1 = x; *y1 = y; @@ -1194,9 +1214,9 @@ void PDQ_GFX::getTextBounds(const __FlashStringHelper *str, coord_t x, coord xa = pgm_read_byte(&glyph->xAdvance); xo = pgm_read_byte(&glyph->xOffset); yo = pgm_read_byte(&glyph->yOffset); - if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= _width)) // Line wrap + if (wrap && ((x + (((int16_t)xo + gw) * ts)) >= xe)) // Line wrap { - x = 0; // Reset x to 0 + x = xs; // Reset x to 0 y += ya; // Advance y by 1 line } gx1 = x + xo * ts; @@ -1217,7 +1237,7 @@ void PDQ_GFX::getTextBounds(const __FlashStringHelper *str, coord_t x, coord } else // Newline { - x = 0; // Reset x + x = xs; // Reset x y += ya; // Advance y by 1 line } } diff --git a/nano_gui.cpp b/nano_gui.cpp index 6ca1ddb..b27b091 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -178,7 +178,7 @@ void displayInit(void){ tft.begin(); tft.setFont(ubitx_font); - tft.setTextWrap(false); + tft.setTextWrap(true); tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK); tft.setTextSize(1); tft.setRotation(1); @@ -217,6 +217,14 @@ void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t void displayRawText(char *text, int x1, int y1, int color, int background){ tft.setTextColor(color,background); tft.setCursor(x1,y1); + tft.setBound(0,320); + tft.print(text); +} + +void displayRawText(char *text, int x1, int y1, int w, int color, int background){ + tft.setTextColor(color,background); + tft.setCursor(x1,y1); + tft.setBound(x1,x1+w); tft.print(text); } @@ -228,10 +236,27 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr int16_t y1_out; uint16_t width_out; uint16_t height_out; - tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out); - x1 += (w - ( width_out + (x1_out-x1)))/2; - y1 += h - (h - height_out)/2; - displayRawText(text,x1,y1,color,background); + tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out,w); + Serial.println(text); + Serial.print(F("Calc w/h:")); + Serial.print(width_out); + Serial.print(F(",")); + Serial.println(height_out); + Serial.print(F("w/h:")); + Serial.print(w); + Serial.print(F(",")); + Serial.println(h); + Serial.print(F("Old x1/y1:")); + Serial.print(x1); + Serial.print(F(",")); + Serial.println(y1); + x1 += (w - ( (int32_t)width_out + (x1_out-x1)))/2; + y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out + (y1_out-y1)))/2; + Serial.print(F("New x1/y1:")); + Serial.print(x1); + Serial.print(F(",")); + Serial.println(y1); + displayRawText(text,x1,y1,w,color,background); } void setupTouch(){ From a8e616637c394856d9fdafc7d1750dc7b7835205 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 12:57:53 -0800 Subject: [PATCH 061/324] Remove a bunch of debugging statements --- nano_gui.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index b27b091..902f2ad 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -237,25 +237,8 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr uint16_t width_out; uint16_t height_out; tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out,w); - Serial.println(text); - Serial.print(F("Calc w/h:")); - Serial.print(width_out); - Serial.print(F(",")); - Serial.println(height_out); - Serial.print(F("w/h:")); - Serial.print(w); - Serial.print(F(",")); - Serial.println(h); - Serial.print(F("Old x1/y1:")); - Serial.print(x1); - Serial.print(F(",")); - Serial.println(y1); x1 += (w - ( (int32_t)width_out + (x1_out-x1)))/2; y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out + (y1_out-y1)))/2; - Serial.print(F("New x1/y1:")); - Serial.print(x1); - Serial.print(F(",")); - Serial.println(y1); displayRawText(text,x1,y1,w,color,background); } From ec409d8805d4f80f8c581a7a2abd2b3e07ca14c5 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 13:05:02 -0800 Subject: [PATCH 062/324] Fix reset x for manual newlines --- PDQ_MinLib/PDQ_GFX.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDQ_MinLib/PDQ_GFX.h b/PDQ_MinLib/PDQ_GFX.h index 49370f0..cb9f152 100644 --- a/PDQ_MinLib/PDQ_GFX.h +++ b/PDQ_MinLib/PDQ_GFX.h @@ -748,7 +748,7 @@ size_t PDQ_GFX::write(uint8_t c) { if(c == '\n') { - cursor_x = 0; + cursor_x = bound_x1; cursor_y += (coord_t)textsize * (uint8_t)pgm_read_byte(&gfxFont->yAdvance); } else if (c != '\r') From d0900aa392d05e92c508c40f7e503960e8076a04 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 18:40:11 -0800 Subject: [PATCH 063/324] Refactor local oscillator cal --- nano_gui.h | 1 - setup.cpp | 171 +++++++++++++++++++----------------------- ubitx.h | 9 --- ubitx_ui.cpp | 35 +++++---- ubitx_v6.3.1_code.ino | 11 +-- 5 files changed, 102 insertions(+), 125 deletions(-) diff --git a/nano_gui.h b/nano_gui.h index f58cf02..b6d24ac 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -23,7 +23,6 @@ void formatFreq(uint32_t freq, char* buff, uint16_t buff_size); /* touch functions */ boolean readTouch(); -void setupTouch(); void scaleTouch(struct Point *p); // Color definitions diff --git a/setup.cpp b/setup.cpp index 953a0dd..329a41d 100644 --- a/setup.cpp +++ b/setup.cpp @@ -1,9 +1,10 @@ #include -#include +#include "freeRam.h" #include "morse.h" +#include "nano_gui.h" +#include "setup.h" #include "settings.h" #include "ubitx.h" -#include "nano_gui.h" /** Menus * The Radio menus are accessed by tapping on the function button. @@ -85,43 +86,6 @@ struct SettingScreen_t { void (*Finalize)(const long int final_value); }; -#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) -ssCwToneInitialize(long int* start_value_out) -{ - *start_value_out = globalSettings.cwSideToneFreq; -} -ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out) -{ - *validated_value_out = LIMIT(candidate_value_in,100,2000); -} -ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) -{ - globalSettings.cwSideToneFreq = new_value; - tone(CW_TONE, globalSettings.cwSideToneFreq); - ltoa(globalSettings.cwSideToneFreq,buff_out,10); -} -ssCwToneFinalize(const long int final_value) -{ - noTone(CW_TONE); - globalSettings.cwSideToneFreq = final_value; - SaveSettingsToEeprom(); -} -const char SS_EMPTY [] PROGMEM = ""; -const char SS_CW_TONE [] PROGMEM = "Set CW Tone (Hz)"; -const char SS_LONG_TEXT [] PROGMEM = "This is a long string of text that should be wrapped at least once, possibly more."; -const SettingScreen_t settingScreens [] PROGMEM = { - SS_CW_TONE, - SS_LONG_TEXT, - 1, - 10, - ssCwToneInitialize, - ssCwToneValidate, - ssCwToneChange, - ssCwToneFinalize -}; -void runSetting(const SettingScreen_t* const screen); -void runToneSetting(){runSetting(&settingScreens[0]);} - void runSetting(const SettingScreen_t* const p_screen) { SettingScreen_t screen = {0}; @@ -142,7 +106,7 @@ void runSetting(const SettingScreen_t* const p_screen) screen.OnValueChange(last_value,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); - raw_value = last_value * screen.KnobDivider; + raw_value = last_value * (int32_t)screen.KnobDivider; while (!btnDown()) { @@ -176,73 +140,96 @@ void runSetting(const SettingScreen_t* const p_screen) screen.Finalize(last_value); } -void printCarrierFreq(unsigned long freq) +#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) + +ssCwToneInitialize(long int* start_value_out) { - formatFreq(freq,c,sizeof(c)); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); + *start_value_out = globalSettings.cwSideToneFreq; } +ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,100,2000); +} +ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + globalSettings.cwSideToneFreq = new_value; + tone(CW_TONE, globalSettings.cwSideToneFreq); + ltoa(globalSettings.cwSideToneFreq,buff_out,10); + strcat_P(buff_out,(const char*)F("Hz")); +} +ssCwToneFinalize(const long int final_value) +{ + noTone(CW_TONE); + globalSettings.cwSideToneFreq = final_value; + SaveSettingsToEeprom(); +} +const char SS_CW_TONE_T [] PROGMEM = "Set CW Tone"; +const char SS_CW_TONE_A [] PROGMEM = "Select a frequency that\nCW mode to tune for"; +const SettingScreen_t ssTone PROGMEM = { + SS_CW_TONE_T, + SS_CW_TONE_A, + 1, + 10, + ssCwToneInitialize, + ssCwToneValidate, + ssCwToneChange, + ssCwToneFinalize +}; +void runToneSetting(){runSetting(&ssTone);} -void setupFreq(){ - //displayDialog(F("Set Frequency"),F("Push TUNE to Save")); - - //round off the the nearest khz +void ssLocalOscInitialize(long int* start_value_out){ + //round off the current frequency the nearest kHz { uint32_t freq = GetActiveVfoFreq(); - freq = (freq/1000l)* 1000l; + freq = (freq/1000L) * 1000L; setFrequency(freq); + si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator, cw tx switches it off } - - strcpy_P(c,(const char*)F("You should have a")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - strcpy_P(c,(const char*)F("signal exactly at")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 1*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - ltoa(GetActiveVfoFreq()/1000L, c, 10); - strcat_P(c,(const char*)F(" KHz")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 2*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - strcpy_P(c,(const char*)F("Rotate to zerobeat")); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - - ltoa(globalSettings.oscillatorCal, b, 10); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); - //keep clear of any previous button press - while (btnDown()) - active_delay(100); - active_delay(100); - - while (!btnDown()) - { - int knob = enc_read(); - if(knob != 0){ - globalSettings.oscillatorCal += knob * 875; - } - else{ - continue; //don't update the frequency or the display - } - - si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator anyway, cw tx switches it off - si5351_set_calibration(globalSettings.oscillatorCal); - setFrequency(GetActiveVfoFreq()); - - ltoa(globalSettings.oscillatorCal, b, 10); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); + *start_value_out = globalSettings.oscillatorCal; + Serial.println(freeRam()); +} +void ssLocalOscValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = candidate_value_in;//No check - allow anything +} +void ssLocalOscChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + si5351_set_calibration(new_value); + setFrequency(GetActiveVfoFreq()); + const long int u = abs(new_value); + if(new_value != u){ + strcpy_P(buff_out,(const char*)F("-")); + ++buff_out; } - + formatFreq(u,buff_out,buff_out_size); + strcat_P(buff_out,(const char*)F("Hz")); +} +void ssLocalOscFinalize(const long int final_value) +{ + globalSettings.oscillatorCal = final_value; SaveSettingsToEeprom(); - initOscillators(); si5351_set_calibration(globalSettings.oscillatorCal); setFrequency(GetActiveVfoFreq()); - - //debounce and delay - while(btnDown()) - active_delay(50); - active_delay(100); } +const char SS_LOCAL_OSC_T [] PROGMEM = "Set Local Osc Calibration"; +const char SS_LOCAL_OSC_A [] PROGMEM = "Exit menu, tune so that the\ndial displays the desired freq,\nthen tune here until the\nsignal is zerobeat"; +const SettingScreen_t ssLocalOsc PROGMEM = { + SS_LOCAL_OSC_T, + SS_LOCAL_OSC_A, + 1, + 875, + ssLocalOscInitialize, + ssLocalOscValidate, + ssLocalOscChange, + ssLocalOscFinalize +}; +void runLocalOscSetting(){runSetting(&ssLocalOsc);} void setupBFO(){ //displayDialog(F("Set BFO"),F("Press TUNE to Save")); si5351bx_setfreq(0, globalSettings.usbCarrierFreq); - printCarrierFreq(globalSettings.usbCarrierFreq); + //printCarrierFreq(globalSettings.usbCarrierFreq); while (!btnDown()){ int knob = enc_read(); @@ -255,7 +242,7 @@ void setupBFO(){ si5351bx_setfreq(0, globalSettings.usbCarrierFreq); setFrequency(GetActiveVfoFreq()); - printCarrierFreq(globalSettings.usbCarrierFreq); + //printCarrierFreq(globalSettings.usbCarrierFreq); active_delay(100); } @@ -450,7 +437,7 @@ const char MI_SET_BFO [] PROGMEM = "Beat Frequency Osc (BFO)"; const char MI_TOUCH [] PROGMEM = "Touch Screen"; const MenuItem_t calibrationMenu [] PROGMEM { {MT_CAL,nullptr},//Title - {MI_SET_FREQ,setupFreq}, + {MI_SET_FREQ,runLocalOscSetting}, {MI_SET_BFO,setupBFO}, {MI_TOUCH,setupTouch}, }; diff --git a/ubitx.h b/ubitx.h index 3944a6d..e9aa36e 100644 --- a/ubitx.h +++ b/ubitx.h @@ -92,10 +92,6 @@ extern char c[30], b[30]; #define HIGHEST_FREQ (30000000l) static const uint32_t THRESHOLD_USB_LSB = 10000000L; -extern unsigned long firstIF; - -extern uint8_t menuOn; - /* these are functions implemented in the main file named as ubitx_xxx.ino */ void active_delay(int delay_by); void saveVFOs(); @@ -122,11 +118,6 @@ void drawTx(); //are useful to concatanate the values with text like "Set Freq to " x " KHz" int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix); -//functions of the setup menu. implemented in seteup.cpp -void doSetup2(); //main setup function, displays the setup menu, calls various dialog boxes -void setupBFO(); -void setupFreq(); - //main functions to check if any button is pressed and other user interface events void doCommands(); //does the commands with encoder to jump from button to button void checkTouch(); //does the commands with a touch on the buttons diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 8457f11..ad0f9ee 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -1,7 +1,8 @@ #include -#include +#include "freeRam.h" #include "morse.h" #include "settings.h" +#include "setup.h" #include "ubitx.h" #include "nano_gui.h" @@ -900,6 +901,7 @@ void doCommand(Button* button){ } case BUTTON_MNU: { + Serial.println(freeRam()); doSetup2(); break; } @@ -953,20 +955,17 @@ void drawFocus(int ibtn, int color){ } void doCommands(){ - int select=0, i, prevButton, btnState; + int select = 0; + int prev_button = 0; //wait for the button to be raised up while(btnDown()) active_delay(50); active_delay(50); //debounce - menuOn = 2; - - while (menuOn){ - + while (true){ //check if the knob's button was pressed - btnState = btnDown(); - if (btnState){ + if (btnDown()){ Button button; memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); @@ -986,27 +985,27 @@ void doCommands(){ return; } - i = enc_read(); + int knob = enc_read(); - if (i == 0){ + if (knob == 0){ active_delay(50); continue; } - if (i > 0){ - if (select + i < BUTTON_TOTAL * 10) - select += i; + if (knob > 0){ + if (select + knob < BUTTON_TOTAL * 10) + select += knob; } - if (i < 0 && select + i >= 0) - select += i; //caught ya, i is already -ve here, so you add it + if (knob < 0 && select + knob >= 0) + select += knob; //caught ya, i is already -ve here, so you add it - if (prevButton == select / 10) + if (prev_button == select / 10) continue; //we are on a new button - drawFocus(prevButton, COLOR_INACTIVE_BORDER); + drawFocus(prev_button, COLOR_INACTIVE_BORDER); drawFocus(select/10, COLOR_ACTIVE_BORDER); - prevButton = select/10; + prev_button = select/10; } // guiUpdate(); diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 0d18816..bce908d 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -31,6 +31,7 @@ */ #include #include "settings.h" +#include "setup.h" #include "ubitx.h" #include "nano_gui.h" @@ -40,16 +41,16 @@ * created in a memory region called the stack. The stack has just a few bytes of space on the Arduino * if you declare large strings inside functions, they can easily exceed the capacity of the stack * and mess up your programs. - * We circumvent this by declaring a few global buffers as kitchen counters where we can + * We circumvent this by declaring a few global buffers as kitchen counters where we can * slice and dice our strings. These strings are mostly used to control the display or handle * the input and output from the USB port. We must keep a count of the bytes used while reading * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. */ -char c[30], b[30]; +char b[30]; +char c[30]; //during CAT commands, we will freeeze the display until CAT is disengaged unsigned char doingCAT = 0; -byte menuOn = 0; //set to 1 when the menu is being displayed, if a menu item sets it to zero, the menu is exited /** @@ -463,7 +464,7 @@ void initPorts(){ void setup() { Serial.begin(38400); - Serial.flush(); + Serial.flush(); initSettings(); displayInit(); @@ -477,7 +478,7 @@ void setup() setupTouch(); SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); setFrequency(10000000L); - setupFreq(); + runLocalOscSetting(); SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); setFrequency(7100000L); setupBFO(); From 9b224699ee46af8222990b6e2e072aca822ec3bf Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 18:41:36 -0800 Subject: [PATCH 064/324] increase buffer b size to avoid heap smashing --- ubitx.h | 2 +- ubitx_v6.3.1_code.ino | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ubitx.h b/ubitx.h index e9aa36e..0800e75 100644 --- a/ubitx.h +++ b/ubitx.h @@ -56,7 +56,7 @@ it uses an ILI9341 display controller and an XPT2046 touch controller. * the input and output from the USB port. We must keep a count of the bytes used while reading * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. */ -extern char c[30], b[30]; +extern char c[30], b[128]; /** * The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig. diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index bce908d..21abdaf 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -46,7 +46,7 @@ * the input and output from the USB port. We must keep a count of the bytes used while reading * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. */ -char b[30]; +char b[128]; char c[30]; //during CAT commands, we will freeeze the display until CAT is disengaged From 315d9348f06503ff4f18cdb21754b186a37b03b2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 19:00:45 -0800 Subject: [PATCH 065/324] Swap most string operations to bounded versions --- setup.cpp | 32 +++++++++++++++----------------- ubitx_cat.cpp | 11 ----------- ubitx_ui.cpp | 38 ++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 48 deletions(-) diff --git a/setup.cpp b/setup.cpp index 329a41d..6a90477 100644 --- a/setup.cpp +++ b/setup.cpp @@ -1,5 +1,4 @@ #include -#include "freeRam.h" #include "morse.h" #include "nano_gui.h" #include "setup.h" @@ -67,11 +66,11 @@ void displayDialog(const char* title, displayClear(COLOR_BACKGROUND); displayRect(LAYOUT_OUTER_BORDER_X,LAYOUT_OUTER_BORDER_Y,LAYOUT_OUTER_BORDER_WIDTH,LAYOUT_OUTER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); displayRect(LAYOUT_INNER_BORDER_X,LAYOUT_INNER_BORDER_Y,LAYOUT_INNER_BORDER_WIDTH,LAYOUT_INNER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); - strcpy_P(b,title); + strncpy_P(b,title,sizeof(b)); displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); - strcpy_P(b,instructions); + strncpy_P(b,instructions,sizeof(b)); displayText(b, LAYOUT_INSTRUCTIONS_TEXT_X, LAYOUT_INSTRUCTIONS_TEXT_Y, LAYOUT_INSTRUCTIONS_TEXT_WIDTH, LAYOUT_INSTRUCTIONS_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - strcpy_P(b,(const char*)F("Push Tune to Save")); + strncpy_P(b,(const char*)F("Push Tune to Save"),sizeof(b)); displayText(b, LAYOUT_CONFIRM_TEXT_X, LAYOUT_CONFIRM_TEXT_Y, LAYOUT_CONFIRM_TEXT_WIDTH, LAYOUT_CONFIRM_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } @@ -155,7 +154,7 @@ ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_s globalSettings.cwSideToneFreq = new_value; tone(CW_TONE, globalSettings.cwSideToneFreq); ltoa(globalSettings.cwSideToneFreq,buff_out,10); - strcat_P(buff_out,(const char*)F("Hz")); + strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); } ssCwToneFinalize(const long int final_value) { @@ -186,7 +185,6 @@ void ssLocalOscInitialize(long int* start_value_out){ si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator, cw tx switches it off } *start_value_out = globalSettings.oscillatorCal; - Serial.println(freeRam()); } void ssLocalOscValidate(const long int candidate_value_in, long int* validated_value_out) { @@ -198,11 +196,11 @@ void ssLocalOscChange(const long int new_value, char* buff_out, const size_t buf setFrequency(GetActiveVfoFreq()); const long int u = abs(new_value); if(new_value != u){ - strcpy_P(buff_out,(const char*)F("-")); + strncpy_P(buff_out,(const char*)F("-"),buff_out_size); ++buff_out; } - formatFreq(u,buff_out,buff_out_size); - strcat_P(buff_out,(const char*)F("Hz")); + formatFreq(u,buff_out,buff_out_size - strlen(buff_out)); + strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); } void ssLocalOscFinalize(const long int final_value) { @@ -261,7 +259,7 @@ void setupCwDelay(){ prev_cw_delay = globalSettings.cwActiveTimeoutMs; ltoa(globalSettings.cwActiveTimeoutMs, b, 10); - strcat_P(b,(const char*)F(" msec")); + strncat_P(b,(const char*)F(" msec"),sizeof(b) - strlen(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); while (!btnDown()){ @@ -275,7 +273,7 @@ void setupCwDelay(){ continue; //don't update the frequency or the display ltoa(globalSettings.cwActiveTimeoutMs, b, 10); - strcat_P(b,(const char*)F(" msec")); + strncat_P(b,(const char*)F(" msec"),sizeof(b) - strlen(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); } @@ -384,7 +382,7 @@ void setupCwTone(){ void setupResetAll() { //displayDialog(F("Reset all cals and settings?"),F("Press tune to Confirm")); - strcpy_P(b,(const char*)F("No")); + strncpy_P(b,(const char*)F("No"),sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); bool reset_all = false; @@ -402,10 +400,10 @@ void setupResetAll() } if(reset_all){ - strcpy_P(b,(const char*)F("Yes")); + strncpy_P(b,(const char*)F("Yes"),sizeof(b)); } else{ - strcpy_P(b,(const char*)F("No")); + strncpy_P(b,(const char*)F("No"),sizeof(b)); } displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); @@ -474,15 +472,15 @@ void drawMenu(const MenuItem_t* const items, const uint16_t num_items) displayClear(COLOR_BACKGROUND); MenuItem_t mi = {"",nullptr}; memcpy_P(&mi,&items[0],sizeof(mi)); - strcpy_P(b,mi.ItemName); + strncpy_P(b,mi.ItemName,sizeof(b)); displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); for(unsigned int i = 1; i < num_items; ++i){ memcpy_P(&mi,&items[i],sizeof(mi)); - strcpy_P(b,mi.ItemName); + strncpy_P(b,mi.ItemName,sizeof(b)); displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); } memcpy_P(&mi,&exitMenu,sizeof(mi)); - strcpy_P(b,mi.ItemName); + strncpy_P(b,mi.ItemName,sizeof(b)); displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (num_items-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); } diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 815c18b..91c7f49 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -123,13 +123,6 @@ void catReadEEPRom(void) //for remove warnings byte temp0 = cat[0]; byte temp1 = cat[1]; -/* - itoa((int) cat[0], b, 16); - strcat(b, ":"); - itoa((int) cat[1], c, 16); - strcat(b, c); - printLine2(b); -*/ cat[0] = 0; cat[1] = 0; @@ -385,10 +378,6 @@ void processCATCommand2(byte* cmd) { default: //somehow, get this to print the four bytes ultoa(*((unsigned long *)cmd), c, 16); - /*itoa(cmd[4], b, 16); - strcat(b, ">"); - strcat(b, c); - printLine2(b);*/ response[0] = 0x00; Serial.write(response[0]); } diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index ad0f9ee..624705f 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -1,5 +1,4 @@ #include -#include "freeRam.h" #include "morse.h" #include "settings.h" #include "setup.h" @@ -166,10 +165,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, const active_delay(200); knob_value = initial; - strcpy_P(b,(const char*)prefix); + strncpy_P(b,(const char*)prefix,sizeof(b)); itoa(knob_value, c, 10); - strcat(b, c); - strcat_P(b, (const char*)postfix); + strncat(b, c, sizeof(b) - strlen(b)); + strncat_P(b, (const char*)postfix, sizeof(b) - strlen(b)); drawCommandbar(b); while(!btnDown() && digitalRead(PTT) == HIGH){ @@ -180,10 +179,10 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, const if (knob_value < maximum && knob > 0) knob_value += step_size; - strcpy_P(b,(const char*)prefix); + strncpy_P(b,(const char*)prefix,sizeof(b)); itoa(knob_value, c, 10); - strcat(b, c); - strcat_P(b,(const char*)postfix); + strncat(b, c, sizeof(b) - strlen(b)); + strncat_P(b,(const char*)postfix, sizeof(b) - strlen(b)); drawCommandbar(b); } checkCAT(); @@ -335,8 +334,8 @@ void displayRIT(){ c[0] = 0; displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); if(globalSettings.ritOn){ - strcpy_P(c,(const char*)F("TX:")); - formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-3); + strncpy_P(c,(const char*)F("TX:"),sizeof(c)); + formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-strlen(c)); if (VFO_A == globalSettings.activeVfo) displayText(c, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); else @@ -350,9 +349,9 @@ void fastTune(){ active_delay(50); active_delay(300); - strcpy_P(c,(const char*)F("Fast tune")); + strncpy_P(c,(const char*)F("Fast tune"),sizeof(c)); displayText(c, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - while(1){ + while(true){ checkCAT(); //exit after debouncing the btnDown @@ -472,8 +471,8 @@ void enterFreq(){ }//switch }//if button hit test }// end of the button scanning loop - strcpy(b, c); - strcat_P(b,(const char*)F(" KHz")); + strncpy(b, c, sizeof(b)); + strncat_P(b,(const char*)F(" KHz"),sizeof(b) - strlen(b)); displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); active_delay(300); while(readTouch()) @@ -482,21 +481,21 @@ void enterFreq(){ } void drawCWStatus(){ - strcpy_P(b,(const char*)F(" cw: ")); + strncpy_P(b,(const char*)F(" cw: "),sizeof(b)); int wpm = 1200/globalSettings.cwDitDurationMs; itoa(wpm,c, 10); - strcat(b, c); - strcat_P(b,(const char*)F("wpm, ")); + strncat(b, c, sizeof(b) - strlen(b)); + strncat_P(b,(const char*)F("wpm, "), sizeof(b) - strlen(b)); itoa(globalSettings.cwSideToneFreq, c, 10); - strcat(b, c); - strcat_P(b,(const char*)F("hz")); + strncat(b, c, sizeof(b) - strlen(b)); + strncat_P(b,(const char*)F("hz"), sizeof(b) - strlen(b)); displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } void drawTx(){ if (globalSettings.txActive){ - strcpy_P(b,(const char*)F("TX")); + strncpy_P(b,(const char*)F("TX"), sizeof(b)); displayText(b, LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND); } else{ @@ -901,7 +900,6 @@ void doCommand(Button* button){ } case BUTTON_MNU: { - Serial.println(freeRam()); doSetup2(); break; } From b99e13eff4b211f73b68b8ab3441037c65ac15a3 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 19:24:26 -0800 Subject: [PATCH 066/324] Refactor BFO settings menu --- setup.cpp | 63 +++++++++++++++++++++++++------------------ setup.h | 6 +++++ ubitx_v6.3.1_code.ino | 2 +- 3 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 setup.h diff --git a/setup.cpp b/setup.cpp index 6a90477..fcc43a8 100644 --- a/setup.cpp +++ b/setup.cpp @@ -78,7 +78,7 @@ struct SettingScreen_t { const char* const Title; const char* const AdditionalText; const uint16_t KnobDivider; - const uint16_t StepSize; + const int16_t StepSize;//int so that it can be negative void (*Initialize)(long int* start_value_out); void (*Validate)(const long int candidate_value_in, long int* validated_value_out); void (*OnValueChange)(const long int new_value, char* buff_out, const size_t buff_out_size); @@ -111,7 +111,7 @@ void runSetting(const SettingScreen_t* const p_screen) { int knob = enc_read(); if(knob != 0){ - raw_value += knob * (int32_t)screen.StepSize; + raw_value += knob * screen.StepSize; } else{ continue; @@ -141,6 +141,7 @@ void runSetting(const SettingScreen_t* const p_screen) #define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) +//CW Tone ssCwToneInitialize(long int* start_value_out) { *start_value_out = globalSettings.cwSideToneFreq; @@ -176,11 +177,11 @@ const SettingScreen_t ssTone PROGMEM = { }; void runToneSetting(){runSetting(&ssTone);} +//Local Oscillator void ssLocalOscInitialize(long int* start_value_out){ - //round off the current frequency the nearest kHz { uint32_t freq = GetActiveVfoFreq(); - freq = (freq/1000L) * 1000L; + freq = (freq/1000L) * 1000L;//round off the current frequency the nearest kHz setFrequency(freq); si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator, cw tx switches it off } @@ -223,32 +224,42 @@ const SettingScreen_t ssLocalOsc PROGMEM = { }; void runLocalOscSetting(){runSetting(&ssLocalOsc);} -void setupBFO(){ - //displayDialog(F("Set BFO"),F("Press TUNE to Save")); - +//BFO +void ssBfoInitialize(long int* start_value_out){ si5351bx_setfreq(0, globalSettings.usbCarrierFreq); - //printCarrierFreq(globalSettings.usbCarrierFreq); - - while (!btnDown()){ - int knob = enc_read(); - if(knob != 0){ - globalSettings.usbCarrierFreq -= 50 * knob; - } - else{ - continue; //don't update the frequency or the display - } - - si5351bx_setfreq(0, globalSettings.usbCarrierFreq); - setFrequency(GetActiveVfoFreq()); - //printCarrierFreq(globalSettings.usbCarrierFreq); - - active_delay(100); - } - + *start_value_out = globalSettings.usbCarrierFreq; +} +void ssBfoValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,11048000L,11060000L); +} +void ssBfoChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + si5351bx_setfreq(0, new_value); + setFrequency(GetActiveVfoFreq()); + formatFreq(new_value,buff_out,buff_out_size); + strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); +} +void ssBfoFinalize(const long int final_value) +{ + globalSettings.usbCarrierFreq = final_value; SaveSettingsToEeprom(); si5351bx_setfreq(0, globalSettings.usbCarrierFreq); setFrequency(GetActiveVfoFreq()); } +const char SS_BFO_T [] PROGMEM = "Set BFO Calibration"; +const char SS_BFO_A [] PROGMEM = "Exit menu, tune to an unused\nfrequency, then tune here\nuntil the audio is between\n300-3000Hz"; +const SettingScreen_t ssBfo PROGMEM = { + SS_BFO_T, + SS_BFO_A, + 1, + -50,//Negative to make dial more intuitive: turning clockwise increases the perceived audio frequency + ssBfoInitialize, + ssBfoValidate, + ssBfoChange, + ssBfoFinalize +}; +void runBfoSetting(){runSetting(&ssBfo);} void setupCwDelay(){ int knob = 0; @@ -436,7 +447,7 @@ const char MI_TOUCH [] PROGMEM = "Touch Screen"; const MenuItem_t calibrationMenu [] PROGMEM { {MT_CAL,nullptr},//Title {MI_SET_FREQ,runLocalOscSetting}, - {MI_SET_BFO,setupBFO}, + {MI_SET_BFO,runBfoSetting}, {MI_TOUCH,setupTouch}, }; void runCalibrationMenu(){RUN_MENU(calibrationMenu);} diff --git a/setup.h b/setup.h new file mode 100644 index 0000000..16b5b0d --- /dev/null +++ b/setup.h @@ -0,0 +1,6 @@ +#pragma once + +void doSetup2(); //main setup function, displays the setup menu, calls various dialog boxes +void setupTouch(); +void runLocalOscSetting(); +void runBfoSetting(); \ No newline at end of file diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 21abdaf..617977e 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -481,7 +481,7 @@ void setup() runLocalOscSetting(); SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); setFrequency(7100000L); - setupBFO(); + runBfoSetting(); } guiUpdate(); From 58bfe556207f6f3bdaef3b2db4f98ac51b7571c0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 19:26:31 -0800 Subject: [PATCH 067/324] Move tone down to keep the menus in a somewhat orderly fashion --- setup.cpp | 72 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/setup.cpp b/setup.cpp index fcc43a8..a2d91f0 100644 --- a/setup.cpp +++ b/setup.cpp @@ -141,42 +141,6 @@ void runSetting(const SettingScreen_t* const p_screen) #define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) -//CW Tone -ssCwToneInitialize(long int* start_value_out) -{ - *start_value_out = globalSettings.cwSideToneFreq; -} -ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out) -{ - *validated_value_out = LIMIT(candidate_value_in,100,2000); -} -ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) -{ - globalSettings.cwSideToneFreq = new_value; - tone(CW_TONE, globalSettings.cwSideToneFreq); - ltoa(globalSettings.cwSideToneFreq,buff_out,10); - strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); -} -ssCwToneFinalize(const long int final_value) -{ - noTone(CW_TONE); - globalSettings.cwSideToneFreq = final_value; - SaveSettingsToEeprom(); -} -const char SS_CW_TONE_T [] PROGMEM = "Set CW Tone"; -const char SS_CW_TONE_A [] PROGMEM = "Select a frequency that\nCW mode to tune for"; -const SettingScreen_t ssTone PROGMEM = { - SS_CW_TONE_T, - SS_CW_TONE_A, - 1, - 10, - ssCwToneInitialize, - ssCwToneValidate, - ssCwToneChange, - ssCwToneFinalize -}; -void runToneSetting(){runSetting(&ssTone);} - //Local Oscillator void ssLocalOscInitialize(long int* start_value_out){ { @@ -261,6 +225,42 @@ const SettingScreen_t ssBfo PROGMEM = { }; void runBfoSetting(){runSetting(&ssBfo);} +//CW Tone +ssCwToneInitialize(long int* start_value_out) +{ + *start_value_out = globalSettings.cwSideToneFreq; +} +ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,100,2000); +} +ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + globalSettings.cwSideToneFreq = new_value; + tone(CW_TONE, globalSettings.cwSideToneFreq); + ltoa(globalSettings.cwSideToneFreq,buff_out,10); + strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); +} +ssCwToneFinalize(const long int final_value) +{ + noTone(CW_TONE); + globalSettings.cwSideToneFreq = final_value; + SaveSettingsToEeprom(); +} +const char SS_CW_TONE_T [] PROGMEM = "Set CW Tone"; +const char SS_CW_TONE_A [] PROGMEM = "Select a frequency that\nCW mode to tune for"; +const SettingScreen_t ssTone PROGMEM = { + SS_CW_TONE_T, + SS_CW_TONE_A, + 1, + 10, + ssCwToneInitialize, + ssCwToneValidate, + ssCwToneChange, + ssCwToneFinalize +}; +void runToneSetting(){runSetting(&ssTone);} + void setupCwDelay(){ int knob = 0; int prev_cw_delay; From dc1da20b13072ed632ea6d6b3f37620653e65208 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 19:40:03 -0800 Subject: [PATCH 068/324] Refactor cw switch delay --- setup.cpp | 68 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/setup.cpp b/setup.cpp index a2d91f0..994d589 100644 --- a/setup.cpp +++ b/setup.cpp @@ -226,22 +226,22 @@ const SettingScreen_t ssBfo PROGMEM = { void runBfoSetting(){runSetting(&ssBfo);} //CW Tone -ssCwToneInitialize(long int* start_value_out) +void ssCwToneInitialize(long int* start_value_out) { *start_value_out = globalSettings.cwSideToneFreq; } -ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out) +void ssCwToneValidate(const long int candidate_value_in, long int* validated_value_out) { *validated_value_out = LIMIT(candidate_value_in,100,2000); } -ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) +void ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) { globalSettings.cwSideToneFreq = new_value; tone(CW_TONE, globalSettings.cwSideToneFreq); ltoa(globalSettings.cwSideToneFreq,buff_out,10); strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); } -ssCwToneFinalize(const long int final_value) +void ssCwToneFinalize(const long int final_value) { noTone(CW_TONE); globalSettings.cwSideToneFreq = final_value; @@ -261,36 +261,38 @@ const SettingScreen_t ssTone PROGMEM = { }; void runToneSetting(){runSetting(&ssTone);} -void setupCwDelay(){ - int knob = 0; - int prev_cw_delay; - - //displayDialog(F("Set CW T/R Delay"),F("Press tune to Save")); - - prev_cw_delay = globalSettings.cwActiveTimeoutMs; - - ltoa(globalSettings.cwActiveTimeoutMs, b, 10); - strncat_P(b,(const char*)F(" msec"),sizeof(b) - strlen(b)); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - - while (!btnDown()){ - knob = enc_read(); - - if (knob < 0 && globalSettings.cwActiveTimeoutMs > 100) - globalSettings.cwActiveTimeoutMs -= 100; - else if (knob > 0 && globalSettings.cwActiveTimeoutMs < 1000) - globalSettings.cwActiveTimeoutMs += 100; - else - continue; //don't update the frequency or the display - - ltoa(globalSettings.cwActiveTimeoutMs, b, 10); - strncat_P(b,(const char*)F(" msec"),sizeof(b) - strlen(b)); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - - } - +//CW Switch Delay +void ssCwSwitchDelayInitialize(long int* start_value_out) +{ + *start_value_out = globalSettings.cwActiveTimeoutMs; +} +void ssCwSwitchDelayValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,100,1000); +} +void ssCwSwitchDelayChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + ltoa(new_value,buff_out,10); + strncat_P(buff_out,(const char*)F("ms"),buff_out_size - strlen(buff_out)); +} +void ssCwSwitchDelayFinalize(const long int final_value) +{ + globalSettings.cwActiveTimeoutMs = final_value; SaveSettingsToEeprom(); } +const char SS_CW_SWITCH_T [] PROGMEM = "Set CW Tx/Rx Switch Delay"; +const char SS_CW_SWITCH_A [] PROGMEM = "Select how long the radio\nshould wait before switching\nbetween TX and RX when in\nCW mode"; +const SettingScreen_t ssCwSwitchDelay PROGMEM = { + SS_CW_SWITCH_T, + SS_CW_SWITCH_A, + 1, + 100, + ssCwSwitchDelayInitialize, + ssCwSwitchDelayValidate, + ssCwSwitchDelayChange, + ssCwSwitchDelayFinalize +}; +void runCwSwitchDelaySetting(){runSetting(&ssCwSwitchDelay);} void formatKeyerEnum(char* output, const KeyerMode_e mode) { @@ -461,7 +463,7 @@ const MenuItem_t cwMenu [] PROGMEM { {MT_CW,nullptr},//Title {MI_CW_SPEED,setupCwSpeed}, {MI_CW_TONE,runToneSetting}, - {MI_CW_DELAY,setupCwDelay}, + {MI_CW_DELAY,runCwSwitchDelaySetting}, {MI_CW_KEYER,setupKeyer}, }; void runCwMenu(){RUN_MENU(cwMenu);} From 9af0c1c965b1336b2356393e6e34a5f0074e9869 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 19:50:11 -0800 Subject: [PATCH 069/324] Refactor keyer setting into new menu style --- setup.cpp | 69 ++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/setup.cpp b/setup.cpp index 994d589..6bfdec8 100644 --- a/setup.cpp +++ b/setup.cpp @@ -294,50 +294,45 @@ const SettingScreen_t ssCwSwitchDelay PROGMEM = { }; void runCwSwitchDelaySetting(){runSetting(&ssCwSwitchDelay);} -void formatKeyerEnum(char* output, const KeyerMode_e mode) +//CW Keyer +void ssKeyerInitialize(long int* start_value_out) { - if(KeyerMode_e::KEYER_STRAIGHT == mode){ - strcpy_P(output,(const char*)F("< Hand Key >")); + *start_value_out = globalSettings.keyerMode; +} +void ssKeyerValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,KeyerMode_e::KEYER_STRAIGHT,KeyerMode_e::KEYER_IAMBIC_B); +} +void ssKeyerChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + if(KeyerMode_e::KEYER_STRAIGHT == new_value){ + strncpy_P(buff_out,(const char*)F("< Hand Key >"),buff_out_size); } - else if(KeyerMode_e::KEYER_IAMBIC_A == mode){ - strcpy_P(output,(const char*)F("< Iambic A >")); + else if(KeyerMode_e::KEYER_IAMBIC_A == new_value){ + strncpy_P(buff_out,(const char*)F("< Iambic A >"),buff_out_size); } else{ - strcpy_P(output,(const char*)F("< Iambic B >")); + strncpy_P(buff_out,(const char*)F("< Iambic B >"),buff_out_size); } } - -void setupKeyer(){ - //displayDialog(F("Set CW Keyer"),F("Press tune to Save")); - - int knob = 0; - uint32_t tmp_mode = globalSettings.keyerMode; - formatKeyerEnum(c, tmp_mode); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - - while (!btnDown()) - { - knob = enc_read(); - if(knob == 0){ - active_delay(50); - continue; - } - if(knob < 0 && tmp_mode > KeyerMode_e::KEYER_STRAIGHT){ - tmp_mode--; - } - if(knob > 0 && tmp_mode < KeyerMode_e::KEYER_IAMBIC_B){ - tmp_mode++; - } - - formatKeyerEnum(c,tmp_mode); - displayText(c, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - } - - active_delay(500); - - globalSettings.keyerMode = tmp_mode; +void ssKeyerFinalize(const long int final_value) +{ + globalSettings.keyerMode = final_value; SaveSettingsToEeprom(); } +const char SS_KEYER_T [] PROGMEM = "Set CW Keyer Type"; +const char SS_KEYER_A [] PROGMEM = "Select which type of\nkeyer/paddle is being used"; +const SettingScreen_t ssKeyer PROGMEM = { + SS_KEYER_T, + SS_KEYER_A, + 10, + 1, + ssKeyerInitialize, + ssKeyerValidate, + ssKeyerChange, + ssKeyerFinalize +}; +void runKeyerSetting(){runSetting(&ssKeyer);} void setupCwSpeed() { @@ -464,7 +459,7 @@ const MenuItem_t cwMenu [] PROGMEM { {MI_CW_SPEED,setupCwSpeed}, {MI_CW_TONE,runToneSetting}, {MI_CW_DELAY,runCwSwitchDelaySetting}, - {MI_CW_KEYER,setupKeyer}, + {MI_CW_KEYER,runKeyerSetting}, }; void runCwMenu(){RUN_MENU(cwMenu);} From 4265d56d327337094195c59fa0c8c2fe2d6e90af Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 19:50:54 -0800 Subject: [PATCH 070/324] Remove unused setupCwTone --- setup.cpp | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/setup.cpp b/setup.cpp index 6bfdec8..cea0064 100644 --- a/setup.cpp +++ b/setup.cpp @@ -361,32 +361,6 @@ void setupCwSpeed() SaveSettingsToEeprom(); } -void setupCwTone(){ - //displayDialog(F("Set CW Tone (Hz)"),F("Press tune to Save")); - - tone(CW_TONE, globalSettings.cwSideToneFreq); - itoa(globalSettings.cwSideToneFreq, b, 10); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - - while(!btnDown()){ - int knob = enc_read(); - - if (knob > 0 && globalSettings.cwSideToneFreq < 2000) - globalSettings.cwSideToneFreq += 10; - else if (knob < 0 && globalSettings.cwSideToneFreq > 100 ) - globalSettings.cwSideToneFreq -= 10; - else - continue; //don't update the frequency or the display - - tone(CW_TONE, globalSettings.cwSideToneFreq); - itoa(globalSettings.cwSideToneFreq, b, 10); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - } - noTone(CW_TONE); - - SaveSettingsToEeprom(); -} - void setupResetAll() { //displayDialog(F("Reset all cals and settings?"),F("Press tune to Confirm")); From ece69fff3a6ea59f30d36fb0671c0c5129f30c45 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 20:15:01 -0800 Subject: [PATCH 071/324] Let morseText play back at any desired rate, not just the default one --- morse.cpp | 24 ++++++++---------------- morse.h | 4 ++-- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/morse.cpp b/morse.cpp index 2afaeaa..20a1020 100644 --- a/morse.cpp +++ b/morse.cpp @@ -56,12 +56,12 @@ static const PROGMEM struct Morse morse_table[] = { {'?', 0x8c}, // 10001100 }; -static void morseLetter(char c){ +static void morseLetter(char c, uint16_t dit_duration_ms){ unsigned char mask = 0x80; //handle space character as three dashes if (c == ' '){ - active_delay(9 * globalSettings.cwDitDurationMs); + active_delay(7 * dit_duration_ms); //Serial.print(' '); return; } @@ -81,36 +81,28 @@ static void morseLetter(char c){ while(mask){ tone(CW_TONE, globalSettings.cwSideToneFreq,10000); if (mask & code){ - delay(3 * globalSettings.cwDitDurationMs); + delay(3 * dit_duration_ms); //Serial.print('-'); } else{ - delay(globalSettings.cwDitDurationMs); + delay(dit_duration_ms); //Serial.print('.'); } //Serial.print('#'); noTone(CW_TONE); - delay(globalSettings.cwDitDurationMs); // space between dots and dashes + delay(dit_duration_ms); // space between dots and dashes mask = mask >> 1; } //Serial.println('@'); - delay(2*globalSettings.cwDitDurationMs); // space between letters is a dash (3 dots), one dot's space has already been sent + delay(2*dit_duration_ms); // space between letters is a dash (3 dots), one dot's space has already been sent break;//We've played the letter, so don't bother checking the rest of the list } } } -void morseText(char *text){ -// while (1){ - noTone(CW_TONE); - delay(1000); - tone(CW_TONE, 600); - delay(1000); -// } - - //Serial.println(globalSettings.cwSideToneFreq); +void morseText(char *text, uint16_t dit_duration_ms){ while(*text){ - morseLetter(*text++); + morseLetter(*text++, dit_duration_ms); } } diff --git a/morse.h b/morse.h index 9c2de08..5e7d76f 100644 --- a/morse.h +++ b/morse.h @@ -1,3 +1,3 @@ +#include "settings.h" //sends out morse code at the speed set by cwSpeed -extern int cwSpeed; //this is actuall the dot period in milliseconds -void morseText(char *text); +void morseText(char *text, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); From 850cda59e45dfd1fed0ccd7875e2862d9aa5b31a Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 20:20:03 -0800 Subject: [PATCH 072/324] Refactor cw play speed setting --- setup.cpp | 53 +++++++++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/setup.cpp b/setup.cpp index cea0064..747c299 100644 --- a/setup.cpp +++ b/setup.cpp @@ -334,32 +334,37 @@ const SettingScreen_t ssKeyer PROGMEM = { }; void runKeyerSetting(){runSetting(&ssKeyer);} -void setupCwSpeed() +//CW Speed +void ssCwSpeedInitialize(long int* start_value_out) { - //displayDialog(F("Set CW Speed (WPM)"),F("Press tune to Save")); - - unsigned int wpm = 1200/globalSettings.cwDitDurationMs; - - itoa(wpm, b, 10); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - - while (!btnDown()){ - int knob = enc_read(); - - if (knob < 0 && wpm > 1) - --wpm; - else if (knob > 0 && wpm < 100) - ++wpm; - else - continue;//don't update the frequency or the display - - itoa(wpm, b, 10); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - } - - globalSettings.cwDitDurationMs = 1200/wpm; + *start_value_out = 1200L/globalSettings.cwDitDurationMs; +} +void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,1,100); +} +void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + ltoa(new_value, buff_out, 10); +} +void ssCwSpeedFinalize(const long int final_value) +{ + globalSettings.cwDitDurationMs = 1200L/final_value; SaveSettingsToEeprom(); } +const char SS_CW_SPEED_T [] PROGMEM = "Set CW Speed"; +const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters"; +const SettingScreen_t ssCwSpeed PROGMEM = { + SS_CW_SPEED_T, + SS_CW_SPEED_A, + 5, + 1, + ssCwSpeedInitialize, + ssCwSpeedValidate, + ssCwSpeedChange, + ssCwSpeedFinalize +}; +void runCwSpeedSetting(){runSetting(&ssCwSpeed);} void setupResetAll() { @@ -430,7 +435,7 @@ const char MI_CW_DELAY [] PROGMEM = "Tx/Rx Switching Delay"; const char MI_CW_KEYER [] PROGMEM = "Keyer Type"; const MenuItem_t cwMenu [] PROGMEM { {MT_CW,nullptr},//Title - {MI_CW_SPEED,setupCwSpeed}, + {MI_CW_SPEED,runCwSpeedSetting}, {MI_CW_TONE,runToneSetting}, {MI_CW_DELAY,runCwSwitchDelaySetting}, {MI_CW_KEYER,runKeyerSetting}, From d032664620332bac4e6948df609d7af00bc1e794 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 20:21:51 -0800 Subject: [PATCH 073/324] Re-order cw settings to match the menu --- setup.cpp | 64 +++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/setup.cpp b/setup.cpp index 747c299..7ffda75 100644 --- a/setup.cpp +++ b/setup.cpp @@ -225,6 +225,38 @@ const SettingScreen_t ssBfo PROGMEM = { }; void runBfoSetting(){runSetting(&ssBfo);} +//CW Speed +void ssCwSpeedInitialize(long int* start_value_out) +{ + *start_value_out = 1200L/globalSettings.cwDitDurationMs; +} +void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,1,100); +} +void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + ltoa(new_value, buff_out, 10); +} +void ssCwSpeedFinalize(const long int final_value) +{ + globalSettings.cwDitDurationMs = 1200L/final_value; + SaveSettingsToEeprom(); +} +const char SS_CW_SPEED_T [] PROGMEM = "Set CW Speed"; +const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters"; +const SettingScreen_t ssCwSpeed PROGMEM = { + SS_CW_SPEED_T, + SS_CW_SPEED_A, + 5, + 1, + ssCwSpeedInitialize, + ssCwSpeedValidate, + ssCwSpeedChange, + ssCwSpeedFinalize +}; +void runCwSpeedSetting(){runSetting(&ssCwSpeed);} + //CW Tone void ssCwToneInitialize(long int* start_value_out) { @@ -334,38 +366,6 @@ const SettingScreen_t ssKeyer PROGMEM = { }; void runKeyerSetting(){runSetting(&ssKeyer);} -//CW Speed -void ssCwSpeedInitialize(long int* start_value_out) -{ - *start_value_out = 1200L/globalSettings.cwDitDurationMs; -} -void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_value_out) -{ - *validated_value_out = LIMIT(candidate_value_in,1,100); -} -void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t buff_out_size) -{ - ltoa(new_value, buff_out, 10); -} -void ssCwSpeedFinalize(const long int final_value) -{ - globalSettings.cwDitDurationMs = 1200L/final_value; - SaveSettingsToEeprom(); -} -const char SS_CW_SPEED_T [] PROGMEM = "Set CW Speed"; -const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters"; -const SettingScreen_t ssCwSpeed PROGMEM = { - SS_CW_SPEED_T, - SS_CW_SPEED_A, - 5, - 1, - ssCwSpeedInitialize, - ssCwSpeedValidate, - ssCwSpeedChange, - ssCwSpeedFinalize -}; -void runCwSpeedSetting(){runSetting(&ssCwSpeed);} - void setupResetAll() { //displayDialog(F("Reset all cals and settings?"),F("Press tune to Confirm")); From 6d5fb97c62fbdd1522d506c915ef57f80cd1a413 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 20:35:43 -0800 Subject: [PATCH 074/324] Refactor reset-all setting --- setup.cpp | 67 ++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/setup.cpp b/setup.cpp index 7ffda75..7a1b058 100644 --- a/setup.cpp +++ b/setup.cpp @@ -366,47 +366,45 @@ const SettingScreen_t ssKeyer PROGMEM = { }; void runKeyerSetting(){runSetting(&ssKeyer);} -void setupResetAll() +//Reset all settings +void ssResetAllInitialize(long int* start_value_out) { - //displayDialog(F("Reset all cals and settings?"),F("Press tune to Confirm")); - strncpy_P(b,(const char*)F("No"),sizeof(b)); - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); - - bool reset_all = false; - while(!btnDown()){ - int knob = enc_read(); - - if(knob > 0){ - reset_all = true; - } - else if(knob < 0){ - reset_all = false; - } - else{ - continue; - } - - if(reset_all){ - strncpy_P(b,(const char*)F("Yes"),sizeof(b)); - } - else{ - strncpy_P(b,(const char*)F("No"),sizeof(b)); - } - - displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND); + *start_value_out = 0;//Default to NOT resetting +} +void ssResetAllValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,0,1); +} +void ssResetAllChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + if(new_value){ + strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size); } - - while(btnDown()){ - active_delay(50); + else{ + strncpy_P(buff_out,(const char*)F("No"),buff_out_size); } - active_delay(50); - - if(reset_all){ +} +void ssResetAllFinalize(const long int final_value) +{ + if(final_value){ LoadDefaultSettings(); SaveSettingsToEeprom(); setup(); } } +const char SS_RESET_ALL_T [] PROGMEM = "Reset All Cals/Settings"; +const char SS_RESET_ALL_A [] PROGMEM = "WARNING: Selecting \"Yes\"\nwill reset all calibrations and\nsettings to their default\nvalues"; +const SettingScreen_t ssResetAll PROGMEM = { + SS_RESET_ALL_T, + SS_RESET_ALL_A, + 20, + 1, + ssResetAllInitialize, + ssResetAllValidate, + ssResetAllChange, + ssResetAllFinalize +}; +void runResetAllSetting(){runSetting(&ssResetAll);} struct MenuItem_t { const char* const ItemName; @@ -443,12 +441,11 @@ const MenuItem_t cwMenu [] PROGMEM { void runCwMenu(){RUN_MENU(cwMenu);} const char MT_SETTINGS [] PROGMEM = "Settings"; -const char MI_RESET [] PROGMEM = "Reset all Cals/Settings"; const MenuItem_t mainMenu [] PROGMEM { {MT_SETTINGS,nullptr},//Title {MT_CAL,runCalibrationMenu}, {MT_CW,runCwMenu}, - {MI_RESET,setupResetAll}, + {SS_RESET_ALL_T,runResetAllSetting}, }; const char MI_EXIT [] PROGMEM = "Exit"; From dd3a6162afa5647d1e1c49cff05d6a37ae9d7502 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 20:42:44 -0800 Subject: [PATCH 075/324] Set global setting so that setFrequency will work correctly --- setup.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/setup.cpp b/setup.cpp index 7a1b058..c011018 100644 --- a/setup.cpp +++ b/setup.cpp @@ -199,8 +199,9 @@ void ssBfoValidate(const long int candidate_value_in, long int* validated_value_ } void ssBfoChange(const long int new_value, char* buff_out, const size_t buff_out_size) { - si5351bx_setfreq(0, new_value); + globalSettings.usbCarrierFreq = new_value; setFrequency(GetActiveVfoFreq()); + si5351bx_setfreq(0, new_value); formatFreq(new_value,buff_out,buff_out_size); strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); } From 1f033b6af4e5c56c30f6f0ebfff775ae6781c85f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 20:51:19 -0800 Subject: [PATCH 076/324] Save 102 progmem bytes by de-duping strings --- setup.cpp | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/setup.cpp b/setup.cpp index c011018..14272f7 100644 --- a/setup.cpp +++ b/setup.cpp @@ -174,7 +174,7 @@ void ssLocalOscFinalize(const long int final_value) si5351_set_calibration(globalSettings.oscillatorCal); setFrequency(GetActiveVfoFreq()); } -const char SS_LOCAL_OSC_T [] PROGMEM = "Set Local Osc Calibration"; +const char SS_LOCAL_OSC_T [] PROGMEM = "Local Oscillator"; const char SS_LOCAL_OSC_A [] PROGMEM = "Exit menu, tune so that the\ndial displays the desired freq,\nthen tune here until the\nsignal is zerobeat"; const SettingScreen_t ssLocalOsc PROGMEM = { SS_LOCAL_OSC_T, @@ -212,7 +212,7 @@ void ssBfoFinalize(const long int final_value) si5351bx_setfreq(0, globalSettings.usbCarrierFreq); setFrequency(GetActiveVfoFreq()); } -const char SS_BFO_T [] PROGMEM = "Set BFO Calibration"; +const char SS_BFO_T [] PROGMEM = "Beat Frequency Osc (BFO)"; const char SS_BFO_A [] PROGMEM = "Exit menu, tune to an unused\nfrequency, then tune here\nuntil the audio is between\n300-3000Hz"; const SettingScreen_t ssBfo PROGMEM = { SS_BFO_T, @@ -244,7 +244,7 @@ void ssCwSpeedFinalize(const long int final_value) globalSettings.cwDitDurationMs = 1200L/final_value; SaveSettingsToEeprom(); } -const char SS_CW_SPEED_T [] PROGMEM = "Set CW Speed"; +const char SS_CW_SPEED_T [] PROGMEM = "CW Play Speed"; const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters"; const SettingScreen_t ssCwSpeed PROGMEM = { SS_CW_SPEED_T, @@ -280,7 +280,7 @@ void ssCwToneFinalize(const long int final_value) globalSettings.cwSideToneFreq = final_value; SaveSettingsToEeprom(); } -const char SS_CW_TONE_T [] PROGMEM = "Set CW Tone"; +const char SS_CW_TONE_T [] PROGMEM = "CW Tone Frequency"; const char SS_CW_TONE_A [] PROGMEM = "Select a frequency that\nCW mode to tune for"; const SettingScreen_t ssTone PROGMEM = { SS_CW_TONE_T, @@ -313,7 +313,7 @@ void ssCwSwitchDelayFinalize(const long int final_value) globalSettings.cwActiveTimeoutMs = final_value; SaveSettingsToEeprom(); } -const char SS_CW_SWITCH_T [] PROGMEM = "Set CW Tx/Rx Switch Delay"; +const char SS_CW_SWITCH_T [] PROGMEM = "CW Tx -> Rx Switch Delay"; const char SS_CW_SWITCH_A [] PROGMEM = "Select how long the radio\nshould wait before switching\nbetween TX and RX when in\nCW mode"; const SettingScreen_t ssCwSwitchDelay PROGMEM = { SS_CW_SWITCH_T, @@ -353,7 +353,7 @@ void ssKeyerFinalize(const long int final_value) globalSettings.keyerMode = final_value; SaveSettingsToEeprom(); } -const char SS_KEYER_T [] PROGMEM = "Set CW Keyer Type"; +const char SS_KEYER_T [] PROGMEM = "CW Keyer/Paddle Type"; const char SS_KEYER_A [] PROGMEM = "Select which type of\nkeyer/paddle is being used"; const SettingScreen_t ssKeyer PROGMEM = { SS_KEYER_T, @@ -416,28 +416,22 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); #define RUN_MENU(menu) runMenu(menu,sizeof(menu)/sizeof(menu[0])) const char MT_CAL [] PROGMEM = "Calibrations"; -const char MI_SET_FREQ [] PROGMEM = "Local Oscillator"; -const char MI_SET_BFO [] PROGMEM = "Beat Frequency Osc (BFO)"; const char MI_TOUCH [] PROGMEM = "Touch Screen"; const MenuItem_t calibrationMenu [] PROGMEM { {MT_CAL,nullptr},//Title - {MI_SET_FREQ,runLocalOscSetting}, - {MI_SET_BFO,runBfoSetting}, + {SS_LOCAL_OSC_T,runLocalOscSetting}, + {SS_BFO_T,runBfoSetting}, {MI_TOUCH,setupTouch}, }; void runCalibrationMenu(){RUN_MENU(calibrationMenu);} const char MT_CW [] PROGMEM = "CW/Morse Setup"; -const char MI_CW_SPEED [] PROGMEM = "Play Speed (WPM)"; -const char MI_CW_TONE [] PROGMEM = "Tone Frequency"; -const char MI_CW_DELAY [] PROGMEM = "Tx/Rx Switching Delay"; -const char MI_CW_KEYER [] PROGMEM = "Keyer Type"; const MenuItem_t cwMenu [] PROGMEM { {MT_CW,nullptr},//Title - {MI_CW_SPEED,runCwSpeedSetting}, - {MI_CW_TONE,runToneSetting}, - {MI_CW_DELAY,runCwSwitchDelaySetting}, - {MI_CW_KEYER,runKeyerSetting}, + {SS_CW_SPEED_T,runCwSpeedSetting}, + {SS_CW_TONE_T,runToneSetting}, + {SS_CW_SWITCH_T,runCwSwitchDelaySetting}, + {SS_KEYER_T,runKeyerSetting}, }; void runCwMenu(){RUN_MENU(cwMenu);} From 9fb4efc5ace02192df7287cdbe567056fe25e1fe Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 22:49:59 -0800 Subject: [PATCH 077/324] Move encoder functions to their own file --- encoder.cpp | 72 ++++++++++++++++++++++++++ encoder.h | 4 ++ ubitx_ui.cpp | 142 --------------------------------------------------- 3 files changed, 76 insertions(+), 142 deletions(-) create mode 100644 encoder.cpp create mode 100644 encoder.h diff --git a/encoder.cpp b/encoder.cpp new file mode 100644 index 0000000..c5bc049 --- /dev/null +++ b/encoder.cpp @@ -0,0 +1,72 @@ +/* + * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. + */ +int8_t enc_count; +uint8_t prev_enc; + +uint8_t enc_state (void) { + return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0); +} + +/* + * The Interrupt Service Routine for Pin Change Interrupts on A0-A5. + */ +ISR (PCINT1_vect) { + uint8_t cur_enc = enc_state(); + if (prev_enc == cur_enc) { + //Serial.println("unnecessary ISR"); + return; + } + //Serial.print(prev_enc); + //Serial.println(cur_enc); + + //these transitions point to the enccoder being rotated anti-clockwise + if ((prev_enc == 0 && cur_enc == 2) || + (prev_enc == 2 && cur_enc == 3) || + (prev_enc == 3 && cur_enc == 1) || + (prev_enc == 1 && cur_enc == 0)) + { + enc_count-=1; + } + //these transitions point to the enccoder being rotated clockwise + else if ((prev_enc == 0 && cur_enc == 1) || + (prev_enc == 1 && cur_enc == 3) || + (prev_enc == 3 && cur_enc == 2) || + (prev_enc == 2 && cur_enc == 0)) + { + enc_count+=1; + } + else { + // A change to two states, we can't tell whether it was forward or backward, so we skip it. + //Serial.println("skip"); + } + prev_enc = cur_enc; // Record state for next pulse interpretation +} + +/* + * Setup the encoder interrupts and global variables. + */ +void pci_setup(byte pin) { + *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin + PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt + PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group +} + +void enc_setup(void) +{ + enc_count = 0; + // This is already done in setup() ? + //pinMode(ENC_A, INPUT); + //pinMode(ENC_B, INPUT); + prev_enc = enc_state(); + + // Setup Pin Change Interrupts for the encoder inputs + pci_setup(ENC_A); + pci_setup(ENC_B); +} + +int enc_read(void) { + int8_t ret = enc_count; + enc_count = 0; + return int(ret); +} \ No newline at end of file diff --git a/encoder.h b/encoder.h new file mode 100644 index 0000000..5176684 --- /dev/null +++ b/encoder.h @@ -0,0 +1,4 @@ +#pragma once + +void enc_setup(void); +int enc_read(void); \ No newline at end of file diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 624705f..6f11eb7 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -541,148 +541,6 @@ void updateDisplay() { displayVFO(globalSettings.activeVfo); } - -/** - * The A7 And A6 are purely analog lines on the Arduino Nano - * These need to be pulled up externally using two 10 K resistors - * - * There are excellent pages on the Internet about how these encoders work - * and how they should be used. We have elected to use the simplest way - * to use these encoders without the complexity of interrupts etc to - * keep it understandable. - * - * The enc_state returns a two-bit number such that each bit reflects the current - * value of each of the two phases of the encoder - * - * The enc_read returns the number of net pulses counted over 50 msecs. - * If the puluses are -ve, they were anti-clockwise, if they are +ve, the - * were in the clockwise directions. Higher the pulses, greater the speed - * at which the enccoder was spun - */ - -/* -int enc_prev_state = 3; - -byte enc_state (void) { - //Serial.print(digitalRead(ENC_A)); Serial.print(":");Serial.println(digitalRead(ENC_B)); - return (digitalRead(ENC_A) == 1 ? 1 : 0) + (digitalRead(ENC_B) == 1 ? 2: 0); -} - - -int enc_read(void) { - int result = 0; - byte newState; - int enc_speed = 0; - - long stop_by = millis() + 200; - - while (millis() < stop_by) { // check if the previous state was stable - newState = enc_state(); // Get current state - -// if (newState != enc_prev_state) -// active_delay(20); - - if (enc_state() != newState || newState == enc_prev_state) - continue; - //these transitions point to the encoder being rotated anti-clockwise - if ((enc_prev_state == 0 && newState == 2) || - (enc_prev_state == 2 && newState == 3) || - (enc_prev_state == 3 && newState == 1) || - (enc_prev_state == 1 && newState == 0)){ - result--; - } - //these transitions point o the enccoder being rotated clockwise - if ((enc_prev_state == 0 && newState == 1) || - (enc_prev_state == 1 && newState == 3) || - (enc_prev_state == 3 && newState == 2) || - (enc_prev_state == 2 && newState == 0)){ - result++; - } - enc_prev_state = newState; // Record state for next pulse interpretation - enc_speed++; - active_delay(1); - } - //if (result) - // Serial.println(result); - return(result); -} -*/ - -/* - * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. - */ -int8_t enc_count; -uint8_t prev_enc; - -uint8_t enc_state (void) { - return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0); -} - -/* - * Setup the encoder interrupts and global variables. - */ -void pci_setup(byte pin) { - *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin - PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt - PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group -} - -void enc_setup(void) { - enc_count = 0; - // This is already done in setup() ? - //pinMode(ENC_A, INPUT); - //pinMode(ENC_B, INPUT); - prev_enc = enc_state(); - - // Setup Pin Change Interrupts for the encoder inputs - pci_setup(ENC_A); - pci_setup(ENC_B); -} - -/* - * The Interrupt Service Routine for Pin Change Interrupts on A0-A5. - */ -ISR (PCINT1_vect) { - uint8_t cur_enc = enc_state(); - if (prev_enc == cur_enc) { - //Serial.println("unnecessary ISR"); - return; - } - //Serial.print(prev_enc); - //Serial.println(cur_enc); - - //these transitions point to the enccoder being rotated anti-clockwise - if ((prev_enc == 0 && cur_enc == 2) || - (prev_enc == 2 && cur_enc == 3) || - (prev_enc == 3 && cur_enc == 1) || - (prev_enc == 1 && cur_enc == 0)) - { - enc_count-=1; - } - //these transitions point to the enccoder being rotated clockwise - else if ((prev_enc == 0 && cur_enc == 1) || - (prev_enc == 1 && cur_enc == 3) || - (prev_enc == 3 && cur_enc == 2) || - (prev_enc == 2 && cur_enc == 0)) - { - enc_count+=1; - } - else { - // A change to two states, we can't tell whether it was forward or backward, so we skip it. - //Serial.println("skip"); - } - prev_enc = cur_enc; // Record state for next pulse interpretation -} - -int enc_read(void) { - int8_t ret = enc_count; - enc_count = 0; - return int(ret); -} - - - - void ritToggle(struct Button *button){ if(!globalSettings.ritOn){ ritEnable(GetActiveVfoFreq()); From 755b2214f941b14faf2c17e92cd568841c6fc7c0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 22:53:00 -0800 Subject: [PATCH 078/324] Add missing includes to compile --- encoder.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/encoder.cpp b/encoder.cpp index c5bc049..5c994fc 100644 --- a/encoder.cpp +++ b/encoder.cpp @@ -1,3 +1,9 @@ +#include +#include + +#include "ubitx.h"//Pin definitions + + /* * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. */ From 4aea1b7126ab2c84c4e6590e32fed247e631041d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 19 Jan 2020 22:54:42 -0800 Subject: [PATCH 079/324] Slightly change centering. Appears to ride a tiny bit high because it leaves room for below-line characters, like gjpqy --- nano_gui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index 902f2ad..9efe8ec 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -238,7 +238,7 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr uint16_t height_out; tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out,w); x1 += (w - ( (int32_t)width_out + (x1_out-x1)))/2; - y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out + (y1_out-y1)))/2; + y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out))/2; displayRawText(text,x1,y1,w,color,background); } From 13f109c8b3b4149a37d6729d2d72e6d97219db83 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 01:13:36 -0800 Subject: [PATCH 080/324] First pass at a momentum function --- encoder.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++---------- encoder.h | 2 +- 2 files changed, 61 insertions(+), 14 deletions(-) diff --git a/encoder.cpp b/encoder.cpp index 5c994fc..9caa45c 100644 --- a/encoder.cpp +++ b/encoder.cpp @@ -1,23 +1,30 @@ #include #include +#include "encoder.h" #include "ubitx.h"//Pin definitions +//Normal encoder state +uint8_t prev_enc = 0; +int8_t enc_count = 0; -/* - * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. - */ -int8_t enc_count; -uint8_t prev_enc; +//Momentum encoder state +int16_t enc_count_periodic = 0; +int8_t momentum[3] = {0}; +static const uint16_t CALLBACK_PERIOD_MS = 200; +static const uint8_t MOMENTUM_MULTIPLIER = 1; -uint8_t enc_state (void) { - return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0); +uint8_t enc_state (void) +{ + return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0); } /* + * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. * The Interrupt Service Routine for Pin Change Interrupts on A0-A5. */ -ISR (PCINT1_vect) { +ISR (PCINT1_vect) +{ uint8_t cur_enc = enc_state(); if (prev_enc == cur_enc) { //Serial.println("unnecessary ISR"); @@ -32,7 +39,8 @@ ISR (PCINT1_vect) { (prev_enc == 3 && cur_enc == 1) || (prev_enc == 1 && cur_enc == 0)) { - enc_count-=1; + enc_count -= 1; + enc_count_periodic -= 1; } //these transitions point to the enccoder being rotated clockwise else if ((prev_enc == 0 && cur_enc == 1) || @@ -40,7 +48,8 @@ ISR (PCINT1_vect) { (prev_enc == 3 && cur_enc == 2) || (prev_enc == 2 && cur_enc == 0)) { - enc_count+=1; + enc_count += 1; + enc_count_periodic += 1; } else { // A change to two states, we can't tell whether it was forward or backward, so we skip it. @@ -69,10 +78,48 @@ void enc_setup(void) // Setup Pin Change Interrupts for the encoder inputs pci_setup(ENC_A); pci_setup(ENC_B); + + //Set up timer interrupt for momentum + TCCR1A = 0;//"normal" mode + TCCR1B = 3;//clock divider of 64 + TCNT1 = 0;//start counting at 0 + OCR1A = F_CPU * CALLBACK_PERIOD_MS / 1000 / 64;//set target number + TIMSK1 |= (1 << OCIE1A);//enable interrupt +} + +ISR(TIMER1_COMPA_vect) +{ + momentum[2] = momentum[1]; + momentum[1] = momentum[0]; + momentum[0] = enc_count_periodic; + enc_count_periodic = 0; +} + +int8_t min_momentum_mag() +{ + int8_t min_mag = 127; + for(uint8_t i = 0; i < sizeof(momentum)/sizeof(momentum[0]); ++i){ + int8_t mag = abs(momentum[i]); + if(mag < min_mag){ + min_mag = mag; + } + } + return min_mag; } int enc_read(void) { - int8_t ret = enc_count; - enc_count = 0; - return int(ret); + if(0 != enc_count){ + int16_t ret = enc_count; + int8_t s = (enc_count < 0) ? -1 : 1; + int8_t momentum_mag = min_momentum_mag(); + if(momentum_mag >= 20){ + ret += s*40; + } + else if(momentum_mag >= 5){ + ret += s*(20 + momentum_mag)/(20 - momentum_mag); + } + enc_count = 0; + return ret; + } + return 0; } \ No newline at end of file diff --git a/encoder.h b/encoder.h index 5176684..b3bd8a7 100644 --- a/encoder.h +++ b/encoder.h @@ -1,4 +1,4 @@ #pragma once void enc_setup(void); -int enc_read(void); \ No newline at end of file +int enc_read(void); From bbdd6840c908eacd97e3dbcf2d3c48c2f8dcc9f7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 01:37:09 -0800 Subject: [PATCH 081/324] Reduce setting step size, since momentum can get places faster --- setup.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.cpp b/setup.cpp index 14272f7..e933700 100644 --- a/setup.cpp +++ b/setup.cpp @@ -180,7 +180,7 @@ const SettingScreen_t ssLocalOsc PROGMEM = { SS_LOCAL_OSC_T, SS_LOCAL_OSC_A, 1, - 875, + 50, ssLocalOscInitialize, ssLocalOscValidate, ssLocalOscChange, @@ -286,7 +286,7 @@ const SettingScreen_t ssTone PROGMEM = { SS_CW_TONE_T, SS_CW_TONE_A, 1, - 10, + 1, ssCwToneInitialize, ssCwToneValidate, ssCwToneChange, @@ -319,7 +319,7 @@ const SettingScreen_t ssCwSwitchDelay PROGMEM = { SS_CW_SWITCH_T, SS_CW_SWITCH_A, 1, - 100, + 10, ssCwSwitchDelayInitialize, ssCwSwitchDelayValidate, ssCwSwitchDelayChange, From 3087830bfb0e9c56c651a00ebd0d9f0f395b7281 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 21:21:50 -0800 Subject: [PATCH 082/324] Expose single letter morse to other code areas --- morse.h | 1 + 1 file changed, 1 insertion(+) diff --git a/morse.h b/morse.h index 5e7d76f..c588783 100644 --- a/morse.h +++ b/morse.h @@ -1,3 +1,4 @@ #include "settings.h" //sends out morse code at the speed set by cwSpeed +void morseLetter(char c, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); void morseText(char *text, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); From 88d16bb073fa5fe64cde0888075f76b8e34ab1ea Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 21:30:18 -0800 Subject: [PATCH 083/324] Add morse playback of main menu --- ubitx_ui.cpp | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 624705f..ac1ef2c 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -347,7 +347,7 @@ void fastTune(){ //if the btn is down, wait until it is up while(btnDown()) active_delay(50); - active_delay(300); + active_delay(50); strncpy_P(c,(const char*)F("Fast tune"),sizeof(c)); displayText(c, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); @@ -361,7 +361,7 @@ void fastTune(){ //wait until the button is realsed and then return while(btnDown()) active_delay(50); - active_delay(300); + active_delay(50); return; } @@ -390,12 +390,22 @@ void enterFreq(){ btnDraw(&button); } + while(btnDown()) + active_delay(50); + active_delay(50); + int cursor_pos = 0; memset(c, 0, sizeof(c)); while(1){ checkCAT(); + if(btnDown()){ + while(btnDown()) + active_delay(50); + active_delay(50); + break; + } if(!readTouch()) continue; @@ -427,8 +437,6 @@ void enterFreq(){ } saveVFOs(); } - guiUpdate(); - return; break; } @@ -443,8 +451,6 @@ void enterFreq(){ } case KEYS_CANCEL: { - guiUpdate(); - return; break; } case KEYS_0: @@ -478,6 +484,9 @@ void enterFreq(){ while(readTouch()) checkCAT(); } // end of event loop : while(1) + + guiUpdate(); + enc_read();//clear out any tuner turning that happened during entry } void drawCWStatus(){ @@ -961,12 +970,13 @@ void doCommands(){ active_delay(50); active_delay(50); //debounce + Button button; + memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); + morseLetter(button.morse); + while (true){ //check if the knob's button was pressed if (btnDown()){ - Button button; - memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); - doCommand(&button); //unfocus the buttons @@ -999,11 +1009,14 @@ void doCommands(){ if (prev_button == select / 10) continue; - - //we are on a new button - drawFocus(prev_button, COLOR_INACTIVE_BORDER); - drawFocus(select/10, COLOR_ACTIVE_BORDER); - prev_button = select/10; + + //we are on a new button + drawFocus(prev_button, COLOR_INACTIVE_BORDER); + drawFocus(select/10, COLOR_ACTIVE_BORDER); + memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); + morseLetter(button.morse); + enc_read();//Clear any rotation that was done while the letter was playing + prev_button = select/10; } // guiUpdate(); From b0193ca7626a17f4e31f5a9d55e19c6e5c843a30 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 22:06:37 -0800 Subject: [PATCH 084/324] Add option to turn on and off morse menu playback --- settings.cpp | 15 +++++++++++---- settings.h | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/settings.cpp b/settings.cpp index 2c395a1..fa08499 100644 --- a/settings.cpp +++ b/settings.cpp @@ -20,10 +20,11 @@ static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_X = 32;//int16_t static const uint16_t EEPROM_ADDR_TOUCH_SLOPE_Y = 36;//int16_t static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_X = 40;//int16_t static const uint16_t EEPROM_ADDR_TOUCH_OFFSET_Y = 44;//int16_t -static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48; -static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256; -static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257; -static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358; +static const uint16_t EEPROM_ADDR_MORSE_MENU = 46;//uint8_t +static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48;//uint16_t +static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256;//uint8_t +static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257;//uint8_t +static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358;//uint8_t template bool LoadSane(T& dest,uint16_t addr, T min, T max) @@ -81,6 +82,7 @@ void LoadDefaultSettings() globalSettings.txActive = false; globalSettings.txCatActive = false; globalSettings.cwExpirationTimeMs = 0; + globalSettings.morseMenuOn = false; } void LoadSettingsFromEeprom() @@ -97,6 +99,10 @@ void LoadSettingsFromEeprom() LoadSane(globalSettings.vfoB.mode,EEPROM_ADDR_VFO_B_MODE,VFO_MODE_LSB,VFO_MODE_USB); LoadSane(globalSettings.keyerMode,EEPROM_ADDR_CW_KEY_TYPE,KEYER_STRAIGHT,KEYER_IAMBIC_B); + uint8_t morse_on; + LoadSane(morse_on,EEPROM_ADDR_MORSE_MENU,(uint8_t)0,(uint8_t)1); + globalSettings.morseMenuOn = morse_on; + //No sanity check on these - cal your heart out EEPROM.get(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal); EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX); @@ -122,6 +128,7 @@ void SaveSettingsToEeprom() EEPROM.put(EEPROM_ADDR_VFO_A_MODE,globalSettings.vfoA.mode); EEPROM.put(EEPROM_ADDR_VFO_B_MODE,globalSettings.vfoB.mode); EEPROM.put(EEPROM_ADDR_CW_KEY_TYPE,globalSettings.keyerMode); + EEPROM.put(EEPROM_ADDR_MORSE_MENU,(uint8_t)globalSettings.morseMenuOn); } uint32_t GetActiveVfoFreq() diff --git a/settings.h b/settings.h index efd90ba..a87f08f 100644 --- a/settings.h +++ b/settings.h @@ -97,6 +97,7 @@ struct SettingsRam bool txActive; bool txCatActive; uint32_t cwExpirationTimeMs; + bool morseMenuOn; }; //This is the shared declaration From 1c099663fc36147512d1149636a663cf23d8179f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 22:07:11 -0800 Subject: [PATCH 085/324] Have morseLetter respect global playback setting --- morse.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/morse.cpp b/morse.cpp index 20a1020..babbdaa 100644 --- a/morse.cpp +++ b/morse.cpp @@ -57,6 +57,9 @@ static const PROGMEM struct Morse morse_table[] = { }; static void morseLetter(char c, uint16_t dit_duration_ms){ + if(!globalSettings.morseMenuOn){ + return; + } unsigned char mask = 0x80; //handle space character as three dashes From edbb17e4c46cb2ae14c6f249cee7b81937458099 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 22:59:48 -0800 Subject: [PATCH 086/324] Fix keypad frequency entry code --- ubitx_ui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index ac1ef2c..dd5a8f3 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -397,7 +397,8 @@ void enterFreq(){ int cursor_pos = 0; memset(c, 0, sizeof(c)); - while(1){ + bool exit = false; + while(!exit){ checkCAT(); if(btnDown()){ @@ -437,6 +438,7 @@ void enterFreq(){ } saveVFOs(); } + exit = true; break; } @@ -451,6 +453,7 @@ void enterFreq(){ } case KEYS_CANCEL: { + exit = true; break; } case KEYS_0: @@ -483,7 +486,7 @@ void enterFreq(){ active_delay(300); while(readTouch()) checkCAT(); - } // end of event loop : while(1) + } // end of event loop : while(!exit) guiUpdate(); enc_read();//clear out any tuner turning that happened during entry From d854a51184c3e917cda53141334cab23784c5b67 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 23:17:47 -0800 Subject: [PATCH 087/324] Add start and end of transmission to morse list --- morse.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/morse.cpp b/morse.cpp index babbdaa..0999723 100644 --- a/morse.cpp +++ b/morse.cpp @@ -54,6 +54,8 @@ static const PROGMEM struct Morse morse_table[] = { {'.', 0x95}, // 10010101 {',', 0xb3}, // 10110011 {'?', 0x8c}, // 10001100 +{ 2 , 0xd5}, // 11010101 ASCII 0x02 is Start of Text - +{ 4 , 0x85}, // 10000101 ASCII 0x04 is End of Transmission - is too long for our encoding scheme in 8 bits, but fits }; static void morseLetter(char c, uint16_t dit_duration_ms){ From a9e73bb10286aeb12ce6fbefc83bf438dfc0ea46 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 23:19:00 -0800 Subject: [PATCH 088/324] Instead of having long press of tuner enter menu, have it turn on morse menu readout mode instead --- ubitx_v6.3.1_code.ino | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 617977e..184bd91 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -30,10 +30,11 @@ * Si5351 object to control the clocks. */ #include +#include "morse.h" +#include "nano_gui.h" #include "settings.h" #include "setup.h" #include "ubitx.h" -#include "nano_gui.h" /** * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. @@ -65,8 +66,6 @@ unsigned char doingCAT = 0; void active_delay(int delay_by){ unsigned long timeStart = millis(); while (millis() - timeStart <= (unsigned long)delay_by) { - delay(10); - //Background Work checkCAT(); } } @@ -322,13 +321,20 @@ void checkButton(){ active_delay(10); downTime++; if (downTime > 300){ - doSetup2(); + if(!globalSettings.morseMenuOn){ + globalSettings.morseMenuOn = true;//set before playing + morseLetter(2); + } + else{ + morseLetter(4); + globalSettings.morseMenuOn = false;//unset after playing + } + SaveSettingsToEeprom(); return; } - } - active_delay(100); + } + active_delay(100); - doCommands(); //wait for the button to go up again while(btnDown()) From 418acf644b60e0f17478855164c99a786f2935ef Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 23:53:09 -0800 Subject: [PATCH 089/324] Fix morse encoding for 'y' --- morse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/morse.cpp b/morse.cpp index 0999723..5b962bb 100644 --- a/morse.cpp +++ b/morse.cpp @@ -39,7 +39,7 @@ static const PROGMEM struct Morse morse_table[] = { {'v', 0xe1}, // 11100001 {'w', 0xf3}, // 11110011 {'x', 0xe9}, // 11101001 -{'y', 0xe3}, // 11101011 +{'y', 0xeb}, // 11101011 {'z', 0xec}, // 11101100 {'1', 0xcf}, // 11001111 {'2', 0xc7}, // 11000111 From 13df195efcc1bec399f9aca8aed0778d39e9539e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Jan 2020 23:54:42 -0800 Subject: [PATCH 090/324] Replace morse table with direct binary values so that there can't be mis-translations of the hex --- morse.cpp | 82 +++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/morse.cpp b/morse.cpp index 5b962bb..c44cb81 100644 --- a/morse.cpp +++ b/morse.cpp @@ -15,47 +15,47 @@ struct Morse { * The first zero after the 1s indicates the start of the letter, it MUST be discarded */ static const PROGMEM struct Morse morse_table[] = { -{'a', 0xf9}, // 11111001 -{'b', 0xe8}, // 11101000 -{'c', 0xea}, // 11101010 -{'d', 0xf4}, // 11110100 -{'e', 0xfc}, // 11111100 -{'f', 0xe2}, // 11100010 -{'g', 0xf6}, // 11110110 -{'h', 0xe0}, // 11100000 -{'i', 0xf8}, // 11111000 -{'j', 0xe7}, // 11100111 -{'k', 0xf6}, // 11110101 -{'l', 0xe4}, // 11100100 -{'m', 0xfb}, // 11111011 -{'n', 0xfa}, // 11111010 -{'o', 0xf7}, // 11110111 -{'p', 0xe6}, // 11100110 -{'q', 0xed}, // 11101101 -{'r', 0xf2}, // 11110010 -{'s', 0xf0}, // 11110000 -{'t', 0xfd}, // 11111101 -{'u', 0xf1}, // 11110001 -{'v', 0xe1}, // 11100001 -{'w', 0xf3}, // 11110011 -{'x', 0xe9}, // 11101001 -{'y', 0xeb}, // 11101011 -{'z', 0xec}, // 11101100 -{'1', 0xcf}, // 11001111 -{'2', 0xc7}, // 11000111 -{'3', 0xc3}, // 11000011 -{'4', 0xc1}, // 11000001 -{'5', 0xc0}, // 11000000 -{'6', 0xd0}, // 11010000 -{'7', 0xd8}, // 11011000 -{'8', 0xdc}, // 11011100 -{'9', 0xde}, // 11011110 -{'0', 0xdf}, // 11011111 -{'.', 0x95}, // 10010101 -{',', 0xb3}, // 10110011 -{'?', 0x8c}, // 10001100 -{ 2 , 0xd5}, // 11010101 ASCII 0x02 is Start of Text - -{ 4 , 0x85}, // 10000101 ASCII 0x04 is End of Transmission - is too long for our encoding scheme in 8 bits, but fits +{'a', 0b11111001}, +{'b', 0b11101000}, +{'c', 0b11101010}, +{'d', 0b11110100}, +{'e', 0b11111100}, +{'f', 0b11100010}, +{'g', 0b11110110}, +{'h', 0b11100000}, +{'i', 0b11111000}, +{'j', 0b11100111}, +{'k', 0b11110101}, +{'l', 0b11100100}, +{'m', 0b11111011}, +{'n', 0b11111010}, +{'o', 0b11110111}, +{'p', 0b11100110}, +{'q', 0b11101101}, +{'r', 0b11110010}, +{'s', 0b11110000}, +{'t', 0b11111101}, +{'u', 0b11110001}, +{'v', 0b11100001}, +{'w', 0b11110011}, +{'x', 0b11101001}, +{'y', 0b11101011}, +{'z', 0b11101100}, +{'1', 0b11001111}, +{'2', 0b11000111}, +{'3', 0b11000011}, +{'4', 0b11000001}, +{'5', 0b11000000}, +{'6', 0b11010000}, +{'7', 0b11011000}, +{'8', 0b11011100}, +{'9', 0b11011110}, +{'0', 0b11011111}, +{'.', 0b10010101}, +{',', 0b10110011}, +{'?', 0b10001100}, +{ 2 , 0b11010101}, // ASCII 0x02 is Start of Text - +{ 4 , 0b10000101}, // ASCII 0x04 is End of Transmission - is too long for our encoding scheme in 8 bits, but fits }; static void morseLetter(char c, uint16_t dit_duration_ms){ From 70153f77d258a6b46cd023011fac37f32e205c06 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 22 Jan 2020 00:04:12 -0800 Subject: [PATCH 091/324] Add morse menu playback to setup --- setup.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 5 deletions(-) diff --git a/setup.cpp b/setup.cpp index 14272f7..9f0875b 100644 --- a/setup.cpp +++ b/setup.cpp @@ -238,6 +238,8 @@ void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_va void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t buff_out_size) { ltoa(new_value, buff_out, 10); + morseText(buff_out,1200L/new_value); + enc_read();//Consume any rotations during morse playback } void ssCwSpeedFinalize(const long int final_value) { @@ -307,6 +309,8 @@ void ssCwSwitchDelayChange(const long int new_value, char* buff_out, const size_ { ltoa(new_value,buff_out,10); strncat_P(buff_out,(const char*)F("ms"),buff_out_size - strlen(buff_out)); + morseText(buff_out); + enc_read();//Consume any rotations during morse playback } void ssCwSwitchDelayFinalize(const long int final_value) { @@ -338,15 +342,21 @@ void ssKeyerValidate(const long int candidate_value_in, long int* validated_valu } void ssKeyerChange(const long int new_value, char* buff_out, const size_t buff_out_size) { + char m; if(KeyerMode_e::KEYER_STRAIGHT == new_value){ - strncpy_P(buff_out,(const char*)F("< Hand Key >"),buff_out_size); + strncpy_P(buff_out,(const char*)F("Hand Key"),buff_out_size); + m = 'S'; } else if(KeyerMode_e::KEYER_IAMBIC_A == new_value){ - strncpy_P(buff_out,(const char*)F("< Iambic A >"),buff_out_size); + strncpy_P(buff_out,(const char*)F("Iambic A"),buff_out_size); + m = 'A'; } else{ - strncpy_P(buff_out,(const char*)F("< Iambic B >"),buff_out_size); + strncpy_P(buff_out,(const char*)F("Iambic B"),buff_out_size); + m = 'B'; } + morseLetter(m); + enc_read();//Consume any rotations during morse playback } void ssKeyerFinalize(const long int final_value) { @@ -378,12 +388,17 @@ void ssResetAllValidate(const long int candidate_value_in, long int* validated_v } void ssResetAllChange(const long int new_value, char* buff_out, const size_t buff_out_size) { + char m; if(new_value){ strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size); + m = 'Y'; } else{ strncpy_P(buff_out,(const char*)F("No"),buff_out_size); + m = 'N'; } + morseLetter(m); + enc_read();//Consume any rotations during morse playback } void ssResetAllFinalize(const long int final_value) { @@ -407,6 +422,48 @@ const SettingScreen_t ssResetAll PROGMEM = { }; void runResetAllSetting(){runSetting(&ssResetAll);} +//Morse menu playback +void ssMorseMenuInitialize(long int* start_value_out) +{ + *start_value_out = globalSettings.morseMenuOn; +} +void ssMorseMenuValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,0,1); +} +void ssMorseMenuChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + char m; + if(new_value){ + strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size); + m = 'Y'; + } + else{ + strncpy_P(buff_out,(const char*)F("No"),buff_out_size); + m = 'N'; + } + morseLetter(m); + enc_read();//Consume any rotations during morse playback +} +void ssMorseMenuFinalize(const long int final_value) +{ + globalSettings.morseMenuOn = final_value; + SaveSettingsToEeprom(); +} +const char SS_MORSE_MENU_T [] PROGMEM = "Morse Menu Play"; +const char SS_MORSE_MENU_A [] PROGMEM = "When on, menu selections\nwill play morse code"; +const SettingScreen_t ssMorseMenu PROGMEM = { + SS_MORSE_MENU_T, + SS_MORSE_MENU_A, + 10, + 1, + ssMorseMenuInitialize, + ssMorseMenuValidate, + ssMorseMenuChange, + ssMorseMenuFinalize +}; +void runMorseMenuSetting(){runSetting(&ssMorseMenu);} + struct MenuItem_t { const char* const ItemName; const void (*OnSelect)(); @@ -440,6 +497,7 @@ const MenuItem_t mainMenu [] PROGMEM { {MT_SETTINGS,nullptr},//Title {MT_CAL,runCalibrationMenu}, {MT_CW,runCwMenu}, + {SS_MORSE_MENU_T,runMorseMenuSetting}, {SS_RESET_ALL_T,runResetAllSetting}, }; @@ -482,10 +540,10 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items) static const unsigned int COUNTS_PER_ITEM = 10; const unsigned int MAX_KNOB_VALUE = num_items*COUNTS_PER_ITEM - 1; int knob_sum = 0; - unsigned int old_index = 0; + unsigned int old_index = -1; drawMenu(menu_items,num_items); - movePuck(1,0);//Force draw of puck + movePuck(-1,0);//Force draw of puck //wait for the button to be raised up while(btnDown()){ @@ -504,6 +562,16 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items) uint16_t index = knob_sum/COUNTS_PER_ITEM; movePuck(old_index,index); + + if(globalSettings.morseMenuOn //Only spend cycles copying menu item into RAM if we actually need to + && (old_index != index)){ + MenuItem_t mi = {"",nullptr}; + memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 + strncpy_P(b,mi.ItemName,sizeof(b)); + morseText(b); + enc_read();//Consume any rotations during morse playback + } + old_index = index; if (!btnDown()){ From 814b646ab0f25e2e90629855b7eaf6f5f09a144f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 22 Jan 2020 00:11:52 -0800 Subject: [PATCH 092/324] Shuffle CW menu a bit, and reduce lots of menu name string lengths so that they play faster when in CW mode --- setup.cpp | 162 +++++++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) diff --git a/setup.cpp b/setup.cpp index 9f0875b..0ac1f44 100644 --- a/setup.cpp +++ b/setup.cpp @@ -226,40 +226,6 @@ const SettingScreen_t ssBfo PROGMEM = { }; void runBfoSetting(){runSetting(&ssBfo);} -//CW Speed -void ssCwSpeedInitialize(long int* start_value_out) -{ - *start_value_out = 1200L/globalSettings.cwDitDurationMs; -} -void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_value_out) -{ - *validated_value_out = LIMIT(candidate_value_in,1,100); -} -void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t buff_out_size) -{ - ltoa(new_value, buff_out, 10); - morseText(buff_out,1200L/new_value); - enc_read();//Consume any rotations during morse playback -} -void ssCwSpeedFinalize(const long int final_value) -{ - globalSettings.cwDitDurationMs = 1200L/final_value; - SaveSettingsToEeprom(); -} -const char SS_CW_SPEED_T [] PROGMEM = "CW Play Speed"; -const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters"; -const SettingScreen_t ssCwSpeed PROGMEM = { - SS_CW_SPEED_T, - SS_CW_SPEED_A, - 5, - 1, - ssCwSpeedInitialize, - ssCwSpeedValidate, - ssCwSpeedChange, - ssCwSpeedFinalize -}; -void runCwSpeedSetting(){runSetting(&ssCwSpeed);} - //CW Tone void ssCwToneInitialize(long int* start_value_out) { @@ -282,7 +248,7 @@ void ssCwToneFinalize(const long int final_value) globalSettings.cwSideToneFreq = final_value; SaveSettingsToEeprom(); } -const char SS_CW_TONE_T [] PROGMEM = "CW Tone Frequency"; +const char SS_CW_TONE_T [] PROGMEM = "Tone"; const char SS_CW_TONE_A [] PROGMEM = "Select a frequency that\nCW mode to tune for"; const SettingScreen_t ssTone PROGMEM = { SS_CW_TONE_T, @@ -317,7 +283,7 @@ void ssCwSwitchDelayFinalize(const long int final_value) globalSettings.cwActiveTimeoutMs = final_value; SaveSettingsToEeprom(); } -const char SS_CW_SWITCH_T [] PROGMEM = "CW Tx -> Rx Switch Delay"; +const char SS_CW_SWITCH_T [] PROGMEM = "Tx to Rx Delay"; const char SS_CW_SWITCH_A [] PROGMEM = "Select how long the radio\nshould wait before switching\nbetween TX and RX when in\nCW mode"; const SettingScreen_t ssCwSwitchDelay PROGMEM = { SS_CW_SWITCH_T, @@ -363,7 +329,7 @@ void ssKeyerFinalize(const long int final_value) globalSettings.keyerMode = final_value; SaveSettingsToEeprom(); } -const char SS_KEYER_T [] PROGMEM = "CW Keyer/Paddle Type"; +const char SS_KEYER_T [] PROGMEM = "Keyer Type"; const char SS_KEYER_A [] PROGMEM = "Select which type of\nkeyer/paddle is being used"; const SettingScreen_t ssKeyer PROGMEM = { SS_KEYER_T, @@ -377,16 +343,16 @@ const SettingScreen_t ssKeyer PROGMEM = { }; void runKeyerSetting(){runSetting(&ssKeyer);} -//Reset all settings -void ssResetAllInitialize(long int* start_value_out) +//Morse menu playback +void ssMorseMenuInitialize(long int* start_value_out) { - *start_value_out = 0;//Default to NOT resetting + *start_value_out = globalSettings.morseMenuOn; } -void ssResetAllValidate(const long int candidate_value_in, long int* validated_value_out) +void ssMorseMenuValidate(const long int candidate_value_in, long int* validated_value_out) { *validated_value_out = LIMIT(candidate_value_in,0,1); } -void ssResetAllChange(const long int new_value, char* buff_out, const size_t buff_out_size) +void ssMorseMenuChange(const long int new_value, char* buff_out, const size_t buff_out_size) { char m; if(new_value){ @@ -400,38 +366,69 @@ void ssResetAllChange(const long int new_value, char* buff_out, const size_t buf morseLetter(m); enc_read();//Consume any rotations during morse playback } -void ssResetAllFinalize(const long int final_value) +void ssMorseMenuFinalize(const long int final_value) { - if(final_value){ - LoadDefaultSettings(); - SaveSettingsToEeprom(); - setup(); - } + globalSettings.morseMenuOn = final_value; + SaveSettingsToEeprom(); } -const char SS_RESET_ALL_T [] PROGMEM = "Reset All Cals/Settings"; -const char SS_RESET_ALL_A [] PROGMEM = "WARNING: Selecting \"Yes\"\nwill reset all calibrations and\nsettings to their default\nvalues"; -const SettingScreen_t ssResetAll PROGMEM = { - SS_RESET_ALL_T, - SS_RESET_ALL_A, - 20, +const char SS_MORSE_MENU_T [] PROGMEM = "Menu Audio"; +const char SS_MORSE_MENU_A [] PROGMEM = "When on, menu selections\nwill play morse code"; +const SettingScreen_t ssMorseMenu PROGMEM = { + SS_MORSE_MENU_T, + SS_MORSE_MENU_A, + 10, 1, - ssResetAllInitialize, - ssResetAllValidate, - ssResetAllChange, - ssResetAllFinalize + ssMorseMenuInitialize, + ssMorseMenuValidate, + ssMorseMenuChange, + ssMorseMenuFinalize }; -void runResetAllSetting(){runSetting(&ssResetAll);} +void runMorseMenuSetting(){runSetting(&ssMorseMenu);} -//Morse menu playback -void ssMorseMenuInitialize(long int* start_value_out) +//CW Speed +void ssCwSpeedInitialize(long int* start_value_out) { - *start_value_out = globalSettings.morseMenuOn; + *start_value_out = 1200L/globalSettings.cwDitDurationMs; } -void ssMorseMenuValidate(const long int candidate_value_in, long int* validated_value_out) +void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_value_out) +{ + *validated_value_out = LIMIT(candidate_value_in,1,100); +} +void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t buff_out_size) +{ + ltoa(new_value, buff_out, 10); + morseText(buff_out,1200L/new_value); + enc_read();//Consume any rotations during morse playback +} +void ssCwSpeedFinalize(const long int final_value) +{ + globalSettings.cwDitDurationMs = 1200L/final_value; + SaveSettingsToEeprom(); +} +const char SS_CW_SPEED_T [] PROGMEM = "Play Speed"; +const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters"; +const SettingScreen_t ssCwSpeed PROGMEM = { + SS_CW_SPEED_T, + SS_CW_SPEED_A, + 5, + 1, + ssCwSpeedInitialize, + ssCwSpeedValidate, + ssCwSpeedChange, + ssCwSpeedFinalize +}; +void runCwSpeedSetting(){runSetting(&ssCwSpeed);} + +//Reset all settings +void ssResetAllInitialize(long int* start_value_out) +{ + *start_value_out = 0;//Default to NOT resetting +} +void ssResetAllValidate(const long int candidate_value_in, long int* validated_value_out) { *validated_value_out = LIMIT(candidate_value_in,0,1); } -void ssMorseMenuChange(const long int new_value, char* buff_out, const size_t buff_out_size) +void ssResetAllChange(const long int new_value, char* buff_out, const size_t buff_out_size) { char m; if(new_value){ @@ -445,24 +442,27 @@ void ssMorseMenuChange(const long int new_value, char* buff_out, const size_t bu morseLetter(m); enc_read();//Consume any rotations during morse playback } -void ssMorseMenuFinalize(const long int final_value) +void ssResetAllFinalize(const long int final_value) { - globalSettings.morseMenuOn = final_value; - SaveSettingsToEeprom(); + if(final_value){ + LoadDefaultSettings(); + SaveSettingsToEeprom(); + setup(); + } } -const char SS_MORSE_MENU_T [] PROGMEM = "Morse Menu Play"; -const char SS_MORSE_MENU_A [] PROGMEM = "When on, menu selections\nwill play morse code"; -const SettingScreen_t ssMorseMenu PROGMEM = { - SS_MORSE_MENU_T, - SS_MORSE_MENU_A, - 10, +const char SS_RESET_ALL_T [] PROGMEM = "Reset All"; +const char SS_RESET_ALL_A [] PROGMEM = "WARNING: Selecting \"Yes\"\nwill reset all calibrations and\nsettings to their default\nvalues"; +const SettingScreen_t ssResetAll PROGMEM = { + SS_RESET_ALL_T, + SS_RESET_ALL_A, + 20, 1, - ssMorseMenuInitialize, - ssMorseMenuValidate, - ssMorseMenuChange, - ssMorseMenuFinalize + ssResetAllInitialize, + ssResetAllValidate, + ssResetAllChange, + ssResetAllFinalize }; -void runMorseMenuSetting(){runSetting(&ssMorseMenu);} +void runResetAllSetting(){runSetting(&ssResetAll);} struct MenuItem_t { const char* const ItemName; @@ -482,13 +482,14 @@ const MenuItem_t calibrationMenu [] PROGMEM { }; void runCalibrationMenu(){RUN_MENU(calibrationMenu);} -const char MT_CW [] PROGMEM = "CW/Morse Setup"; +const char MT_CW [] PROGMEM = "CW Setup"; const MenuItem_t cwMenu [] PROGMEM { {MT_CW,nullptr},//Title - {SS_CW_SPEED_T,runCwSpeedSetting}, {SS_CW_TONE_T,runToneSetting}, {SS_CW_SWITCH_T,runCwSwitchDelaySetting}, {SS_KEYER_T,runKeyerSetting}, + {SS_MORSE_MENU_T,runMorseMenuSetting}, + {SS_CW_SPEED_T,runCwSpeedSetting}, }; void runCwMenu(){RUN_MENU(cwMenu);} @@ -497,7 +498,6 @@ const MenuItem_t mainMenu [] PROGMEM { {MT_SETTINGS,nullptr},//Title {MT_CAL,runCalibrationMenu}, {MT_CW,runCwMenu}, - {SS_MORSE_MENU_T,runMorseMenuSetting}, {SS_RESET_ALL_T,runResetAllSetting}, }; From 1b8966103dcc377ea9021462ae8861ab81b205d3 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 22 Jan 2020 00:49:59 -0800 Subject: [PATCH 093/324] Send audio for 'Exit' menu option correctly --- setup.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/setup.cpp b/setup.cpp index 0ac1f44..7d666df 100644 --- a/setup.cpp +++ b/setup.cpp @@ -565,9 +565,14 @@ void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items) if(globalSettings.morseMenuOn //Only spend cycles copying menu item into RAM if we actually need to && (old_index != index)){ - MenuItem_t mi = {"",nullptr}; - memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 - strncpy_P(b,mi.ItemName,sizeof(b)); + if(num_items-1 > index){ + MenuItem_t mi = {"",nullptr}; + memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 + strncpy_P(b,mi.ItemName,sizeof(b)); + } + else{ + strncpy_P(b,MI_EXIT,sizeof(b)); + } morseText(b); enc_read();//Consume any rotations during morse playback } From 0c575d222fbf171ac27fa457aa0f8201a9b1f253 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Jan 2020 11:27:58 -0800 Subject: [PATCH 094/324] Add a way to terminate playback --- morse.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/morse.cpp b/morse.cpp index c44cb81..96198ec 100644 --- a/morse.cpp +++ b/morse.cpp @@ -106,8 +106,13 @@ static void morseLetter(char c, uint16_t dit_duration_ms){ } void morseText(char *text, uint16_t dit_duration_ms){ - while(*text){ + int16_t total_counts = 0; + tone(CW_TONE, globalSettings.cwSideToneFreq-100); + delay(100); + enc_read();//Don't count initial tone against total_counts + while(*text && (abs(total_counts) < 10)){ morseLetter(*text++, dit_duration_ms); + total_counts += enc_read(); } } From a8910e1ba27a1ae08e2d16bf874106ae7fc1d292 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Jan 2020 11:57:04 -0800 Subject: [PATCH 095/324] Auto-update sideband mode based on keyed-in frequency --- ubitx_ui.cpp | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 6f11eb7..0832138 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -415,16 +415,29 @@ void enterFreq(){ switch(button.id){ case KEYS_OK: { - long freq = atol(c); - if((LOWEST_FREQ/1000 <= freq) && (freq <= HIGHEST_FREQ/1000)){ - freq *= 1000L; - setFrequency(freq); + long new_freq = atol(c); + if((LOWEST_FREQ/1000 <= new_freq) && (new_freq <= HIGHEST_FREQ/1000)){ + new_freq *= 1000L; + + long prev_freq = GetActiveVfoFreq(); + //Transition from below to above the traditional threshold for USB + if(prev_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + } + + //Transition from aboveo to below the traditional threshold for USB + if(prev_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + } + if (VFO_A == globalSettings.activeVfo){ - globalSettings.vfoA.frequency = freq; + globalSettings.vfoA.frequency = new_freq; } else{ - globalSettings.vfoB.frequency = freq; + globalSettings.vfoB.frequency = new_freq; } + + setFrequency(new_freq); saveVFOs(); } guiUpdate(); From 54e4d4bf061b624b11136dc569cbe4be90257f67 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Jan 2020 12:02:30 -0800 Subject: [PATCH 096/324] When sideband mode is changed, immediately update tuning --- ubitx_ui.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 0832138..d553244 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -619,10 +619,13 @@ void cwToggle(struct Button *b){ } void sidebandToggle(Button* button){ - if(BUTTON_LSB == button->id) + if(BUTTON_LSB == button->id){ SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - else + } + else{ SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + } + setFrequency(GetActiveVfoFreq()); struct Button button2; getButton(BUTTON_USB, &button2); From 68b85e6fa0b2edc826ea30a1217c503a9a189793 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Jan 2020 15:54:06 -0800 Subject: [PATCH 097/324] Add a brief pause before continuing to play the actual characters --- morse.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/morse.cpp b/morse.cpp index 96198ec..c8f06f5 100644 --- a/morse.cpp +++ b/morse.cpp @@ -109,6 +109,8 @@ void morseText(char *text, uint16_t dit_duration_ms){ int16_t total_counts = 0; tone(CW_TONE, globalSettings.cwSideToneFreq-100); delay(100); + noTone(CW_TONE); + delay(100); enc_read();//Don't count initial tone against total_counts while(*text && (abs(total_counts) < 10)){ morseLetter(*text++, dit_duration_ms); From c6b21bfa6da06643f8556125c998df738c5f7167 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Jan 2020 15:54:47 -0800 Subject: [PATCH 098/324] Instead of fast tuning, play back the current frequency upon selection --- ubitx_ui.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 7d320f0..ffa2bea 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -710,22 +710,18 @@ void doCommand(Button* button){ } case BUTTON_VFOA: { - if(VFO_A == globalSettings.activeVfo){ - fastTune(); - } - else{ - switchVFO(VFO_A); - } + switchVFO(VFO_A); + uint32_t freq = globalSettings.vfoA.frequency; + ltoa(freq,b,10); + morseText(b); break; } case BUTTON_VFOB: { - if(VFO_B == globalSettings.activeVfo){ - fastTune(); - } - else{ - switchVFO(VFO_B); - } + switchVFO(VFO_B); + uint32_t freq = globalSettings.vfoB.frequency; + ltoa(freq,b,10); + morseText(b); break; } case BUTTON_80: From 9635d404b0c69974eb3694f4aa97e2595fbc0cad Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Jan 2020 16:31:32 -0800 Subject: [PATCH 099/324] Add morseBool function --- morse.cpp | 12 ++++++++---- morse.h | 3 +++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/morse.cpp b/morse.cpp index c8f06f5..fc464b2 100644 --- a/morse.cpp +++ b/morse.cpp @@ -105,12 +105,10 @@ static void morseLetter(char c, uint16_t dit_duration_ms){ } } +static const uint8_t RELATIVE_OFFSET_HZ = 100; void morseText(char *text, uint16_t dit_duration_ms){ int16_t total_counts = 0; - tone(CW_TONE, globalSettings.cwSideToneFreq-100); - delay(100); - noTone(CW_TONE); - delay(100); + morseBool(false); enc_read();//Don't count initial tone against total_counts while(*text && (abs(total_counts) < 10)){ morseLetter(*text++, dit_duration_ms); @@ -118,3 +116,9 @@ void morseText(char *text, uint16_t dit_duration_ms){ } } +void morseBool(bool val){ + tone(CW_TONE, globalSettings.cwSideToneFreq + (val ? RELATIVE_OFFSET_HZ : -RELATIVE_OFFSET_HZ)); + delay(3*globalSettings.cwDitDurationMs); + noTone(CW_TONE); + delay(3*globalSettings.cwDitDurationMs); +} diff --git a/morse.h b/morse.h index c588783..44ed35a 100644 --- a/morse.h +++ b/morse.h @@ -2,3 +2,6 @@ //sends out morse code at the speed set by cwSpeed void morseLetter(char c, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); void morseText(char *text, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); + +//Plays either a higher or lower tone to indicate a boolean value +void morseBool(bool val); From 1175d1f7ebad3b8e6926c4a454d38275a0337c70 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Jan 2020 16:32:04 -0800 Subject: [PATCH 100/324] Add morseBool to main screen buttons --- ubitx_ui.cpp | 86 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 19 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index ffa2bea..be54499 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -76,29 +76,55 @@ struct Button { unsigned int id; char text[5]; char morse; + void (*morse_status)(int8_t* val_out);//-1 if a low tone should play, +1 if a high tone should play }; +void msVfoA(int8_t* val_out){ + *val_out = (Vfo_e::VFO_A == globalSettings.activeVfo) ? 1 : -1; +} +void msVfoB(int8_t* val_out){ + *val_out = (Vfo_e::VFO_B == globalSettings.activeVfo) ? 1 : -1; +} +void msRit(int8_t* val_out){ + *val_out = globalSettings.ritOn ? 1 : -1; +} +void msUsb(int8_t* val_out){ + *val_out = (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? 1 : -1; +} +void msLsb(int8_t* val_out){ + *val_out = (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? 1 : -1; +} +void msCw(int8_t* val_out){ + *val_out = (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? 1 : -1; +} +void msSpl(int8_t* val_out){ + *val_out = globalSettings.splitOn ? 1 : -1; +} +void msIgnore(int8_t* val_out){ + *val_out = 0; +} + constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = { - {LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A'}, - {LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B'}, + {LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A', msVfoA}, + {LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B', msVfoB}, - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R'}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U'}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L'}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C'}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S'}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8'}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4'}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3'}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2'}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7'}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5'}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1'}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0'}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "MNU", 'M'}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F'}, + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R', msRit}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U', msUsb}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L', msLsb}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C', msCw}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S', msSpl}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8', msIgnore}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4', msIgnore}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3', msIgnore}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2', msIgnore}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7', msIgnore}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5', msIgnore}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1', msIgnore}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0', msIgnore}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "MNU", 'M', msIgnore}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F', msIgnore}, }; static const unsigned int KEYS_OFFSET = 256;//Unique from buttons @@ -830,6 +856,16 @@ void doCommands(){ Button button; memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); morseLetter(button.morse); + int8_t morse_status = 0; + button.morse_status(&morse_status); + if(morse_status){ + if(morse_status > 0){ + morseBool(true); + } + else{ + morseBool(false); + } + } while (true){ //check if the knob's button was pressed @@ -872,6 +908,18 @@ void doCommands(){ drawFocus(select/10, COLOR_ACTIVE_BORDER); memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); morseLetter(button.morse); + morse_status = 0; + button.morse_status(&morse_status); + Serial.println((uint16_t)button.morse_status); + Serial.println(morse_status); + if(morse_status){ + if(morse_status > 0){ + morseBool(true); + } + else{ + morseBool(false); + } + } enc_read();//Clear any rotation that was done while the letter was playing prev_button = select/10; } From e88ee1826e5e2457aee06bce43d46353543593db Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:22:01 -0800 Subject: [PATCH 101/324] Remove unused variables and set default values for colors --- ubitx_ui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 6f11eb7..d8328f8 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -193,8 +193,9 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, const } void displayVFO(Vfo_e vfo){ - int x, y; - int displayColor, displayBackground, displayBorder; + uint16_t displayColor = COLOR_INACTIVE_TEXT; + uint16_t displayBackground = COLOR_INACTIVE_BACKGROUND; + uint16_t displayBorder = COLOR_INACTIVE_BORDER; Button button; if (globalSettings.splitOn){ From 2ac24eb28df826a631c78e82c2db3358478dbf5a Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:22:20 -0800 Subject: [PATCH 102/324] Minor whitespace adjustment, and remove unused variables --- ubitx_v6.3.1_code.ino | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index 617977e..0efc991 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -305,8 +305,6 @@ void checkPTT(){ //check if the encoder button was pressed void checkButton(){ - int i, t1, t2, knob, new_knob; - //only if the button is pressed if (!btnDown()) return; @@ -325,10 +323,9 @@ void checkButton(){ doSetup2(); return; } - } - active_delay(100); + } + active_delay(100); - doCommands(); //wait for the button to go up again while(btnDown()) From b65e5eb90c9ff695b79833a6077430300b5c08f5 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:38:35 -0800 Subject: [PATCH 103/324] un-name unused variable --- PDQ_MinLib/PDQ_GFX.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PDQ_MinLib/PDQ_GFX.h b/PDQ_MinLib/PDQ_GFX.h index cb9f152..f2a551e 100644 --- a/PDQ_MinLib/PDQ_GFX.h +++ b/PDQ_MinLib/PDQ_GFX.h @@ -839,7 +839,7 @@ void PDQ_GFX::drawChar(coord_t x, coord_t y, unsigned char c, color_t color, // Draw a character with GFX font template -void PDQ_GFX::drawCharGFX(coord_t x, coord_t y, unsigned char c, color_t color, color_t bg, uint8_t size) +void PDQ_GFX::drawCharGFX(coord_t x, coord_t y, unsigned char c, color_t color, color_t /*bg*/, uint8_t size) { // Character is assumed previously filtered by write() to eliminate // newlines, returns, non-printable characters, etc. Calling drawChar() From f54320e8cb74869477e77d5ba1c4e2371bcd1b5e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:39:01 -0800 Subject: [PATCH 104/324] Match unsigned with unsigned --- morse.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/morse.cpp b/morse.cpp index 20a1020..2551577 100644 --- a/morse.cpp +++ b/morse.cpp @@ -66,7 +66,7 @@ static void morseLetter(char c, uint16_t dit_duration_ms){ return; } - for (int i = 0; i < sizeof(morse_table)/ sizeof(struct Morse); i++){ + for (unsigned int i = 0; i < sizeof(morse_table)/ sizeof(struct Morse); i++){ struct Morse m; memcpy_P(&m, morse_table + i, sizeof(struct Morse)); From 6dd4b37d8a2f842dcbfe9f10f48978562a651733 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:40:03 -0800 Subject: [PATCH 105/324] analogRead technically returns an int, but it only can be 0-1023, so practically it's an unsigned int. This matches types for the constants. Also removed cwAdcSTFrom, since the value will always be greater than 0 --- keyer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index dbbf4e7..21bdf98 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -29,7 +29,7 @@ */ //CW ADC Range -static const unsigned int cwAdcSTFrom = 0; +//static const unsigned int cwAdcSTFrom = 0; static const unsigned int cwAdcSTTo = 50; static const unsigned int cwAdcBothFrom = cwAdcSTTo + 1; static const unsigned int cwAdcBothTo = 300; @@ -79,7 +79,7 @@ uint8_t keyerControl = 0; char update_PaddleLatch(bool isUpdateKeyState) { unsigned char tmpKeyerControl = 0; - int paddle = analogRead(ANALOG_KEYER); + unsigned int paddle = analogRead(ANALOG_KEYER); //use the PTT as the key for tune up, quick QSOs if (digitalRead(PTT) == 0) @@ -93,7 +93,7 @@ char update_PaddleLatch(bool isUpdateKeyState) { else{ if (KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode) tmpKeyerControl = 0 ; - else if (paddle >= cwAdcSTFrom && paddle <= cwAdcSTTo) + else if (paddle <= cwAdcSTTo) tmpKeyerControl = DIT_L ; else tmpKeyerControl = 0 ; From c38460576b572207f8827a589e3b428887d97fc1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:40:59 -0800 Subject: [PATCH 106/324] A number of explicit casts, initializations, and type adjustments to avoid warnings --- setup.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/setup.cpp b/setup.cpp index e933700..135ec00 100644 --- a/setup.cpp +++ b/setup.cpp @@ -87,7 +87,7 @@ struct SettingScreen_t { void runSetting(const SettingScreen_t* const p_screen) { - SettingScreen_t screen = {0}; + SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; memcpy_P(&screen,p_screen,sizeof(screen)); displayDialog(screen.Title, screen.AdditionalText); @@ -235,7 +235,7 @@ void ssCwSpeedValidate(const long int candidate_value_in, long int* validated_va { *validated_value_out = LIMIT(candidate_value_in,1,100); } -void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t buff_out_size) +void ssCwSpeedChange(const long int new_value, char* buff_out, const size_t /*buff_out_size*/) { ltoa(new_value, buff_out, 10); } @@ -334,7 +334,7 @@ void ssKeyerInitialize(long int* start_value_out) } void ssKeyerValidate(const long int candidate_value_in, long int* validated_value_out) { - *validated_value_out = LIMIT(candidate_value_in,KeyerMode_e::KEYER_STRAIGHT,KeyerMode_e::KEYER_IAMBIC_B); + *validated_value_out = LIMIT(candidate_value_in,(uint8_t)KeyerMode_e::KEYER_STRAIGHT,(uint8_t)KeyerMode_e::KEYER_IAMBIC_B); } void ssKeyerChange(const long int new_value, char* buff_out, const size_t buff_out_size) { @@ -350,7 +350,7 @@ void ssKeyerChange(const long int new_value, char* buff_out, const size_t buff_o } void ssKeyerFinalize(const long int final_value) { - globalSettings.keyerMode = final_value; + globalSettings.keyerMode = (KeyerMode_e)final_value; SaveSettingsToEeprom(); } const char SS_KEYER_T [] PROGMEM = "CW Keyer/Paddle Type"; @@ -409,7 +409,7 @@ void runResetAllSetting(){runSetting(&ssResetAll);} struct MenuItem_t { const char* const ItemName; - const void (*OnSelect)(); + void (*OnSelect)(); }; void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); @@ -480,7 +480,7 @@ void movePuck(unsigned int old_index, unsigned int new_index) void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items) { static const unsigned int COUNTS_PER_ITEM = 10; - const unsigned int MAX_KNOB_VALUE = num_items*COUNTS_PER_ITEM - 1; + const int MAX_KNOB_VALUE = num_items*COUNTS_PER_ITEM - 1; int knob_sum = 0; unsigned int old_index = 0; From fea7b8d86803d3cda517f5c696c83a6e63bdf97c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:42:20 -0800 Subject: [PATCH 107/324] Move string to PROGMEM, and remove unused return value --- nano_gui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index 9efe8ec..fdfdfa3 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -162,7 +162,7 @@ PDQ_ILI9341 tft; #include "nano_font.h" -bool xpt2046_Init(){ +void xpt2046_Init(){ pinMode(CS_PIN, OUTPUT); digitalWrite(CS_PIN, HIGH); } @@ -246,7 +246,8 @@ void setupTouch(){ int x1, y1, x2, y2, x3, y3, x4, y4; displayClear(DISPLAY_BLACK); - displayText("Click on the cross", 20,100, 200, 50, DISPLAY_WHITE, DISPLAY_BLACK, DISPLAY_BLACK); + strncpy_P(b,(const char*)F("Click on the cross"),sizeof(b)); + displayText(b, 20,100, 200, 50, DISPLAY_WHITE, DISPLAY_BLACK, DISPLAY_BLACK); // TOP-LEFT displayHline(10,20,20,DISPLAY_WHITE); From fe9f04d14681b2d70360acb960bd05ad06b87bd6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:42:37 -0800 Subject: [PATCH 108/324] Remove unused static --- ubitx_cat.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 91c7f49..27d9707 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -19,7 +19,6 @@ static byte rxBufferCheckCount = 0; #define CAT_RECEIVE_TIMEOUT 500 static byte cat[5]; static byte insideCat = 0; -static byte useOpenRadioControl = 0; //for broken protocol #define CAT_RECEIVE_TIMEOUT 500 From 15059367137d7f1b58122a8624415f635797c8dc Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:43:11 -0800 Subject: [PATCH 109/324] Remove unused variable --- ubitx_si5351.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ubitx_si5351.cpp b/ubitx_si5351.cpp index 8e900e0..27f1b7a 100644 --- a/ubitx_si5351.cpp +++ b/ubitx_si5351.cpp @@ -66,12 +66,11 @@ void i2cWriten(uint8_t reg, uint8_t *vals, uint8_t vcnt) { // write array void si5351bx_init() { // Call once at power-up, start PLLA - uint8_t reg; uint32_t msxp1; Wire.begin(); i2cWrite(149, 0); // SpreadSpectrum off i2cWrite(3, si5351bx_clken); // Disable all CLK output drivers i2cWrite(183, SI5351BX_XTALPF << 6); // Set 25mhz crystal load capacitance - msxp1 = 128 * SI5351BX_MSA - 512; // and msxp2=0, msxp3=1, not fractional + uint32_t msxp1 = 128 * SI5351BX_MSA - 512; // and msxp2=0, msxp3=1, not fractional uint8_t vals[8] = {0, 1, BB2(msxp1), BB1(msxp1), BB0(msxp1), 0, 0, 0}; i2cWriten(26, vals, 8); // Write to 8 PLLA msynth regs i2cWrite(177, 0x20); // Reset PLLA (0x80 resets PLLB) From 298bb479b5b0114b3f895285946d14e852a2a866 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 10:47:57 -0800 Subject: [PATCH 110/324] Explicit cast to prevent integer overflow --- encoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/encoder.cpp b/encoder.cpp index 9caa45c..7eb57d5 100644 --- a/encoder.cpp +++ b/encoder.cpp @@ -83,7 +83,7 @@ void enc_setup(void) TCCR1A = 0;//"normal" mode TCCR1B = 3;//clock divider of 64 TCNT1 = 0;//start counting at 0 - OCR1A = F_CPU * CALLBACK_PERIOD_MS / 1000 / 64;//set target number + OCR1A = F_CPU * (unsigned long)CALLBACK_PERIOD_MS / 1000 / 64;//set target number TIMSK1 |= (1 << OCIE1A);//enable interrupt } From 953a59f309e781c6c25200e0a71b46be064640e6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 11:15:11 -0800 Subject: [PATCH 111/324] Don't play bools if morseMenu is off --- morse.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/morse.cpp b/morse.cpp index 7315b3a..9dc2931 100644 --- a/morse.cpp +++ b/morse.cpp @@ -117,6 +117,9 @@ void morseText(char *text, uint16_t dit_duration_ms){ } void morseBool(bool val){ + if(!globalSettings.morseMenuOn){ + return; + } tone(CW_TONE, globalSettings.cwSideToneFreq + (val ? RELATIVE_OFFSET_HZ : -RELATIVE_OFFSET_HZ)); delay(3*globalSettings.cwDitDurationMs); noTone(CW_TONE); From 95ea5b0ee2a99acd6d3bcf461d4bc674d9f7db15 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 11:26:18 -0800 Subject: [PATCH 112/324] Use unsigned ints for frequency --- ubitx_ui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 58828fe..321c1a8 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -416,11 +416,11 @@ void enterFreq(){ switch(button.id){ case KEYS_OK: { - long new_freq = atol(c); + uint32_t new_freq = atol(c); if((LOWEST_FREQ/1000 <= new_freq) && (new_freq <= HIGHEST_FREQ/1000)){ new_freq *= 1000L; - long prev_freq = GetActiveVfoFreq(); + uint32_t prev_freq = GetActiveVfoFreq(); //Transition from below to above the traditional threshold for USB if(prev_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); From e67885d8a0e5414d352da2889a64f850ab8f570e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Jan 2020 13:03:50 -0800 Subject: [PATCH 113/324] disable delay before starting CW, allow straight key values through the paddle resistors, set correct timeout --- keyer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index 21bdf98..d213978 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -38,7 +38,7 @@ static const unsigned int cwAdcDotTo = 600; static const unsigned int cwAdcDashFrom = cwAdcDotTo + 1; static const unsigned int cwAdcDashTo = 800; -static const unsigned int delayBeforeCWStartTime = 50; +static const unsigned int delayBeforeCWStartTime = 0; /** * Starts transmitting the carrier with the sidetone @@ -93,7 +93,7 @@ char update_PaddleLatch(bool isUpdateKeyState) { else{ if (KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode) tmpKeyerControl = 0 ; - else if (paddle <= cwAdcSTTo) + else if (paddle <= cwAdcDashTo) tmpKeyerControl = DIT_L ; else tmpKeyerControl = 0 ; @@ -209,7 +209,7 @@ void cwKeyer(void){ //DelayTime Option active_delay(delayBeforeCWStartTime * 2); - globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwDitDurationMs; + globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; } cwKeydown(); From 8db6401becccc80d4cdb4eaf577dff7e8e90f0d4 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 27 Jan 2020 21:51:34 -0800 Subject: [PATCH 114/324] Remove delay entirely. active_delay delays 10ms even when asked for 0 --- keyer.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index d213978..d138013 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -38,8 +38,6 @@ static const unsigned int cwAdcDotTo = 600; static const unsigned int cwAdcDashFrom = cwAdcDotTo + 1; static const unsigned int cwAdcDashTo = 800; -static const unsigned int delayBeforeCWStartTime = 0; - /** * Starts transmitting the carrier with the sidetone * It assumes that we have called cwTxStart and not called cwTxStop @@ -156,8 +154,6 @@ void cwKeyer(void){ case KEYED_PREP: //modified KD8CEC if (!globalSettings.txActive){ - //DelayTime Option - active_delay(delayBeforeCWStartTime * 2); globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; startTx(TuningMode_e::TUNE_CW); } @@ -205,10 +201,6 @@ void cwKeyer(void){ // if we are here, it is only because the key is pressed if (!globalSettings.txActive){ startTx(TuningMode_e::TUNE_CW); - - //DelayTime Option - active_delay(delayBeforeCWStartTime * 2); - globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; } cwKeydown(); From 13f4bdbe83140c2e3bbb6f57ec0c1d85e3c7ea4e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 27 Jan 2020 22:36:01 -0800 Subject: [PATCH 115/324] Add version string to bottom right corner --- ubitx_ui.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 321c1a8..8a26b59 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -1,9 +1,10 @@ #include #include "morse.h" +#include "nano_gui.h" #include "settings.h" #include "setup.h" #include "ubitx.h" -#include "nano_gui.h" +#include "version.h" static const unsigned int COLOR_TEXT = DISPLAY_WHITE; static const unsigned int COLOR_BACKGROUND = DISPLAY_NAVY; @@ -22,6 +23,8 @@ static const unsigned int COLOR_ACTIVE_TEXT = DISPLAY_BLACK; static const unsigned int COLOR_ACTIVE_BACKGROUND = DISPLAY_ORANGE; static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; +static const unsigned int COLOR_VERSION_TEXT = DISPLAY_LIGHTGREY; + static const unsigned int LAYOUT_VFO_LABEL_X = 0; static const unsigned int LAYOUT_VFO_LABEL_Y = 10; static const unsigned int LAYOUT_VFO_LABEL_WIDTH = 159; @@ -42,9 +45,14 @@ static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; static const unsigned int LAYOUT_CW_TEXT_X = 0; static const unsigned int LAYOUT_CW_TEXT_Y = LAYOUT_BUTTON_Y + 3*LAYOUT_BUTTON_PITCH_Y + 1; -static const unsigned int LAYOUT_CW_TEXT_WIDTH = 320; +static const unsigned int LAYOUT_CW_TEXT_WIDTH = 220; static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 36; +static const unsigned int LAYOUT_VERSION_TEXT_X = LAYOUT_CW_TEXT_X + LAYOUT_CW_TEXT_WIDTH + 1; +static const unsigned int LAYOUT_VERSION_TEXT_Y = LAYOUT_CW_TEXT_Y; +static const unsigned int LAYOUT_VERSION_TEXT_WIDTH = 320 - LAYOUT_CW_TEXT_WIDTH - 1; +static const unsigned int LAYOUT_VERSION_TEXT_HEIGHT = LAYOUT_CW_TEXT_HEIGHT; + static const unsigned int LAYOUT_TX_X = 280; static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; static const unsigned int LAYOUT_TX_WIDTH = 40; @@ -506,6 +514,11 @@ void drawCWStatus(){ displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } +void drawVersion() +{ + strncpy_P(b,VERSION_STRING,sizeof(b)); + displayText(b, LAYOUT_VERSION_TEXT_X, LAYOUT_VERSION_TEXT_Y, LAYOUT_VERSION_TEXT_WIDTH, LAYOUT_VERSION_TEXT_HEIGHT, COLOR_VERSION_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); +} void drawTx(){ if (globalSettings.txActive){ @@ -518,6 +531,7 @@ void drawTx(){ } void drawStatusbar(){ drawCWStatus(); + drawVersion(); } void guiUpdate(){ From 0417907d039cced53ea5de0b600d1f5c59cc6bdb Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 27 Jan 2020 23:08:32 -0800 Subject: [PATCH 116/324] Add justification option for text rendering --- nano_gui.cpp | 13 +++++++++++-- nano_gui.h | 9 ++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index fdfdfa3..1bc9d55 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -228,7 +228,8 @@ void displayRawText(char *text, int x1, int y1, int w, int color, int background tft.print(text); } -void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border) { +void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification) +{ displayFillrect(x1, y1, w ,h, background); displayRect(x1, y1, w ,h, border); @@ -237,7 +238,15 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr uint16_t width_out; uint16_t height_out; tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out,w); - x1 += (w - ( (int32_t)width_out + (x1_out-x1)))/2; + if(TextJustification_e::Center == justification){ + x1 += (w - ( (int32_t)width_out + (x1_out-x1)))/2; + } + else if(TextJustification_e::Right == justification){ + x1 += w - ((int32_t)width_out + (x1_out-x1)); + } + else{ + x1 += 2;//Give a little bit of padding from the border + } y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out))/2; displayRawText(text,x1,y1,w,color,background); } diff --git a/nano_gui.h b/nano_gui.h index b6d24ac..7c1fd21 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -7,6 +7,13 @@ struct Point { }; extern struct Point ts_point; +enum TextJustification_e : uint8_t +{ + Left, + Right, + Center +}; + void displayInit(); void displayClear(unsigned int color); void displayPixel(unsigned int x, unsigned int y, unsigned int c); @@ -16,7 +23,7 @@ void displayRect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,uns void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c); void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg); void displayRawText(char *text, int x1, int y1, int color, int background); -void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border); +void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification = TextJustification_e::Center); void formatFreq(uint32_t freq, char* buff, uint16_t buff_size); From ceec8e2eb29cc54a3b7de7af27c4f57c1861e07c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 27 Jan 2020 23:09:05 -0800 Subject: [PATCH 117/324] Push CW settings text to left, version to right --- ubitx_ui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 8a26b59..329376f 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -511,13 +511,13 @@ void drawCWStatus(){ itoa(globalSettings.cwSideToneFreq, c, 10); strncat(b, c, sizeof(b) - strlen(b)); strncat_P(b,(const char*)F("hz"), sizeof(b) - strlen(b)); - displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND, TextJustification_e::Left); } void drawVersion() { strncpy_P(b,VERSION_STRING,sizeof(b)); - displayText(b, LAYOUT_VERSION_TEXT_X, LAYOUT_VERSION_TEXT_Y, LAYOUT_VERSION_TEXT_WIDTH, LAYOUT_VERSION_TEXT_HEIGHT, COLOR_VERSION_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(b, LAYOUT_VERSION_TEXT_X, LAYOUT_VERSION_TEXT_Y, LAYOUT_VERSION_TEXT_WIDTH, LAYOUT_VERSION_TEXT_HEIGHT, COLOR_VERSION_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND, TextJustification_e::Right); } void drawTx(){ From 03c159ba5198e4e6b51da4ae84016d69d2338736 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 27 Jan 2020 23:09:34 -0800 Subject: [PATCH 118/324] Render menus to the left, rather than center --- setup.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/setup.cpp b/setup.cpp index 135ec00..70852ff 100644 --- a/setup.cpp +++ b/setup.cpp @@ -69,7 +69,7 @@ void displayDialog(const char* title, strncpy_P(b,title,sizeof(b)); displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); strncpy_P(b,instructions,sizeof(b)); - displayText(b, LAYOUT_INSTRUCTIONS_TEXT_X, LAYOUT_INSTRUCTIONS_TEXT_Y, LAYOUT_INSTRUCTIONS_TEXT_WIDTH, LAYOUT_INSTRUCTIONS_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(b, LAYOUT_INSTRUCTIONS_TEXT_X, LAYOUT_INSTRUCTIONS_TEXT_Y, LAYOUT_INSTRUCTIONS_TEXT_WIDTH, LAYOUT_INSTRUCTIONS_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND, TextJustification_e::Left); strncpy_P(b,(const char*)F("Push Tune to Save"),sizeof(b)); displayText(b, LAYOUT_CONFIRM_TEXT_X, LAYOUT_CONFIRM_TEXT_Y, LAYOUT_CONFIRM_TEXT_WIDTH, LAYOUT_CONFIRM_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } @@ -456,11 +456,11 @@ void drawMenu(const MenuItem_t* const items, const uint16_t num_items) for(unsigned int i = 1; i < num_items; ++i){ memcpy_P(&mi,&items[i],sizeof(mi)); strncpy_P(b,mi.ItemName,sizeof(b)); - displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); + displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (i-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER, TextJustification_e::Left); } memcpy_P(&mi,&exitMenu,sizeof(mi)); strncpy_P(b,mi.ItemName,sizeof(b)); - displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (num_items-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER); + displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (num_items-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER, TextJustification_e::Left); } void movePuck(unsigned int old_index, unsigned int new_index) From 21736fcc1d8845e0060814dbbbffb11f46400487 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 27 Jan 2020 23:11:32 -0800 Subject: [PATCH 119/324] Forgot to add version files to the project. Silly me. --- version.cpp | 4 ++++ version.h | 9 +++++++++ 2 files changed, 13 insertions(+) create mode 100644 version.cpp create mode 100644 version.h diff --git a/version.cpp b/version.cpp new file mode 100644 index 0000000..bd2cde7 --- /dev/null +++ b/version.cpp @@ -0,0 +1,4 @@ +#include "version.h" + +const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.1.1"; +const char* const VERSION_STRING = VERSION_STRING_PRIVATE; \ No newline at end of file diff --git a/version.h b/version.h new file mode 100644 index 0000000..9ce2cef --- /dev/null +++ b/version.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +/* + * VERSION_STRING is a PROGMEM string, so extract it before use, e.g. + * strncpy_P(char_buffer_out,VERSION_STRING,size_of_char_buffer_out); + */ +extern const char* const VERSION_STRING; \ No newline at end of file From 015afb5cdea60af877025b921acc8627ddce86c9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 01:25:19 -0800 Subject: [PATCH 120/324] First pass at menu icon --- PDQ_MinLib/FreeSansBold9pt7b.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/PDQ_MinLib/FreeSansBold9pt7b.h b/PDQ_MinLib/FreeSansBold9pt7b.h index aeea463..2f31cd1 100644 --- a/PDQ_MinLib/FreeSansBold9pt7b.h +++ b/PDQ_MinLib/FreeSansBold9pt7b.h @@ -101,7 +101,9 @@ const uint8_t FreeSansBold9pt7bBitmaps[] PROGMEM = { 0x78, 0x1E, 0x03, 0x00, 0xC0, 0x70, 0x38, 0x0E, 0x00, 0xFE, 0xFE, 0x0E, 0x1C, 0x38, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x37, 0x66, 0x66, 0x6E, 0xE6, 0x66, 0x66, 0x67, 0x30, 0xFF, 0xFF, 0x80, 0xCE, 0x66, 0x66, 0x67, 0x76, - 0x66, 0x66, 0x6E, 0xC0, 0x71, 0x8E }; + 0x66, 0x66, 0x6E, 0xC0, 0x71, 0x8E, 0x0C, 0x0C, 0x0B, 0x47, 0xF8, 0x8C, + 0xE1, 0xF8, 0x73, 0x31, 0xFE, 0x2D, 0x03, 0x00 +}; const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { { 0, 0, 0, 5, 0, 1 }, // 0x20 ' ' @@ -198,11 +200,14 @@ const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { { 1207, 4, 17, 7, 1, -12 }, // 0x7B '{' { 1216, 1, 17, 5, 2, -12 }, // 0x7C '|' { 1219, 4, 17, 7, 2, -12 }, // 0x7D '}' - { 1228, 8, 2, 9, 0, -4 } }; // 0x7E '~' + { 1228, 8, 2, 9, 0, -4 }, // 0x7E '~' + { 1231, 10, 10, 12, 1, -11 }, // 0x7F menu +}; const GFXfont FreeSansBold9pt7b PROGMEM = { (uint8_t *)FreeSansBold9pt7bBitmaps, (GFXglyph *)FreeSansBold9pt7bGlyphs, - 0x20, 0x7E, 22 }; - -// Approx. 1902 bytes + 0x20, //first character + 0x7F, //last character + 22 //yAdvance (newline) +}; From 14d19ebbd89a6e3c53c8015f877ce3dd0899dbba Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 01:42:59 -0800 Subject: [PATCH 121/324] Bigger settings icon --- PDQ_MinLib/FreeSansBold9pt7b.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/PDQ_MinLib/FreeSansBold9pt7b.h b/PDQ_MinLib/FreeSansBold9pt7b.h index 2f31cd1..a6c5de9 100644 --- a/PDQ_MinLib/FreeSansBold9pt7b.h +++ b/PDQ_MinLib/FreeSansBold9pt7b.h @@ -101,8 +101,11 @@ const uint8_t FreeSansBold9pt7bBitmaps[] PROGMEM = { 0x78, 0x1E, 0x03, 0x00, 0xC0, 0x70, 0x38, 0x0E, 0x00, 0xFE, 0xFE, 0x0E, 0x1C, 0x38, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x37, 0x66, 0x66, 0x6E, 0xE6, 0x66, 0x66, 0x67, 0x30, 0xFF, 0xFF, 0x80, 0xCE, 0x66, 0x66, 0x67, 0x76, - 0x66, 0x66, 0x6E, 0xC0, 0x71, 0x8E, 0x0C, 0x0C, 0x0B, 0x47, 0xF8, 0x8C, - 0xE1, 0xF8, 0x73, 0x31, 0xFE, 0x2D, 0x03, 0x00 + 0x66, 0x66, 0x6E, 0xC0, 0x71, 0x8E, 0x0C, 0x00, 0xF0, 0x00, 0x8F, 0x10, + 0x1C, 0xF3, 0x83, 0xFF, 0xFC, 0x7F, 0xFF, 0xE3, 0xF0, 0xFE, 0x1E, 0x07, + 0xC1, 0xC0, 0x38, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, + 0x1F, 0x1C, 0x03, 0x81, 0xE0, 0x78, 0x3F, 0x0F, 0xC7, 0xFF, 0xFE, 0x3F, + 0xFF, 0xC3, 0xCF, 0x38, 0x08, 0xF1, 0x00, 0x0F, 0x00 }; const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { @@ -201,7 +204,7 @@ const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { { 1216, 1, 17, 5, 2, -12 }, // 0x7C '|' { 1219, 4, 17, 7, 2, -12 }, // 0x7D '}' { 1228, 8, 2, 9, 0, -4 }, // 0x7E '~' - { 1231, 10, 10, 12, 1, -11 }, // 0x7F menu + { 1231, 20, 20, 22, 1, -12 }, // 0x7F gear icon }; const GFXfont FreeSansBold9pt7b PROGMEM = { From 04d836ab73b1229d5cb0d89c9b8c5acd13ad1d0c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 01:52:11 -0800 Subject: [PATCH 122/324] Removed unused function --- nano_gui.cpp | 7 ------- nano_gui.h | 1 - 2 files changed, 8 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index fdfdfa3..da53b43 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -214,13 +214,6 @@ void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t tft.drawCharGFX(x,y,c,color,bg,1); } -void displayRawText(char *text, int x1, int y1, int color, int background){ - tft.setTextColor(color,background); - tft.setCursor(x1,y1); - tft.setBound(0,320); - tft.print(text); -} - void displayRawText(char *text, int x1, int y1, int w, int color, int background){ tft.setTextColor(color,background); tft.setCursor(x1,y1); diff --git a/nano_gui.h b/nano_gui.h index b6d24ac..e85d493 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -15,7 +15,6 @@ void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c void displayRect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c); void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c); void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg); -void displayRawText(char *text, int x1, int y1, int color, int background); void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border); void formatFreq(uint32_t freq, char* buff, uint16_t buff_size); From 1115441a57c94b803a5b8f957ccc3a3e88044bd9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 01:52:31 -0800 Subject: [PATCH 123/324] Use gear icon for menu button --- ubitx_ui.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 8a26b59..30bbb84 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -105,7 +105,7 @@ constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = { {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5'}, {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1'}, {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0'}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "MNU", 'M'}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "\x7F", 'M'}, {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F'}, }; From 6313aa5adc899f7a40a1a378c3bc1921f32d76b1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 02:29:37 -0800 Subject: [PATCH 124/324] Add two spacer characters --- PDQ_MinLib/FreeSansBold9pt7b.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PDQ_MinLib/FreeSansBold9pt7b.h b/PDQ_MinLib/FreeSansBold9pt7b.h index a6c5de9..8758ba8 100644 --- a/PDQ_MinLib/FreeSansBold9pt7b.h +++ b/PDQ_MinLib/FreeSansBold9pt7b.h @@ -205,12 +205,14 @@ const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { { 1219, 4, 17, 7, 2, -12 }, // 0x7D '}' { 1228, 8, 2, 9, 0, -4 }, // 0x7E '~' { 1231, 20, 20, 22, 1, -12 }, // 0x7F gear icon + { 1231, 0, 0, 10, 0, 1 }, // 0x80 10px space to match numbers + { 1231, 0, 0, 4, 0, 1 }, // 0x81 4px space to match period }; const GFXfont FreeSansBold9pt7b PROGMEM = { (uint8_t *)FreeSansBold9pt7bBitmaps, (GFXglyph *)FreeSansBold9pt7bGlyphs, 0x20, //first character - 0x7F, //last character + 0x81, //last character 22 //yAdvance (newline) }; From 6ddd46a853fd3aeb3f5243c30d91ae9724385d67 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 02:30:34 -0800 Subject: [PATCH 125/324] Add spacers to keep frequency display a fixed width --- nano_gui.cpp | 17 ++++++++++++++--- nano_gui.h | 2 +- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index da53b43..f10bf97 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -11,7 +11,8 @@ struct Point ts_point; /* * This formats the frequency given in f */ -void formatFreq(uint32_t freq, char* buff, uint16_t buff_size) { +void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width) +{ memset(buff, 0, buff_size); ultoa(freq, buff, DEC); @@ -20,10 +21,20 @@ void formatFreq(uint32_t freq, char* buff, uint16_t buff_size) { const uint8_t num_leading_digits_raw = num_digits % 3; const uint8_t num_leading_digits = (0 == num_leading_digits_raw) ? 3 : num_leading_digits_raw; - if(0 == num_spacers){ - return; + if(0 < fixed_width){ + while(0 < fixed_width - num_digits - num_spacers){ + if(0 == fixed_width % 4){ + buff[0] = '\x81';//separator size + } + else{ + buff[0] = '\x80';//digit size + } + --fixed_width; + ++buff; + } } + ultoa(freq, buff, DEC); buff += num_leading_digits; num_digits -= num_leading_digits; for(int i = num_digits-1; i >= 0; --i){ diff --git a/nano_gui.h b/nano_gui.h index e85d493..0826ee1 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -17,7 +17,7 @@ void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg); void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border); -void formatFreq(uint32_t freq, char* buff, uint16_t buff_size); +void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width = 0); /* touch functions */ boolean readTouch(); From 2d48b584614ed3d372152328ddad0e0164c2cf00 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 02:31:14 -0800 Subject: [PATCH 126/324] Force a fix frequency width when possible --- ubitx_ui.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 30bbb84..1427402 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -230,7 +230,7 @@ void displayVFO(Vfo_e vfo){ if (VFO_A == vfo){ getButton(BUTTON_VFOA, &button); - formatFreq(globalSettings.vfoA.frequency, c+2, sizeof(c)-2); + formatFreq(globalSettings.vfoA.frequency, c+2, sizeof(c)-2, 10); if (VFO_A == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; @@ -245,7 +245,7 @@ void displayVFO(Vfo_e vfo){ if (VFO_B == vfo){ getButton(BUTTON_VFOB, &button); - formatFreq(globalSettings.vfoB.frequency, c+2, sizeof(c)-2); + formatFreq(globalSettings.vfoB.frequency, c+2, sizeof(c)-2, 10); if (VFO_B == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; From 40c23919edf77a31cb77fa1363748c4ff6bbdd69 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 20:26:34 -0800 Subject: [PATCH 127/324] Add space between colon and frequency output --- ubitx_ui.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 1427402..c9df34d 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -226,11 +226,12 @@ void displayVFO(Vfo_e vfo){ } } c[1] = ':'; + c[2] = ' '; if (VFO_A == vfo){ getButton(BUTTON_VFOA, &button); - formatFreq(globalSettings.vfoA.frequency, c+2, sizeof(c)-2, 10); + formatFreq(globalSettings.vfoA.frequency, c+3, sizeof(c)-3, 10); if (VFO_A == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; @@ -245,7 +246,7 @@ void displayVFO(Vfo_e vfo){ if (VFO_B == vfo){ getButton(BUTTON_VFOB, &button); - formatFreq(globalSettings.vfoB.frequency, c+2, sizeof(c)-2, 10); + formatFreq(globalSettings.vfoB.frequency, c+3, sizeof(c)-3, 10); if (VFO_B == globalSettings.activeVfo){ displayColor = COLOR_ACTIVE_VFO_TEXT; From 13fa83d4408a69bd2323eafaf3460bf29ef5e129 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 28 Jan 2020 20:54:02 -0800 Subject: [PATCH 128/324] Update reported version --- version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cpp b/version.cpp index bd2cde7..59e9fe4 100644 --- a/version.cpp +++ b/version.cpp @@ -1,4 +1,4 @@ #include "version.h" -const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.1.1"; +const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.1.2"; const char* const VERSION_STRING = VERSION_STRING_PRIVATE; \ No newline at end of file From d440be6c66f49d28ed546e43281590af741af59b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 29 Jan 2020 21:44:46 -0800 Subject: [PATCH 129/324] Rename INO file, so that it matches the repo name, and thus doesn't cause issues when checked out initially with default folder name --- ubitx_v6.3.1_code.ino => ubitxv6.ino | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename ubitx_v6.3.1_code.ino => ubitxv6.ino (100%) diff --git a/ubitx_v6.3.1_code.ino b/ubitxv6.ino similarity index 100% rename from ubitx_v6.3.1_code.ino rename to ubitxv6.ino From bc5c39357f44a0f5e52857d350bc5639cbb9f433 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Thu, 30 Jan 2020 20:23:17 -0800 Subject: [PATCH 130/324] Fix inter-element timing --- keyer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keyer.cpp b/keyer.cpp index d138013..121477f 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -167,7 +167,7 @@ void cwKeyer(void){ case KEYED: if (millis() > ktimer) { // are we at end of key down ? cwKeyUp(); - ktimer = millis() + (globalSettings.cwDitDurationMs / 10); // inter-element time + ktimer = millis() + globalSettings.cwDitDurationMs; // inter-element time keyerState = INTER_ELEMENT; // next state } else if(KeyerMode_e::KEYER_IAMBIC_B == globalSettings.keyerMode){ From 225464c51af8ddf28951ee6bb105df8621a6f5d6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 2 Feb 2020 15:19:44 -0800 Subject: [PATCH 131/324] Remove TX offset in CW mode, and refactor frequency setting code so that it's (almost) all in one place. W0EB pointed out this issue, and it appears that it was discussed but never implemented in https://groups.io/g/BITX20/topic/20916360 --- setup.cpp | 1 - ubitx.h | 2 +- ubitxv6.ino | 71 ++++++++++++++++++++++++++--------------------------- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/setup.cpp b/setup.cpp index 70852ff..89f7c04 100644 --- a/setup.cpp +++ b/setup.cpp @@ -147,7 +147,6 @@ void ssLocalOscInitialize(long int* start_value_out){ uint32_t freq = GetActiveVfoFreq(); freq = (freq/1000L) * 1000L;//round off the current frequency the nearest kHz setFrequency(freq); - si5351bx_setfreq(0, globalSettings.usbCarrierFreq); //set back the carrier oscillator, cw tx switches it off } *start_value_out = globalSettings.oscillatorCal; } diff --git a/ubitx.h b/ubitx.h index 0800e75..3218d9f 100644 --- a/ubitx.h +++ b/ubitx.h @@ -95,7 +95,7 @@ static const uint32_t THRESHOLD_USB_LSB = 10000000L; /* these are functions implemented in the main file named as ubitx_xxx.ino */ void active_delay(int delay_by); void saveVFOs(); -void setFrequency(unsigned long f); +void setFrequency(const unsigned long freq, const bool transmit = false); void startTx(TuningMode_e tx_mode); void stopTx(); void ritEnable(unsigned long f); diff --git a/ubitxv6.ino b/ubitxv6.ino index 0efc991..44437e1 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -155,29 +155,48 @@ void setTXFilters_v5(unsigned long freq){ * through mixing of the second local oscillator. */ -void setFrequency(unsigned long freq){ - static const unsigned long firstIF = 45005000L; +void setFrequency(const unsigned long freq, + const bool transmit){ + static const unsigned long FIRST_IF = 45005000UL; setTXFilters(freq); - uint32_t local_osc_freq; - if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ - local_osc_freq = firstIF + freq + globalSettings.cwSideToneFreq; - } - else{ - local_osc_freq = firstIF + freq; - } + //Nominal values for the oscillators + uint32_t local_osc_freq = FIRST_IF + freq; + uint32_t ssb_osc_freq = FIRST_IF;//will be changed depending on sideband + uint32_t bfo_osc_freq = globalSettings.usbCarrierFreq; - uint32_t ssb_osc_freq; - if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ - ssb_osc_freq = firstIF + globalSettings.usbCarrierFreq; + if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ + if(transmit){ + //We don't do any mixing or converting when transmitting + local_osc_freq = freq; + ssb_osc_freq = 0; + bfo_osc_freq = 0; + } + else{ + //We offset when receiving CW so that it's audible + if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + local_osc_freq -= globalSettings.cwSideToneFreq; + ssb_osc_freq += globalSettings.usbCarrierFreq; + } + else{ + local_osc_freq += globalSettings.cwSideToneFreq; + ssb_osc_freq -= globalSettings.usbCarrierFreq; + } + } } - else{ - ssb_osc_freq = firstIF - globalSettings.usbCarrierFreq; + else{//SSB mode + if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + ssb_osc_freq += globalSettings.usbCarrierFreq; + } + else{ + ssb_osc_freq -= globalSettings.usbCarrierFreq; + } } si5351bx_setfreq(2, local_osc_freq); si5351bx_setfreq(1, ssb_osc_freq); + si5351bx_setfreq(0, bfo_osc_freq); SetActiveVfoFreq(freq); } @@ -196,7 +215,7 @@ void startTx(TuningMode_e tx_mode){ //save the current as the rx frequency uint32_t rit_tx_freq = globalSettings.ritFrequency; globalSettings.ritFrequency = GetActiveVfoFreq(); - setFrequency(rit_tx_freq); + setFrequency(rit_tx_freq,true); } else{ if(globalSettings.splitOn){ @@ -207,26 +226,9 @@ void startTx(TuningMode_e tx_mode){ globalSettings.activeVfo = Vfo_e::VFO_B; } } - setFrequency(GetActiveVfoFreq()); + setFrequency(GetActiveVfoFreq(),true); } - if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ - //turn off the second local oscillator and the bfo - si5351bx_setfreq(0, 0); - si5351bx_setfreq(1, 0); - - //shift the first oscillator to the tx frequency directly - //the key up and key down will toggle the carrier unbalancing - //the exact cw frequency is the tuned frequency + sidetone - if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ - si5351bx_setfreq(2, GetActiveVfoFreq() + globalSettings.cwSideToneFreq); - } - else{ - si5351bx_setfreq(2, GetActiveVfoFreq() - globalSettings.cwSideToneFreq); - } - - delay(20); - } digitalWrite(TX_RX, 1);//turn on the tx globalSettings.txActive = true; drawTx(); @@ -236,9 +238,6 @@ void stopTx(){ digitalWrite(TX_RX, 0);//turn off the tx globalSettings.txActive = false; - //set back the carrier oscillator - cw tx switches it off - si5351bx_setfreq(0, globalSettings.usbCarrierFreq); - if(globalSettings.ritOn){ uint32_t rit_rx_freq = globalSettings.ritFrequency; globalSettings.ritFrequency = GetActiveVfoFreq(); From e35a9eecec71c543baac443fff173f8e7768416d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 8 Feb 2020 14:59:06 -0800 Subject: [PATCH 132/324] Move LIMIT macro to utils --- setup.cpp | 3 +-- utils.h | 3 +++ 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 utils.h diff --git a/setup.cpp b/setup.cpp index 8de8121..284f16e 100644 --- a/setup.cpp +++ b/setup.cpp @@ -4,6 +4,7 @@ #include "setup.h" #include "settings.h" #include "ubitx.h" +#include "utils.h" /** Menus * The Radio menus are accessed by tapping on the function button. @@ -139,8 +140,6 @@ void runSetting(const SettingScreen_t* const p_screen) screen.Finalize(last_value); } -#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) - //Local Oscillator void ssLocalOscInitialize(long int* start_value_out){ { diff --git a/utils.h b/utils.h new file mode 100644 index 0000000..03ef80c --- /dev/null +++ b/utils.h @@ -0,0 +1,3 @@ +#pragma once + +#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) \ No newline at end of file From b805761415fa09de8ce03e33df153d0a8771d8d0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 14:10:08 -0800 Subject: [PATCH 133/324] Start building a menu 'class' --- menu.cpp | 30 ++++++++++++++++++++++++++++++ menu.h | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 menu.cpp create mode 100644 menu.h diff --git a/menu.cpp b/menu.cpp new file mode 100644 index 0000000..7ea45cb --- /dev/null +++ b/menu.cpp @@ -0,0 +1,30 @@ +#include "menu.h" + +bool runSubmenu(Menu_t* current_menu, + void(*redraw_callback)(), + ButtonPress_e tuner_button, + ButtonPress_e touch_button, + Point touch_point, + int16_t knob){ + if(nullptr != current_menu->active_submenu){ + auto ret = current_menu->active_submenu->runMenu(tuner_button,touch_button,touch_point,knob); + switch(ret){ + case MenuReturn_e::StillActive://Fallthrough intended + case MenuReturn_e::ExitedNoRedraw: + { + //Nothing to do here - just return + break; + } + default://Fallthrough intended. Default to this menu being active + case MenuReturn_e::ExitedRedraw: + { + //Turn off submenu, redraw, then return + current_menu->active_submenu = nullptr; + redraw_callback(); + break; + } + }//end switch + return true; + }//end submenu + return false; +} \ No newline at end of file diff --git a/menu.h b/menu.h new file mode 100644 index 0000000..1cca722 --- /dev/null +++ b/menu.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include "nano_gui.h"//Point + +enum MenuReturn_e : uint8_t { + StillActive, + ExitedRedraw, + ExitedNoRedraw +}; + +enum ButtonPress_e : uint8_t { + NotPressed, + ShortPress, + LongPress +} + +struct Menu_t { + MenuReturn_e (*runMenu)(ButtonPress_e tuner_button, + ButtonPress_e touch_button, + Point touch_point, + int16_t knob); + Menu_t* active_submenu; +}; + +static const uint8_t MENU_KNOB_COUNTS_PER_ITEM = 10; + +//Returns true if submenu was run, false otherwise +bool runSubmenu(Menu_t* current_menu, + void(*redraw_callback)(), + ButtonPress_e tuner_button, + ButtonPress_e touch_button, + Point touch_point, + int16_t knob); \ No newline at end of file From 801b1b08c1229a6002e307534754d6f6a7b8e6d9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 14:10:32 -0800 Subject: [PATCH 134/324] Rough out the main menu --- menu_main.cpp | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++ menu_main.h | 2 + 2 files changed, 134 insertions(+) create mode 100644 menu_main.cpp create mode 100644 menu_main.h diff --git a/menu_main.cpp b/menu_main.cpp new file mode 100644 index 0000000..e9a4985 --- /dev/null +++ b/menu_main.cpp @@ -0,0 +1,132 @@ +#include "menu_main.h" + +#include "morse.h" +#include "settings.h" +#include "utils.h" + +MenuReturn_e runMainMenu(ButtonPress_e tuner_button, + ButtonPress_e touch_button, + Point touch_point, + int16_t knob); + +Menu_t mainMenu = { + runMainMenu + nullptr +}; + +static Menu_t* const rootMenu = &mainMenu; + +bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or adjusting frequency +uint8_t mainMenuSelectedItemRaw = 0; + +void drawMainMenu(void) +{ + //TODO +} + +void mainMenuTune(int16_t knob) +{ + static uint32_t current_freq = 0; + + if((0 == knob) && (GetActiveVfoFreq() == current_freq)){ + //Nothing to do - we're already set! + return; + } + + current_freq = GetActiveVfoFreq(); + uint32_t new_freq = current_freq + (50 * knob); + + //Transition from below to above the traditional threshold for USB + if(current_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + } + + //Transition from above to below the traditional threshold for USB + if(current_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + } + + setFrequency(new_freq); + current_freq = new_freq; +} + +MenuReturn_e runMainMenu(ButtonPress_e tuner_button, + ButtonPress_e touch_button, + Point touch_point, + int16_t knob) +{ + if(runSubmenu(&mainMenu, + drawMainMenu, + tuner_button, + touch_button, + touch_point, + knob)){ + //Submenu processed the input, so return now + return MenuReturn_e::StillActive;//main menu always returns StillActive + }//end submenu + + //Submenu didn't run, so handle the inputs ourselves + + //Check tuner_button + if(ButtonPress_e::NotPressed != tuner_button){ + switch(tuner_button){ + default://Fallthrough intended + case ButtonPress_e::NotPressed: + { + //Nothing to do + break; + } + case ButtonPress_e::ShortPress: + { + if(mainMenuSelecting){ + uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + //TODO: activate button + } + mainMenuSelecting = !mainMenuSelecting; + + //Don't handle touch or knob on this run + return MenuReturn_e::StillActive;//main menu always returns StillActive + break; + } + case ButtonPress_e::LongPress: + { + if(!globalSettings.morseMenuOn){ + globalSettings.morseMenuOn = true;//set before playing + morseLetter(2); + } + else{ + morseLetter(4); + globalSettings.morseMenuOn = false;//unset after playing + } + SaveSettingsToEeprom(); + //Don't handle touch or knob on this run + return MenuReturn_e::StillActive;//main menu always returns StillActive + break; + } + }//switch + }//tuner_button + + else if(ButtonPress_e::NotPressed != touch_button){ + //We treat long and short presses the same, so no need to have a switch + Button b; + if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&b,touch_point)){ + //TODO: activate button + } + else{ + //Touch detected, but not on our buttons, so ignore + } + }//touch_button + + else{//Neither button input type found, so handle the knob + if(mainMenuSelecting){ + mainMenuSelectedItemRaw += LIMIT(mainMenuSelectedItemRaw+knob,0,MAIN_MENU_NUM_BUTTONS*MENU_KNOB_COUNTS_PER_ITEM); + } + else{ + mainMenuTune(knob); + } + } + + // + + return MenuReturn_e::StillActive;//main menu always returns StillActive +} \ No newline at end of file diff --git a/menu_main.h b/menu_main.h new file mode 100644 index 0000000..ec8ec84 --- /dev/null +++ b/menu_main.h @@ -0,0 +1,2 @@ +#include "menu.h" +extern static Menu_t* const rootMenu; From 21eb8978d5fb82816b16c0aaa5e60fc580dce9ac Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 14:52:21 -0800 Subject: [PATCH 135/324] Add selection --- menu_main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/menu_main.cpp b/menu_main.cpp index e9a4985..ef6ce4f 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -119,7 +119,12 @@ MenuReturn_e runMainMenu(ButtonPress_e tuner_button, else{//Neither button input type found, so handle the knob if(mainMenuSelecting){ + const uint8_t prev_select = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; mainMenuSelectedItemRaw += LIMIT(mainMenuSelectedItemRaw+knob,0,MAIN_MENU_NUM_BUTTONS*MENU_KNOB_COUNTS_PER_ITEM); + const uint8_t new_select = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + if(prev_select != new_select){ + movePuck(/*button[prev],button[new]*/);//TODO + } } else{ mainMenuTune(knob); From f42ad2bcd2c9849059d4e048d3104ecf2020c0c8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 15:28:46 -0800 Subject: [PATCH 136/324] Move button definition --- button.h | 9 +++++++++ ubitx_ui.cpp | 9 +-------- 2 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 button.h diff --git a/button.h b/button.h new file mode 100644 index 0000000..43d6bef --- /dev/null +++ b/button.h @@ -0,0 +1,9 @@ +#pragma once + +struct Button { + int x, y, w, h; + unsigned int id; + char text[5]; + char morse; + void (*morse_status)(int8_t* val_out);//-1 if a low tone should play, +1 if a high tone should play +}; \ No newline at end of file diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 4e0b0b8..e58b3bb 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -1,4 +1,5 @@ #include +#include "button.h" #include "morse.h" #include "nano_gui.h" #include "settings.h" @@ -79,14 +80,6 @@ enum btn_set_e { BUTTON_TOTAL }; -struct Button { - int x, y, w, h; - unsigned int id; - char text[5]; - char morse; - void (*morse_status)(int8_t* val_out);//-1 if a low tone should play, +1 if a high tone should play -}; - void msVfoA(int8_t* val_out){ *val_out = (Vfo_e::VFO_A == globalSettings.activeVfo) ? 1 : -1; } From a7a2655f022f5a75ab37274893db0f1318b500a5 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 15:29:48 -0800 Subject: [PATCH 137/324] Give readTouch a standard type --- nano_gui.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nano_gui.h b/nano_gui.h index d5a2253..c77176f 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -27,7 +27,7 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width = 0); /* touch functions */ -boolean readTouch(); +bool readTouch(); void scaleTouch(struct Point *p); From 8faa9c58c7d0a492a38630620d7fe7ad14457a09 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 15:30:37 -0800 Subject: [PATCH 138/324] Make function inputs const, and fix some compiler errors --- menu.cpp | 12 ++++++------ menu.h | 20 ++++++++++---------- menu_main.cpp | 22 ++++++++++++---------- menu_main.h | 2 +- 4 files changed, 29 insertions(+), 27 deletions(-) diff --git a/menu.cpp b/menu.cpp index 7ea45cb..43f3ca5 100644 --- a/menu.cpp +++ b/menu.cpp @@ -1,11 +1,11 @@ #include "menu.h" -bool runSubmenu(Menu_t* current_menu, - void(*redraw_callback)(), - ButtonPress_e tuner_button, - ButtonPress_e touch_button, - Point touch_point, - int16_t knob){ +bool runSubmenu(Menu_t* const current_menu, + void(*const redraw_callback)(), + const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob){ if(nullptr != current_menu->active_submenu){ auto ret = current_menu->active_submenu->runMenu(tuner_button,touch_button,touch_point,knob); switch(ret){ diff --git a/menu.h b/menu.h index 1cca722..15a6819 100644 --- a/menu.h +++ b/menu.h @@ -13,13 +13,13 @@ enum ButtonPress_e : uint8_t { NotPressed, ShortPress, LongPress -} +}; struct Menu_t { - MenuReturn_e (*runMenu)(ButtonPress_e tuner_button, - ButtonPress_e touch_button, - Point touch_point, - int16_t knob); + MenuReturn_e (*const runMenu)(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); Menu_t* active_submenu; }; @@ -27,8 +27,8 @@ static const uint8_t MENU_KNOB_COUNTS_PER_ITEM = 10; //Returns true if submenu was run, false otherwise bool runSubmenu(Menu_t* current_menu, - void(*redraw_callback)(), - ButtonPress_e tuner_button, - ButtonPress_e touch_button, - Point touch_point, - int16_t knob); \ No newline at end of file + void(*const redraw_callback)(), + const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); \ No newline at end of file diff --git a/menu_main.cpp b/menu_main.cpp index ef6ce4f..3b8ad5b 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -1,20 +1,22 @@ #include "menu_main.h" +#include "button.h" #include "morse.h" #include "settings.h" +#include "ubitx.h"//THRESHOLD_USB_LSB #include "utils.h" -MenuReturn_e runMainMenu(ButtonPress_e tuner_button, - ButtonPress_e touch_button, - Point touch_point, - int16_t knob); +MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); Menu_t mainMenu = { - runMainMenu + runMainMenu, nullptr }; -static Menu_t* const rootMenu = &mainMenu; +Menu_t* const rootMenu = &mainMenu; bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or adjusting frequency uint8_t mainMenuSelectedItemRaw = 0; @@ -50,10 +52,10 @@ void mainMenuTune(int16_t knob) current_freq = new_freq; } -MenuReturn_e runMainMenu(ButtonPress_e tuner_button, - ButtonPress_e touch_button, - Point touch_point, - int16_t knob) +MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob) { if(runSubmenu(&mainMenu, drawMainMenu, diff --git a/menu_main.h b/menu_main.h index ec8ec84..9be09c0 100644 --- a/menu_main.h +++ b/menu_main.h @@ -1,2 +1,2 @@ #include "menu.h" -extern static Menu_t* const rootMenu; +extern Menu_t* const rootMenu; From 5fb47187a690fd4122d17bdf5789af8e0a784807 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 15:42:37 -0800 Subject: [PATCH 139/324] Add definition for movePuck --- menu.cpp | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/menu.cpp b/menu.cpp index 43f3ca5..1aa6b8b 100644 --- a/menu.cpp +++ b/menu.cpp @@ -1,4 +1,5 @@ #include "menu.h" +#include "nano_gui.h" bool runSubmenu(Menu_t* const current_menu, void(*const redraw_callback)(), @@ -27,4 +28,16 @@ bool runSubmenu(Menu_t* const current_menu, return true; }//end submenu return false; -} \ No newline at end of file +} + +void movePuck(const Button *const b_old, + const Button *const b_new) +{ + if(nullptr != b_old){ + displayRect(b_old->x,b_old->y,b_old->w,b_old->h,COLOR_INACTIVE_BORDER); + } + if(nullptr != b_new){ + displayRect(b_new->x,b_new->y,b_new->w,b_new->h,COLOR_ACTIVE_BORDER); + } +} + From e2249af82688eb696b564ddfe403e873d0ead333 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 15:56:43 -0800 Subject: [PATCH 140/324] Move color definitions to their own file --- color_theme.h | 22 ++++++++++++++++++++++ colors.h | 20 ++++++++++++++++++++ menu.cpp | 3 +++ menu.h | 6 +++++- menu_main.cpp | 11 ++++++++++- nano_gui.cpp | 1 + nano_gui.h | 21 --------------------- setup.cpp | 1 + ubitx_ui.cpp | 20 +------------------- 9 files changed, 63 insertions(+), 42 deletions(-) create mode 100644 color_theme.h create mode 100644 colors.h diff --git a/color_theme.h b/color_theme.h new file mode 100644 index 0000000..d76155e --- /dev/null +++ b/color_theme.h @@ -0,0 +1,22 @@ +#pragma once + +#include "colors.h" + +static const unsigned int COLOR_TEXT = DISPLAY_WHITE; +static const unsigned int COLOR_BACKGROUND = DISPLAY_NAVY; + +static const unsigned int COLOR_ACTIVE_VFO_TEXT = DISPLAY_WHITE; +static const unsigned int COLOR_ACTIVE_VFO_BACKGROUND = DISPLAY_BLACK; + +static const unsigned int COLOR_INACTIVE_VFO_TEXT = DISPLAY_GREEN; +static const unsigned int COLOR_INACTIVE_VFO_BACKGROUND = DISPLAY_BLACK; + +static const unsigned int COLOR_INACTIVE_TEXT = DISPLAY_GREEN; +static const unsigned int COLOR_INACTIVE_BACKGROUND = DISPLAY_BLACK; +static const unsigned int COLOR_INACTIVE_BORDER = DISPLAY_DARKGREY; + +static const unsigned int COLOR_ACTIVE_TEXT = DISPLAY_BLACK; +static const unsigned int COLOR_ACTIVE_BACKGROUND = DISPLAY_ORANGE; +static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; + +static const unsigned int COLOR_VERSION_TEXT = DISPLAY_LIGHTGREY; \ No newline at end of file diff --git a/colors.h b/colors.h new file mode 100644 index 0000000..1743dbe --- /dev/null +++ b/colors.h @@ -0,0 +1,20 @@ +// Color definitions +#define DISPLAY_BLACK 0x0000 ///< 0, 0, 0 +#define DISPLAY_NAVY 0x000F ///< 0, 0, 123 +#define DISPLAY_DARKGREEN 0x03E0 ///< 0, 125, 0 +#define DISPLAY_DARKCYAN 0x03EF ///< 0, 125, 123 +#define DISPLAY_MAROON 0x7800 ///< 123, 0, 0 +#define DISPLAY_PURPLE 0x780F ///< 123, 0, 123 +#define DISPLAY_OLIVE 0x7BE0 ///< 123, 125, 0 +#define DISPLAY_LIGHTGREY 0xC618 ///< 198, 195, 198 +#define DISPLAY_DARKGREY 0x7BEF ///< 123, 125, 123 +#define DISPLAY_BLUE 0x001F ///< 0, 0, 255 +#define DISPLAY_GREEN 0x07E0 ///< 0, 255, 0 +#define DISPLAY_CYAN 0x07FF ///< 0, 255, 255 +#define DISPLAY_RED 0xF800 ///< 255, 0, 0 +#define DISPLAY_MAGENTA 0xF81F ///< 255, 0, 255 +#define DISPLAY_YELLOW 0xFFE0 ///< 255, 255, 0 +#define DISPLAY_WHITE 0xFFFF ///< 255, 255, 255 +#define DISPLAY_ORANGE 0xFD20 ///< 255, 165, 0 +#define DISPLAY_GREENYELLOW 0xAFE5 ///< 173, 255, 41 +#define DISPLAY_PINK 0xFC18 ///< 255, 130, 198 diff --git a/menu.cpp b/menu.cpp index 1aa6b8b..174892e 100644 --- a/menu.cpp +++ b/menu.cpp @@ -1,4 +1,7 @@ #include "menu.h" + +#include "button.h" +#include "color_theme.h" #include "nano_gui.h" bool runSubmenu(Menu_t* const current_menu, diff --git a/menu.h b/menu.h index 15a6819..21b226a 100644 --- a/menu.h +++ b/menu.h @@ -1,6 +1,7 @@ #pragma once #include +#include "button.h" #include "nano_gui.h"//Point enum MenuReturn_e : uint8_t { @@ -31,4 +32,7 @@ bool runSubmenu(Menu_t* current_menu, const ButtonPress_e tuner_button, const ButtonPress_e touch_button, const Point touch_point, - const int16_t knob); \ No newline at end of file + const int16_t knob); + +void movePuck(const Button *const b_old, + const Button *const b_new); diff --git a/menu_main.cpp b/menu_main.cpp index 3b8ad5b..518525f 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -1,5 +1,7 @@ #include "menu_main.h" +#include + #include "button.h" #include "morse.h" #include "settings.h" @@ -21,6 +23,8 @@ Menu_t* const rootMenu = &mainMenu; bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or adjusting frequency uint8_t mainMenuSelectedItemRaw = 0; +const Button mainMenuButtons [] PROGMEM = {}; + void drawMainMenu(void) { //TODO @@ -64,6 +68,8 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, touch_point, knob)){ //Submenu processed the input, so return now + mainMenuSelectedItemRaw = 0; + mainMenuSelecting = false; return MenuReturn_e::StillActive;//main menu always returns StillActive }//end submenu @@ -84,6 +90,9 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; //TODO: activate button } + else{ + movePuck(nullptr,&mainMenuButtons[0]); + } mainMenuSelecting = !mainMenuSelecting; //Don't handle touch or knob on this run @@ -125,7 +134,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, mainMenuSelectedItemRaw += LIMIT(mainMenuSelectedItemRaw+knob,0,MAIN_MENU_NUM_BUTTONS*MENU_KNOB_COUNTS_PER_ITEM); const uint8_t new_select = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; if(prev_select != new_select){ - movePuck(/*button[prev],button[new]*/);//TODO + movePuck(&mainMenuButtons[prev_select],&mainMenuButtons[new_select]);//TODO } } else{ diff --git a/nano_gui.cpp b/nano_gui.cpp index 5753e44..5ef0429 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -1,4 +1,5 @@ #include +#include "colors.h" #include "settings.h" #include "ubitx.h" #include "nano_gui.h" diff --git a/nano_gui.h b/nano_gui.h index c77176f..5ca5582 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -31,27 +31,6 @@ bool readTouch(); void scaleTouch(struct Point *p); -// Color definitions -#define DISPLAY_BLACK 0x0000 ///< 0, 0, 0 -#define DISPLAY_NAVY 0x000F ///< 0, 0, 123 -#define DISPLAY_DARKGREEN 0x03E0 ///< 0, 125, 0 -#define DISPLAY_DARKCYAN 0x03EF ///< 0, 125, 123 -#define DISPLAY_MAROON 0x7800 ///< 123, 0, 0 -#define DISPLAY_PURPLE 0x780F ///< 123, 0, 123 -#define DISPLAY_OLIVE 0x7BE0 ///< 123, 125, 0 -#define DISPLAY_LIGHTGREY 0xC618 ///< 198, 195, 198 -#define DISPLAY_DARKGREY 0x7BEF ///< 123, 125, 123 -#define DISPLAY_BLUE 0x001F ///< 0, 0, 255 -#define DISPLAY_GREEN 0x07E0 ///< 0, 255, 0 -#define DISPLAY_CYAN 0x07FF ///< 0, 255, 255 -#define DISPLAY_RED 0xF800 ///< 255, 0, 0 -#define DISPLAY_MAGENTA 0xF81F ///< 255, 0, 255 -#define DISPLAY_YELLOW 0xFFE0 ///< 255, 255, 0 -#define DISPLAY_WHITE 0xFFFF ///< 255, 255, 255 -#define DISPLAY_ORANGE 0xFD20 ///< 255, 165, 0 -#define DISPLAY_GREENYELLOW 0xAFE5 ///< 173, 255, 41 -#define DISPLAY_PINK 0xFC18 ///< 255, 130, 198 - #define TEXT_LINE_HEIGHT 18 #define TEXT_LINE_INDENT 5 diff --git a/setup.cpp b/setup.cpp index 284f16e..7f7085a 100644 --- a/setup.cpp +++ b/setup.cpp @@ -1,4 +1,5 @@ #include +#include "colors.h" #include "morse.h" #include "nano_gui.h" #include "setup.h" diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index e58b3bb..c31d8b3 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -1,5 +1,6 @@ #include #include "button.h" +#include "color_theme.h" #include "morse.h" #include "nano_gui.h" #include "settings.h" @@ -7,25 +8,6 @@ #include "ubitx.h" #include "version.h" -static const unsigned int COLOR_TEXT = DISPLAY_WHITE; -static const unsigned int COLOR_BACKGROUND = DISPLAY_NAVY; - -static const unsigned int COLOR_ACTIVE_VFO_TEXT = DISPLAY_WHITE; -static const unsigned int COLOR_ACTIVE_VFO_BACKGROUND = DISPLAY_BLACK; - -static const unsigned int COLOR_INACTIVE_VFO_TEXT = DISPLAY_GREEN; -static const unsigned int COLOR_INACTIVE_VFO_BACKGROUND = DISPLAY_BLACK; - -static const unsigned int COLOR_INACTIVE_TEXT = DISPLAY_GREEN; -static const unsigned int COLOR_INACTIVE_BACKGROUND = DISPLAY_BLACK; -static const unsigned int COLOR_INACTIVE_BORDER = DISPLAY_DARKGREY; - -static const unsigned int COLOR_ACTIVE_TEXT = DISPLAY_BLACK; -static const unsigned int COLOR_ACTIVE_BACKGROUND = DISPLAY_ORANGE; -static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; - -static const unsigned int COLOR_VERSION_TEXT = DISPLAY_LIGHTGREY; - static const unsigned int LAYOUT_VFO_LABEL_X = 0; static const unsigned int LAYOUT_VFO_LABEL_Y = 10; static const unsigned int LAYOUT_VFO_LABEL_WIDTH = 159; From 49c5607dd32dcaf1c1a555145f8f3f3b21199b24 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 16:01:52 -0800 Subject: [PATCH 141/324] Move menu utils to their own file --- menu.h | 12 ------------ menu.cpp => menu_utils.cpp | 0 menu_utils.h | 14 ++++++++++++++ 3 files changed, 14 insertions(+), 12 deletions(-) rename menu.cpp => menu_utils.cpp (100%) create mode 100644 menu_utils.h diff --git a/menu.h b/menu.h index 21b226a..c13cd42 100644 --- a/menu.h +++ b/menu.h @@ -1,7 +1,6 @@ #pragma once #include -#include "button.h" #include "nano_gui.h"//Point enum MenuReturn_e : uint8_t { @@ -25,14 +24,3 @@ struct Menu_t { }; static const uint8_t MENU_KNOB_COUNTS_PER_ITEM = 10; - -//Returns true if submenu was run, false otherwise -bool runSubmenu(Menu_t* current_menu, - void(*const redraw_callback)(), - const ButtonPress_e tuner_button, - const ButtonPress_e touch_button, - const Point touch_point, - const int16_t knob); - -void movePuck(const Button *const b_old, - const Button *const b_new); diff --git a/menu.cpp b/menu_utils.cpp similarity index 100% rename from menu.cpp rename to menu_utils.cpp diff --git a/menu_utils.h b/menu_utils.h new file mode 100644 index 0000000..1441afb --- /dev/null +++ b/menu_utils.h @@ -0,0 +1,14 @@ +#pragma once + +#include "button.h" + +//Returns true if submenu was run, false otherwise +bool runSubmenu(Menu_t* current_menu, + void(*const redraw_callback)(), + const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); + +void movePuck(const Button *const b_old, + const Button *const b_new); From e42b21fdf3364c48f18ee45481fad1b005332ad0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 16:16:57 -0800 Subject: [PATCH 142/324] Add touch button finding util --- menu_utils.cpp | 19 +++++++++++++++++++ menu_utils.h | 6 ++++++ 2 files changed, 25 insertions(+) diff --git a/menu_utils.cpp b/menu_utils.cpp index 174892e..7254b81 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -1,5 +1,7 @@ #include "menu.h" +#include + #include "button.h" #include "color_theme.h" #include "nano_gui.h" @@ -44,3 +46,20 @@ void movePuck(const Button *const b_old, } } +bool findPressedButton(const Button *const buttons, + const uint8_t num_buttons, + Button *const button_out, + const Point touch_point) +{ + for(uint16_t i = 0; i < num_buttons; ++i){ + if((buttons[i].x <= touch_point.x) + &&(touch_point.x <= buttons[i].x + buttons[i].w) + &&(buttons[i].y <= touch_point.y) + &&(touch_point.y <= buttons[i].y + buttons[i].h)){ + memcpy_P(button_out,&buttons[i],sizeof(button_out)); + return true; + } + } + + return false; +} diff --git a/menu_utils.h b/menu_utils.h index 1441afb..a748b21 100644 --- a/menu_utils.h +++ b/menu_utils.h @@ -12,3 +12,9 @@ bool runSubmenu(Menu_t* current_menu, void movePuck(const Button *const b_old, const Button *const b_new); + +//Returns true if button was found, false otherwise +bool findPressedButton(const Button *const buttons, + const uint8_t num_buttons, + Button *const button_out, + const Point touch_point); \ No newline at end of file From 66a9d823084fb9de3703e3950b94cb9f53c8237b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 16:17:18 -0800 Subject: [PATCH 143/324] Set size variable for main menu button array --- menu_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/menu_main.cpp b/menu_main.cpp index 518525f..4f7d71d 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -3,6 +3,7 @@ #include #include "button.h" +#include "menu_utils.h" #include "morse.h" #include "settings.h" #include "ubitx.h"//THRESHOLD_USB_LSB @@ -24,6 +25,7 @@ bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or uint8_t mainMenuSelectedItemRaw = 0; const Button mainMenuButtons [] PROGMEM = {}; +static constexpr uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); void drawMainMenu(void) { From 79a37620c2ef5ab70095d3ec0b7e8bc6fa1c0824 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 16:31:24 -0800 Subject: [PATCH 144/324] Play morse when selecting --- menu_main.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 4f7d71d..27e18b8 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -121,8 +121,8 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, else if(ButtonPress_e::NotPressed != touch_button){ //We treat long and short presses the same, so no need to have a switch - Button b; - if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&b,touch_point)){ + Button button; + if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&button,touch_point)){ //TODO: activate button } else{ @@ -137,6 +137,15 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, const uint8_t new_select = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; if(prev_select != new_select){ movePuck(&mainMenuButtons[prev_select],&mainMenuButtons[new_select]);//TODO + morseLetter(mainMenuButtons[new_select].morse); + int8_t morse_status = 0; + mainMenuButtons[new_select].morse_status(morse_status); + if(morse_status < 0){ + morseBool(false); + } + else if(morse_status > 0){ + morseBool(true); + } } } else{ From 5a12a636be59ac1618f54816c012c496bcf4e3e3 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 17:03:37 -0800 Subject: [PATCH 145/324] Make button aware of it's types --- button.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/button.h b/button.h index 43d6bef..74976b5 100644 --- a/button.h +++ b/button.h @@ -1,5 +1,7 @@ #pragma once +#include + struct Button { int x, y, w, h; unsigned int id; From 9e21faa6f132362182931c123e6c3b3c54ddc2cb Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 17:04:00 -0800 Subject: [PATCH 146/324] morseText should take a const char* --- morse.cpp | 2 +- morse.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/morse.cpp b/morse.cpp index 9dc2931..0a9596d 100644 --- a/morse.cpp +++ b/morse.cpp @@ -106,7 +106,7 @@ void morseLetter(char c, uint16_t dit_duration_ms){ } static const uint8_t RELATIVE_OFFSET_HZ = 100; -void morseText(char *text, uint16_t dit_duration_ms){ +void morseText(const char *text, uint16_t dit_duration_ms){ int16_t total_counts = 0; morseBool(false); enc_read();//Don't count initial tone against total_counts diff --git a/morse.h b/morse.h index 44ed35a..b842996 100644 --- a/morse.h +++ b/morse.h @@ -1,7 +1,7 @@ #include "settings.h" //sends out morse code at the speed set by cwSpeed void morseLetter(char c, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); -void morseText(char *text, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); +void morseText(const char *text, uint16_t dit_duration_ms = globalSettings.cwDitDurationMs); //Plays either a higher or lower tone to indicate a boolean value void morseBool(bool val); From 5e30551bf293d4c7aa50515535224638de188a9f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 17:04:47 -0800 Subject: [PATCH 147/324] Move selector logic to menu_utils --- menu_main.cpp | 27 +++++++------------ menu_utils.cpp | 72 +++++++++++++++++++++++++++++++++++++++++--------- menu_utils.h | 21 ++++++++++++--- 3 files changed, 87 insertions(+), 33 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 27e18b8..58b4c97 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -22,7 +22,7 @@ Menu_t mainMenu = { Menu_t* const rootMenu = &mainMenu; bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or adjusting frequency -uint8_t mainMenuSelectedItemRaw = 0; +int16_t mainMenuSelectedItemRaw = 0;//Allow negative only for easier checks on wrap around const Button mainMenuButtons [] PROGMEM = {}; static constexpr uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); @@ -93,7 +93,10 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, //TODO: activate button } else{ - movePuck(nullptr,&mainMenuButtons[0]); + initSelector(&mainMenuSelectedItemRaw, + mainMenuButtons, + MAIN_MENU_NUM_BUTTONS, + MorsePlaybackType_e::PlayChar); } mainMenuSelecting = !mainMenuSelecting; @@ -132,21 +135,11 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, else{//Neither button input type found, so handle the knob if(mainMenuSelecting){ - const uint8_t prev_select = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; - mainMenuSelectedItemRaw += LIMIT(mainMenuSelectedItemRaw+knob,0,MAIN_MENU_NUM_BUTTONS*MENU_KNOB_COUNTS_PER_ITEM); - const uint8_t new_select = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; - if(prev_select != new_select){ - movePuck(&mainMenuButtons[prev_select],&mainMenuButtons[new_select]);//TODO - morseLetter(mainMenuButtons[new_select].morse); - int8_t morse_status = 0; - mainMenuButtons[new_select].morse_status(morse_status); - if(morse_status < 0){ - morseBool(false); - } - else if(morse_status > 0){ - morseBool(true); - } - } + adjustSelector(&mainMenuSelectedItemRaw, + knob, + mainMenuButtons, + MAIN_MENU_NUM_BUTTONS, + MorsePlaybackType_e::PlayChar); } else{ mainMenuTune(knob); diff --git a/menu_utils.cpp b/menu_utils.cpp index 7254b81..ff6274c 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -1,10 +1,12 @@ -#include "menu.h" +#include "menu_utils.h" #include #include "button.h" #include "color_theme.h" +#include "morse.h" #include "nano_gui.h" +#include "utils.h" bool runSubmenu(Menu_t* const current_menu, void(*const redraw_callback)(), @@ -35,17 +37,6 @@ bool runSubmenu(Menu_t* const current_menu, return false; } -void movePuck(const Button *const b_old, - const Button *const b_new) -{ - if(nullptr != b_old){ - displayRect(b_old->x,b_old->y,b_old->w,b_old->h,COLOR_INACTIVE_BORDER); - } - if(nullptr != b_new){ - displayRect(b_new->x,b_new->y,b_new->w,b_new->h,COLOR_ACTIVE_BORDER); - } -} - bool findPressedButton(const Button *const buttons, const uint8_t num_buttons, Button *const button_out, @@ -63,3 +54,60 @@ bool findPressedButton(const Button *const buttons, return false; } + +void movePuck(const Button *const b_old, + const Button *const b_new) +{ + if(nullptr != b_old){ + displayRect(b_old->x,b_old->y,b_old->w,b_old->h,COLOR_INACTIVE_BORDER); + } + if(nullptr != b_new){ + displayRect(b_new->x,b_new->y,b_new->w,b_new->h,COLOR_ACTIVE_BORDER); + } +} + +void playButtonMorse(const Button *const button, + const MorsePlaybackType_e play_type) +{ + if(MorsePlaybackType_e::PlayText == play_type){ + morseText(button->text); + } + else{ + morseLetter(button->morse); + } + + int8_t morse_status = 0; + button->morse_status(&morse_status); + if(morse_status < 0){ + morseBool(false); + } + else if(morse_status > 0){ + morseBool(true); + } +} + +void initSelector(int16_t *const raw_select_val_in_out, + const Button *const buttons, + const uint8_t num_buttons, + const MorsePlaybackType_e play_type) +{ + *raw_select_val_in_out = 0; + if(0 < num_buttons){ + playButtonMorse(&buttons[0],play_type); + } +} + +void adjustSelector(int16_t *const raw_select_val_in_out, + const int16_t knob, + const Button *const buttons, + const uint8_t num_buttons, + const MorsePlaybackType_e play_type) +{ + const uint8_t prev_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; + *raw_select_val_in_out += LIMIT((*raw_select_val_in_out)+knob,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1); + const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; + if(prev_select != new_select){ + movePuck(&buttons[prev_select],&buttons[new_select]); + playButtonMorse(&buttons[new_select],play_type); + } +} diff --git a/menu_utils.h b/menu_utils.h index a748b21..4de02d8 100644 --- a/menu_utils.h +++ b/menu_utils.h @@ -1,6 +1,7 @@ #pragma once #include "button.h" +#include "menu.h" //Returns true if submenu was run, false otherwise bool runSubmenu(Menu_t* current_menu, @@ -10,11 +11,23 @@ bool runSubmenu(Menu_t* current_menu, const Point touch_point, const int16_t knob); -void movePuck(const Button *const b_old, - const Button *const b_new); - //Returns true if button was found, false otherwise bool findPressedButton(const Button *const buttons, const uint8_t num_buttons, Button *const button_out, - const Point touch_point); \ No newline at end of file + const Point touch_point); + +enum MorsePlaybackType_e : uint8_t { + PlayChar, + PlayText +}; +void initSelector(int16_t *const raw_select_val_in_out, + const Button *const buttons, + const uint8_t num_buttons, + const MorsePlaybackType_e); + +void adjustSelector(int16_t *const raw_select_val_in_out, + int16_t knob, + const Button *const buttons, + const uint8_t num_buttons, + const MorsePlaybackType_e); From d9667d675699f5645c59cc5450205f024f5bfbef Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 17:09:46 -0800 Subject: [PATCH 148/324] Add some debugging lines for now --- menu_main.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/menu_main.cpp b/menu_main.cpp index 58b4c97..cd858e9 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -1,6 +1,7 @@ #include "menu_main.h" #include +#include #include "button.h" #include "menu_utils.h" @@ -91,6 +92,10 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, if(mainMenuSelecting){ uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; //TODO: activate button + Serial.print(F("Select button ")); + Serial.print(menu_index); + Serial.print(F(":")); + Serial.println(mainMenuButtons[menu_index].text); } else{ initSelector(&mainMenuSelectedItemRaw, @@ -127,9 +132,12 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, Button button; if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&button,touch_point)){ //TODO: activate button + Serial.print(F("Touch button ")); + Serial.println(button.text); } else{ //Touch detected, but not on our buttons, so ignore + Serial.println(F("Touch not on button")); } }//touch_button From bd616caaba9aebaa52854145e38b59d48a435fc0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 17:58:45 -0800 Subject: [PATCH 149/324] Have touch functions read to passed pointer --- nano_gui.cpp | 22 +++++++++++----------- nano_gui.h | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index 5ef0429..4fcd79a 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -145,18 +145,18 @@ static void touch_update(){ } -bool readTouch(){ +bool readTouch(Point *const touch_point_out){ touch_update(); if (zraw >= Z_THRESHOLD) { - ts_point.x = xraw; - ts_point.y = yraw; + touch_point_out->x = xraw; + touch_point_out->y = yraw; //Serial.print(ts_point.x); Serial.print(",");Serial.println(ts_point.y); return true; } return false; } -void scaleTouch(struct Point *p){ +void scaleTouch(Point *const p){ p->x = ((long)(p->x - globalSettings.touchOffsetX) * 10L)/ (long)globalSettings.touchSlopeX; p->y = ((long)(p->y - globalSettings.touchOffsetY) * 10L)/ (long)globalSettings.touchSlopeY; @@ -267,9 +267,9 @@ void setupTouch(){ displayHline(10,20,20,DISPLAY_WHITE); displayVline(20,10,20, DISPLAY_WHITE); - while(!readTouch()) + while(!readTouch(&ts_point)) delay(100); - while(readTouch()) + while(readTouch(&ts_point)) delay(100); x1 = ts_point.x; y1 = ts_point.y; @@ -284,9 +284,9 @@ void setupTouch(){ displayHline(290,20,20,DISPLAY_WHITE); displayVline(300,10,20, DISPLAY_WHITE); - while(!readTouch()) + while(!readTouch(&ts_point)) delay(100); - while(readTouch()) + while(readTouch(&ts_point)) delay(100); x2 = ts_point.x; y2 = ts_point.y; @@ -300,12 +300,12 @@ void setupTouch(){ displayHline(10,220,20,DISPLAY_WHITE); displayVline(20,210,20, DISPLAY_WHITE); - while(!readTouch()) + while(!readTouch(&ts_point)) delay(100); x3 = ts_point.x; y3 = ts_point.y; - while(readTouch()) + while(readTouch(&ts_point)) delay(100); displayHline(10,220,20,DISPLAY_BLACK); displayVline(20,210,20, DISPLAY_BLACK); @@ -316,7 +316,7 @@ void setupTouch(){ displayHline(290,220,20,DISPLAY_WHITE); displayVline(300,210,20, DISPLAY_WHITE); - while(!readTouch()) + while(!readTouch(&ts_point)) delay(100); x4 = ts_point.x; y4 = ts_point.y; diff --git a/nano_gui.h b/nano_gui.h index 5ca5582..37d9826 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -27,9 +27,9 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width = 0); /* touch functions */ -bool readTouch(); +bool readTouch(Point *const p); -void scaleTouch(struct Point *p); +void scaleTouch(Point *const p); #define TEXT_LINE_HEIGHT 18 #define TEXT_LINE_INDENT 5 From e50857f181d7ef252f415e29e6edc65295f8c4c9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 17:59:29 -0800 Subject: [PATCH 150/324] Have checkTouch support ButtonPress_e --- ubitx.h | 3 ++- ubitx_ui.cpp | 47 ++++++++++++++++++++++++++--------------------- 2 files changed, 28 insertions(+), 22 deletions(-) diff --git a/ubitx.h b/ubitx.h index 3218d9f..5262559 100644 --- a/ubitx.h +++ b/ubitx.h @@ -120,7 +120,8 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* //main functions to check if any button is pressed and other user interface events void doCommands(); //does the commands with encoder to jump from button to button -void checkTouch(); //does the commands with a touch on the buttons +#include "menu.h" +ButtonPress_e checkTouch(Point *const touch_point_out); //does the commands with a touch on the buttons diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index c31d8b3..c8ad956 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -418,7 +418,7 @@ void enterFreq(){ active_delay(50); break; } - if(!readTouch()) + if(!readTouch(&ts_point)) continue; scaleTouch(&ts_point); @@ -508,7 +508,7 @@ void enterFreq(){ strncat_P(b,(const char*)F(" KHz"),sizeof(b) - strlen(b)); displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); active_delay(300); - while(readTouch()) + while(readTouch(&ts_point)) checkCAT(); } // end of event loop : while(!exit) @@ -811,27 +811,32 @@ void doCommand(Button* button){ } } -void checkTouch(){ - if (!readTouch()) - return; - - while(readTouch()) - checkCAT(); - scaleTouch(&ts_point); - - /* //debug code - Serial.print(ts_point.x); Serial.print(' ');Serial.println(ts_point.y); - */ - for (int i = 0; i < BUTTON_TOTAL; i++){ - Button button; - memcpy_P(&button, &(btn_set[i]), sizeof(Button)); +#include "menu.h" +static const uint8_t DEBOUNCE_DELAY_MS = 50; +static const uint16_t LONG_PRESS_TIME_MS = 3000; +static const uint8_t LONG_PRESS_POLL_TIME_MS = 10; +ButtonPress_e checkTouch(Point *const touch_point_out){ + if (!readTouch(touch_point_out)){ + return ButtonPress_e::NotPressed; + } + delay(DEBOUNCE_DELAY_MS); + if (!readTouch(touch_point_out)){//debounce + return ButtonPress_e::NotPressed; + } + + uint16_t down_time = 0; + while(readTouch(touch_point_out) && (down_time < LONG_PRESS_TIME_MS)){ + delay(LONG_PRESS_POLL_TIME_MS); + down_time += LONG_PRESS_POLL_TIME_MS; + } - int x2 = button.x + button.w; - int y2 = button.y + button.h; + scaleTouch(touch_point_out); - if(button.x < ts_point.x && ts_point.x < x2 && - button.y < ts_point.y && ts_point.y < y2) - doCommand(&button); + if(down_time < LONG_PRESS_TIME_MS){ + return ButtonPress_e::ShortPress; + } + else{ + return ButtonPress_e::LongPress; } } From b29bd955ca2ee41de204ade2fed0c7b0c97b73c9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 17:59:58 -0800 Subject: [PATCH 151/324] Swap loop logic for new menu logic --- ubitxv6.ino | 78 +++++++++++++++++++++++------------------------------ 1 file changed, 34 insertions(+), 44 deletions(-) diff --git a/ubitxv6.ino b/ubitxv6.ino index dc291ae..b0febb6 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -30,6 +30,8 @@ * Si5351 object to control the clocks. */ #include +#include "menu.h" +#include "menu_main.h" #include "morse.h" #include "nano_gui.h" #include "settings.h" @@ -302,41 +304,30 @@ void checkPTT(){ } //check if the encoder button was pressed -void checkButton(){ - //only if the button is pressed - if (!btnDown()) - return; - active_delay(50); - if (!btnDown()) //debounce - return; +static const uint8_t DEBOUNCE_DELAY_MS = 50; +static const uint16_t LONG_PRESS_TIME_MS = 3000; +static const uint8_t LONG_PRESS_POLL_TIME_MS = 10; +ButtonPress_e checkButton(){ + if (!btnDown()){ + return ButtonPress_e::NotPressed; + } + delay(DEBOUNCE_DELAY_MS); + if (!btnDown()){//debounce + return ButtonPress_e::NotPressed; + } - //disengage any CAT work - doingCAT = 0; - - int downTime = 0; - while(btnDown()){ - active_delay(10); - downTime++; - if (downTime > 300){ - if(!globalSettings.morseMenuOn){ - globalSettings.morseMenuOn = true;//set before playing - morseLetter(2); - } - else{ - morseLetter(4); - globalSettings.morseMenuOn = false;//unset after playing - } - SaveSettingsToEeprom(); - return; - } + uint16_t down_time = 0; + while(btnDown() && (down_time < LONG_PRESS_TIME_MS)){ + delay(LONG_PRESS_POLL_TIME_MS); + down_time += LONG_PRESS_POLL_TIME_MS; } - active_delay(100); - doCommands(); - //wait for the button to go up again - while(btnDown()) - active_delay(10); - active_delay(50);//debounce + if(down_time < LONG_PRESS_TIME_MS){ + return ButtonPress_e::ShortPress; + } + else{ + return ButtonPress_e::LongPress; + } } void switchVFO(Vfo_e new_vfo){ @@ -502,18 +493,17 @@ void loop(){ else if(!globalSettings.txCatActive){ checkPTT(); } - - checkButton(); - //tune only when not tranmsitting - if(!globalSettings.txActive){ - if(globalSettings.ritOn){ - doRIT(); - } - else{ - doTuning(); - } - checkTouch(); - } checkCAT(); + + if(globalSettings.txActive){ + //Don't run menus when transmitting + return; + } + + ButtonPress_e tuner_button = checkButton(); + Point touch_point; + ButtonPress_e touch_button = checkTouch(&touch_point); + int16_t knob = enc_read(); + rootMenu->runMenu(tuner_button,touch_button,touch_point,knob); } From 72fc92b58481709ba2b64ff72e365e58e6b78163 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 18:40:42 -0800 Subject: [PATCH 152/324] Add classes for button timing variables and point --- button_timing.h | 5 +++++ point.h | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 button_timing.h create mode 100644 point.h diff --git a/button_timing.h b/button_timing.h new file mode 100644 index 0000000..fdac0ea --- /dev/null +++ b/button_timing.h @@ -0,0 +1,5 @@ +#pragma once + +static const uint8_t DEBOUNCE_DELAY_MS = 50; +static const uint16_t LONG_PRESS_TIME_MS = 3000; +static const uint8_t LONG_PRESS_POLL_TIME_MS = 10; \ No newline at end of file diff --git a/point.h b/point.h new file mode 100644 index 0000000..f716a8d --- /dev/null +++ b/point.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +struct Point { + int16_t x; + int16_t y; +}; From 947624518d824e416ff7fcf0004bed3aa4e10362 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 18:41:13 -0800 Subject: [PATCH 153/324] Move touch functions to their own files --- nano_gui.cpp | 130 ++------------------------------------------------- nano_gui.h | 11 ----- touch.cpp | 111 +++++++++++++++++++++++++++++++++++++++++++ touch.h | 11 +++++ ui_touch.cpp | 31 ++++++++++++ ui_touch.h | 6 +++ 6 files changed, 162 insertions(+), 138 deletions(-) create mode 100644 touch.cpp create mode 100644 touch.h create mode 100644 ui_touch.cpp create mode 100644 ui_touch.h diff --git a/nano_gui.cpp b/nano_gui.cpp index 4fcd79a..7e31264 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -3,12 +3,11 @@ #include "settings.h" #include "ubitx.h" #include "nano_gui.h" +#include "touch.h" #include #include -struct Point ts_point; - /* * This formats the frequency given in f */ @@ -47,122 +46,6 @@ void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_wid } } -void readTouchCalibration(){ - LoadSettingsFromEeprom(); - /* for debugging - Serial.print(globalSettings.touchSlopeX); Serial.print(' '); - Serial.print(globalSettings.touchSlopeY); Serial.print(' '); - Serial.print(globalSettings.touchOffsetX); Serial.print(' '); - Serial.println(globalSettings.touchOffsetY); Serial.println(' '); - //*/ -} - -void writeTouchCalibration(){ - SaveSettingsToEeprom(); -} - -#define Z_THRESHOLD 400 -#define Z_THRESHOLD_INT 75 -#define MSEC_THRESHOLD 3 - -static uint32_t msraw=0x80000000; -static int16_t xraw=0, yraw=0, zraw=0; -static uint8_t rotation = 1; - -static int16_t touch_besttwoavg( int16_t x , int16_t y , int16_t z ) { - int16_t da, db, dc; - int16_t reta = 0; - if ( x > y ) da = x - y; else da = y - x; - if ( x > z ) db = x - z; else db = z - x; - if ( z > y ) dc = z - y; else dc = y - z; - - if ( da <= db && da <= dc ) reta = (x + y) >> 1; - else if ( db <= da && db <= dc ) reta = (x + z) >> 1; - else reta = (y + z) >> 1; // else if ( dc <= da && dc <= db ) reta = (x + y) >> 1; - - return (reta); -} - -static void touch_update(){ - int16_t data[6]; - - uint32_t now = millis(); - if (now - msraw < MSEC_THRESHOLD) return; - - SPI.setClockDivider(SPI_CLOCK_DIV8);//2MHz - digitalWrite(CS_PIN, LOW); - SPI.transfer(0xB1 /* Z1 */); - int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3; - int z = z1 + 4095; - int16_t z2 = SPI.transfer16(0x91 /* X */) >> 3; - z -= z2; - if (z >= Z_THRESHOLD) { - SPI.transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy - data[0] = SPI.transfer16(0xD1 /* Y */) >> 3; - data[1] = SPI.transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements - data[2] = SPI.transfer16(0xD1 /* Y */) >> 3; - data[3] = SPI.transfer16(0x91 /* X */) >> 3; - } - else data[0] = data[1] = data[2] = data[3] = 0; // Compiler warns these values may be used unset on early exit. - data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down - data[5] = SPI.transfer16(0) >> 3; - digitalWrite(CS_PIN, HIGH); - SPI.setClockDivider(SPI_CLOCK_DIV2);//Return to full speed for TFT - - if (z < 0) z = 0; - if (z < Z_THRESHOLD) { // if ( !touched ) { - // Serial.println(); - zraw = 0; - return; - } - zraw = z; - - int16_t x = touch_besttwoavg( data[0], data[2], data[4] ); - int16_t y = touch_besttwoavg( data[1], data[3], data[5] ); - - //Serial.printf(" %d,%d", x, y); - //Serial.println(); - if (z >= Z_THRESHOLD) { - msraw = now; // good read completed, set wait - switch (rotation) { - case 0: - xraw = 4095 - y; - yraw = x; - break; - case 1: - xraw = x; - yraw = y; - break; - case 2: - xraw = y; - yraw = 4095 - x; - break; - default: // 3 - xraw = 4095 - x; - yraw = 4095 - y; - } - } -} - - -bool readTouch(Point *const touch_point_out){ - touch_update(); - if (zraw >= Z_THRESHOLD) { - touch_point_out->x = xraw; - touch_point_out->y = yraw; - //Serial.print(ts_point.x); Serial.print(",");Serial.println(ts_point.y); - return true; - } - return false; -} - -void scaleTouch(Point *const p){ - p->x = ((long)(p->x - globalSettings.touchOffsetX) * 10L)/ (long)globalSettings.touchSlopeX; - p->y = ((long)(p->y - globalSettings.touchOffsetY) * 10L)/ (long)globalSettings.touchSlopeY; - - //Serial.print(p->x); Serial.print(",");Serial.println(p->y); -} - /***************** * Begin TFT functions *****************/ @@ -173,12 +56,6 @@ PDQ_ILI9341 tft; #include "nano_font.h" - -void xpt2046_Init(){ - pinMode(CS_PIN, OUTPUT); - digitalWrite(CS_PIN, HIGH); -} - void displayInit(void){ //Pulling this low 6 times should exit deep sleep mode pinMode(TFT_CS,OUTPUT); @@ -194,8 +71,6 @@ void displayInit(void){ tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK); tft.setTextSize(1); tft.setRotation(1); - - xpt2046_Init(); } void displayPixel(unsigned int x, unsigned int y, unsigned int c){ @@ -258,6 +133,7 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr void setupTouch(){ int x1, y1, x2, y2, x3, y3, x4, y4; + Point ts_point; displayClear(DISPLAY_BLACK); strncpy_P(b,(const char*)F("Click on the cross"),sizeof(b)); @@ -349,7 +225,7 @@ void setupTouch(){ Serial.print(globalSettings.touchOffsetX); Serial.print(' '); Serial.println(globalSettings.touchOffsetY); Serial.println(' '); */ - writeTouchCalibration(); + SaveSettingsToEeprom(); displayClear(DISPLAY_BLACK); } diff --git a/nano_gui.h b/nano_gui.h index 37d9826..8945efb 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -1,12 +1,6 @@ #ifndef _NANO_GUI_H_ #define _NANO_GUI_H_ -/* UI functions */ -struct Point { - int x, y; -}; -extern struct Point ts_point; - enum TextJustification_e : uint8_t { Left, @@ -26,11 +20,6 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width = 0); -/* touch functions */ -bool readTouch(Point *const p); - -void scaleTouch(Point *const p); - #define TEXT_LINE_HEIGHT 18 #define TEXT_LINE_INDENT 5 diff --git a/touch.cpp b/touch.cpp new file mode 100644 index 0000000..181bb4e --- /dev/null +++ b/touch.cpp @@ -0,0 +1,111 @@ +#include "touch.h" + +#include + +#include "ubitx.h"//pin assignments + +#define Z_THRESHOLD 400 +#define Z_THRESHOLD_INT 75 +#define MSEC_THRESHOLD 3 + +static uint32_t msraw=0x80000000; +static int16_t xraw=0, yraw=0, zraw=0; +static uint8_t rotation = 1; + +int16_t touch_besttwoavg( int16_t x , int16_t y , int16_t z ) { + int16_t da, db, dc; + int16_t reta = 0; + if ( x > y ) da = x - y; else da = y - x; + if ( x > z ) db = x - z; else db = z - x; + if ( z > y ) dc = z - y; else dc = y - z; + + if ( da <= db && da <= dc ) reta = (x + y) >> 1; + else if ( db <= da && db <= dc ) reta = (x + z) >> 1; + else reta = (y + z) >> 1; // else if ( dc <= da && dc <= db ) reta = (x + y) >> 1; + + return (reta); +} + +void touch_update(){ + int16_t data[6]; + + uint32_t now = millis(); + if (now - msraw < MSEC_THRESHOLD) return; + + SPI.setClockDivider(SPI_CLOCK_DIV8);//2MHz + digitalWrite(CS_PIN, LOW); + SPI.transfer(0xB1 /* Z1 */); + int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3; + int z = z1 + 4095; + int16_t z2 = SPI.transfer16(0x91 /* X */) >> 3; + z -= z2; + if (z >= Z_THRESHOLD) { + SPI.transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy + data[0] = SPI.transfer16(0xD1 /* Y */) >> 3; + data[1] = SPI.transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements + data[2] = SPI.transfer16(0xD1 /* Y */) >> 3; + data[3] = SPI.transfer16(0x91 /* X */) >> 3; + } + else data[0] = data[1] = data[2] = data[3] = 0; // Compiler warns these values may be used unset on early exit. + data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down + data[5] = SPI.transfer16(0) >> 3; + digitalWrite(CS_PIN, HIGH); + SPI.setClockDivider(SPI_CLOCK_DIV2);//Return to full speed for TFT + + if (z < 0) z = 0; + if (z < Z_THRESHOLD) { // if ( !touched ) { + // Serial.println(); + zraw = 0; + return; + } + zraw = z; + + int16_t x = touch_besttwoavg( data[0], data[2], data[4] ); + int16_t y = touch_besttwoavg( data[1], data[3], data[5] ); + + //Serial.printf(" %d,%d", x, y); + //Serial.println(); + if (z >= Z_THRESHOLD) { + msraw = now; // good read completed, set wait + switch (rotation) { + case 0: + xraw = 4095 - y; + yraw = x; + break; + case 1: + xraw = x; + yraw = y; + break; + case 2: + xraw = y; + yraw = 4095 - x; + break; + default: // 3 + xraw = 4095 - x; + yraw = 4095 - y; + } + } +} + +void initTouch(){ + pinMode(CS_PIN, OUTPUT); + digitalWrite(CS_PIN, HIGH); +} + +bool readTouch(Point *const touch_point_out){ + touch_update(); + if (zraw >= Z_THRESHOLD) { + touch_point_out->x = xraw; + touch_point_out->y = yraw; + //Serial.print(ts_point.x); Serial.print(",");Serial.println(ts_point.y); + return true; + } + return false; +} + +void scaleTouch(Point *const touch_point_in_out){ + touch_point_in_out->x = ((long)(touch_point_in_out->x - globalSettings.touchOffsetX) * 10L)/ (long)globalSettings.touchSlopeX; + touch_point_in_out->y = ((long)(touch_point_in_out->y - globalSettings.touchOffsetY) * 10L)/ (long)globalSettings.touchSlopeY; + + //Serial.print(p->x); Serial.print(",");Serial.println(p->y); +} \ No newline at end of file diff --git a/touch.h b/touch.h new file mode 100644 index 0000000..94ef80b --- /dev/null +++ b/touch.h @@ -0,0 +1,11 @@ +#pragma once + +#include "point.h" + +void initTouch(); + +//Returns true if touched, false otherwise +bool readTouch(Point *const touch_point_out); + +//Applies the touch calibration the point passed in +void scaleTouch(Point *const touch_point_in_out); \ No newline at end of file diff --git a/ui_touch.cpp b/ui_touch.cpp new file mode 100644 index 0000000..67e07d3 --- /dev/null +++ b/ui_touch.cpp @@ -0,0 +1,31 @@ +#include "ui_touch.h" + +#include //delay + +#include "button_timing.h" +#include "touch.h" + +ButtonPress_e checkTouch(Point *const touch_point_out){ + if (!readTouch(touch_point_out)){ + return ButtonPress_e::NotPressed; + } + delay(DEBOUNCE_DELAY_MS); + if (!readTouch(touch_point_out)){//debounce + return ButtonPress_e::NotPressed; + } + + uint16_t down_time = 0; + while(readTouch(touch_point_out) && (down_time < LONG_PRESS_TIME_MS)){ + delay(LONG_PRESS_POLL_TIME_MS); + down_time += LONG_PRESS_POLL_TIME_MS; + } + + scaleTouch(touch_point_out); + + if(down_time < LONG_PRESS_TIME_MS){ + return ButtonPress_e::ShortPress; + } + else{ + return ButtonPress_e::LongPress; + } +} diff --git a/ui_touch.h b/ui_touch.h new file mode 100644 index 0000000..386adac --- /dev/null +++ b/ui_touch.h @@ -0,0 +1,6 @@ +#pragma once + +#include "menu.h" +#include "point.h" + +ButtonPress_e checkTouch(Point *const touch_point_out); From 26c670ce140093c3ac2f31755ffc5a9155ffa8f2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 18:41:26 -0800 Subject: [PATCH 154/324] Include new point location --- menu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu.h b/menu.h index c13cd42..15a5c60 100644 --- a/menu.h +++ b/menu.h @@ -1,7 +1,7 @@ #pragma once #include -#include "nano_gui.h"//Point +#include "point.h" enum MenuReturn_e : uint8_t { StillActive, From a92fdc7793fdcfc239af002435141c776eba96ce Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 18:41:47 -0800 Subject: [PATCH 155/324] Update to use new touch functions --- ubitx_ui.cpp | 32 +++----------------------------- ubitxv6.ino | 6 +++--- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index c8ad956..3eb4fe5 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -5,6 +5,7 @@ #include "nano_gui.h" #include "settings.h" #include "setup.h" +#include "touch.h" #include "ubitx.h" #include "version.h" @@ -394,6 +395,8 @@ void fastTune(){ void enterFreq(){ //force the display to refresh everything //display all the buttons + + Point ts_point; for (int i = 0; i < KEYS_TOTAL; i++){ Button button; @@ -811,35 +814,6 @@ void doCommand(Button* button){ } } -#include "menu.h" -static const uint8_t DEBOUNCE_DELAY_MS = 50; -static const uint16_t LONG_PRESS_TIME_MS = 3000; -static const uint8_t LONG_PRESS_POLL_TIME_MS = 10; -ButtonPress_e checkTouch(Point *const touch_point_out){ - if (!readTouch(touch_point_out)){ - return ButtonPress_e::NotPressed; - } - delay(DEBOUNCE_DELAY_MS); - if (!readTouch(touch_point_out)){//debounce - return ButtonPress_e::NotPressed; - } - - uint16_t down_time = 0; - while(readTouch(touch_point_out) && (down_time < LONG_PRESS_TIME_MS)){ - delay(LONG_PRESS_POLL_TIME_MS); - down_time += LONG_PRESS_POLL_TIME_MS; - } - - scaleTouch(touch_point_out); - - if(down_time < LONG_PRESS_TIME_MS){ - return ButtonPress_e::ShortPress; - } - else{ - return ButtonPress_e::LongPress; - } -} - //returns true if the button is pressed int btnDown(){ if (digitalRead(FBUTTON) == HIGH) diff --git a/ubitxv6.ino b/ubitxv6.ino index b0febb6..d58c758 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -30,12 +30,14 @@ * Si5351 object to control the clocks. */ #include +#include "button_timing.h" #include "menu.h" #include "menu_main.h" #include "morse.h" #include "nano_gui.h" #include "settings.h" #include "setup.h" +#include "touch.h" #include "ubitx.h" /** @@ -304,9 +306,6 @@ void checkPTT(){ } //check if the encoder button was pressed -static const uint8_t DEBOUNCE_DELAY_MS = 50; -static const uint16_t LONG_PRESS_TIME_MS = 3000; -static const uint8_t LONG_PRESS_POLL_TIME_MS = 10; ButtonPress_e checkButton(){ if (!btnDown()){ return ButtonPress_e::NotPressed; @@ -462,6 +461,7 @@ void setup() initSettings(); displayInit(); + initTouch(); initPorts(); initOscillators(); setFrequency(globalSettings.vfoA.frequency); From 44838527426acc697b8a9d67f5775333026d661c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 18:44:17 -0800 Subject: [PATCH 156/324] Fix includes --- ubitx.h | 2 -- ubitxv6.ino | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/ubitx.h b/ubitx.h index 5262559..2c5ad65 100644 --- a/ubitx.h +++ b/ubitx.h @@ -120,8 +120,6 @@ int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* //main functions to check if any button is pressed and other user interface events void doCommands(); //does the commands with encoder to jump from button to button -#include "menu.h" -ButtonPress_e checkTouch(Point *const touch_point_out); //does the commands with a touch on the buttons diff --git a/ubitxv6.ino b/ubitxv6.ino index d58c758..beabf41 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -38,6 +38,7 @@ #include "settings.h" #include "setup.h" #include "touch.h" +#include "ui_touch.h" #include "ubitx.h" /** From d4867ac35bd096b89b746348c0f2d30538cc83b1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 21:14:43 -0800 Subject: [PATCH 157/324] Partial move of main menu buttons --- menu_main.cpp | 39 +++++++++++++--- menu_main_buttons.h | 110 ++++++++++++++++++++++++++++++++++++++++++++ ubitx_ui.cpp | 50 ++------------------ 3 files changed, 146 insertions(+), 53 deletions(-) create mode 100644 menu_main_buttons.h diff --git a/menu_main.cpp b/menu_main.cpp index cd858e9..76f6ebe 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -1,23 +1,35 @@ #include "menu_main.h" +#include "menu_main_buttons.h" #include #include #include "button.h" +#include "color_theme.h" #include "menu_utils.h" #include "morse.h" +#include "nano_gui.h" #include "settings.h" #include "ubitx.h"//THRESHOLD_USB_LSB #include "utils.h" +//The startup menu stuff is a little hack to render the main screen on boot +MenuReturn_e runStartupMenu(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); +Menu_t startupMenu = { + runStartupMenu, + nullptr +}; + MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, const ButtonPress_e touch_button, const Point touch_point, const int16_t knob); - Menu_t mainMenu = { runMainMenu, - nullptr + &startupMenu }; Menu_t* const rootMenu = &mainMenu; @@ -25,12 +37,23 @@ Menu_t* const rootMenu = &mainMenu; bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or adjusting frequency int16_t mainMenuSelectedItemRaw = 0;//Allow negative only for easier checks on wrap around -const Button mainMenuButtons [] PROGMEM = {}; -static constexpr uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); - void drawMainMenu(void) { - //TODO + displayClear(COLOR_BACKGROUND); + Button button; + for(uint8_t i = 0; i < MAIN_MENU_NUM_BUTTONS; ++i){ + memcpy_P(&button, &(mainMenuButtons[i]), sizeof(Button)); + displayText(button.text, button.x, button.y, button.w, button.h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); + Serial.println(button.text); + } +} + +MenuReturn_e runStartupMenu(const ButtonPress_e, + const ButtonPress_e, + const Point, + const int16_t) +{ + return MenuReturn_e::ExitedRedraw; } void mainMenuTune(int16_t knob) @@ -57,6 +80,10 @@ void mainMenuTune(int16_t knob) setFrequency(new_freq); current_freq = new_freq; + + Button button; + memcpy_P(&button, &(mainMenuButtons[0]), sizeof(Button)); + displayText(button.text, button.x, button.y, button.w, button.h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); } MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, diff --git a/menu_main_buttons.h b/menu_main_buttons.h new file mode 100644 index 0000000..b5e0e6e --- /dev/null +++ b/menu_main_buttons.h @@ -0,0 +1,110 @@ +//This file is only meant to be included by menu_main.cpp + +#include + +#include "button.h" +#include "settings.h" + +static const unsigned int LAYOUT_VFO_LABEL_X = 0; +static const unsigned int LAYOUT_VFO_LABEL_Y = 10; +static const unsigned int LAYOUT_VFO_LABEL_WIDTH = 159; +static const unsigned int LAYOUT_VFO_LABEL_HEIGHT = 36; +static const unsigned int LAYOUT_VFO_LABEL_PITCH_X = 160; + +static const unsigned int LAYOUT_MODE_TEXT_X = 0; +static const unsigned int LAYOUT_MODE_TEXT_Y = LAYOUT_VFO_LABEL_Y + LAYOUT_VFO_LABEL_HEIGHT + 1; +static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; +static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; + +static const unsigned int LAYOUT_BUTTON_X = 2; +static const unsigned int LAYOUT_BUTTON_Y = LAYOUT_MODE_TEXT_Y + LAYOUT_MODE_TEXT_HEIGHT + 1; +static const unsigned int LAYOUT_BUTTON_WIDTH = 60; +static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; +static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; +static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; + +static const unsigned int LAYOUT_CW_TEXT_X = 0; +static const unsigned int LAYOUT_CW_TEXT_Y = LAYOUT_BUTTON_Y + 3*LAYOUT_BUTTON_PITCH_Y + 1; +static const unsigned int LAYOUT_CW_TEXT_WIDTH = 220; +static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 36; + +static const unsigned int LAYOUT_VERSION_TEXT_X = LAYOUT_CW_TEXT_X + LAYOUT_CW_TEXT_WIDTH + 1; +static const unsigned int LAYOUT_VERSION_TEXT_Y = LAYOUT_CW_TEXT_Y; +static const unsigned int LAYOUT_VERSION_TEXT_WIDTH = 320 - LAYOUT_CW_TEXT_WIDTH - 1; +static const unsigned int LAYOUT_VERSION_TEXT_HEIGHT = LAYOUT_CW_TEXT_HEIGHT; + +static const unsigned int LAYOUT_TX_X = 280; +static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; +static const unsigned int LAYOUT_TX_WIDTH = 40; +static const unsigned int LAYOUT_TX_HEIGHT = 36; + +enum btn_set_e { + BUTTON_VFOA, + BUTTON_VFOB, + BUTTON_RIT, + BUTTON_USB, + BUTTON_LSB, + BUTTON_CW, + BUTTON_SPL, + BUTTON_80, + BUTTON_40, + BUTTON_30, + BUTTON_20, + BUTTON_17, + BUTTON_15, + BUTTON_10, + BUTTON_BLANK_1, + BUTTON_MNU, + BUTTON_FRQ, + BUTTON_TOTAL +}; + +void msVfoA(int8_t* val_out){ + *val_out = (Vfo_e::VFO_A == globalSettings.activeVfo) ? 1 : -1; +} +void msVfoB(int8_t* val_out){ + *val_out = (Vfo_e::VFO_B == globalSettings.activeVfo) ? 1 : -1; +} +void msRit(int8_t* val_out){ + *val_out = globalSettings.ritOn ? 1 : -1; +} +void msUsb(int8_t* val_out){ + *val_out = (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? 1 : -1; +} +void msLsb(int8_t* val_out){ + *val_out = (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? 1 : -1; +} +void msCw(int8_t* val_out){ + *val_out = (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? 1 : -1; +} +void msSpl(int8_t* val_out){ + *val_out = globalSettings.splitOn ? 1 : -1; +} +void msIgnore(int8_t* val_out){ + *val_out = 0; +} + +constexpr Button mainMenuButtons[] PROGMEM = { + {LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A', msVfoA}, + {LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B', msVfoB}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R', msRit}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U', msUsb}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L', msLsb}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C', msCw}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S', msSpl}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8', msIgnore}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4', msIgnore}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3', msIgnore}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2', msIgnore}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7', msIgnore}, + + {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5', msIgnore}, + {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1', msIgnore}, + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0', msIgnore}, + {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "\x7F", 'M', msIgnore}, + {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F', msIgnore}, +}; + +static constexpr uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index 3eb4fe5..b60a0d2 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -63,53 +63,9 @@ enum btn_set_e { BUTTON_TOTAL }; -void msVfoA(int8_t* val_out){ - *val_out = (Vfo_e::VFO_A == globalSettings.activeVfo) ? 1 : -1; -} -void msVfoB(int8_t* val_out){ - *val_out = (Vfo_e::VFO_B == globalSettings.activeVfo) ? 1 : -1; -} -void msRit(int8_t* val_out){ - *val_out = globalSettings.ritOn ? 1 : -1; -} -void msUsb(int8_t* val_out){ - *val_out = (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? 1 : -1; -} -void msLsb(int8_t* val_out){ - *val_out = (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? 1 : -1; -} -void msCw(int8_t* val_out){ - *val_out = (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? 1 : -1; -} -void msSpl(int8_t* val_out){ - *val_out = globalSettings.splitOn ? 1 : -1; -} -void msIgnore(int8_t* val_out){ - *val_out = 0; -} +void msIgnore(int8_t* val_out); -constexpr Button btn_set[BUTTON_TOTAL] PROGMEM = { - {LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A', msVfoA}, - {LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B', msVfoB}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R', msRit}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U', msUsb}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L', msLsb}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C', msCw}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S', msSpl}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8', msIgnore}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4', msIgnore}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3', msIgnore}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2', msIgnore}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7', msIgnore}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5', msIgnore}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1', msIgnore}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0', msIgnore}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "\x7F", 'M', msIgnore}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F', msIgnore}, -}; +Button* btn_set; static const unsigned int KEYS_OFFSET = 256;//Unique from buttons enum keypad_e { @@ -150,7 +106,7 @@ constexpr Button keypad[KEYS_TOTAL] PROGMEM = { {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_CANCEL, "Can", 'C', msIgnore}, }; -boolean getButton(btn_set_e index, Button* button){ +bool getButton(btn_set_e index, Button* button){ if(BUTTON_TOTAL == index){ return false; } From 9541c009be2e1f26b2fb34d77a1f4620a71fa5d8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 21:34:30 -0800 Subject: [PATCH 158/324] Extract progmem variables, and fix LIMITing on menu selection --- menu_utils.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/menu_utils.cpp b/menu_utils.cpp index ff6274c..f68c360 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -93,7 +93,9 @@ void initSelector(int16_t *const raw_select_val_in_out, { *raw_select_val_in_out = 0; if(0 < num_buttons){ - playButtonMorse(&buttons[0],play_type); + Button button; + memcpy_P(&button,&buttons[0],sizeof(button)); + playButtonMorse(&button,play_type); } } @@ -104,10 +106,15 @@ void adjustSelector(int16_t *const raw_select_val_in_out, const MorsePlaybackType_e play_type) { const uint8_t prev_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; - *raw_select_val_in_out += LIMIT((*raw_select_val_in_out)+knob,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1); + *raw_select_val_in_out = LIMIT((*raw_select_val_in_out)+knob,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1); const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; if(prev_select != new_select){ - movePuck(&buttons[prev_select],&buttons[new_select]); - playButtonMorse(&buttons[new_select],play_type); + Button prev_button; + memcpy_P(&prev_button,&buttons[prev_select],sizeof(prev_button)); + Button new_button; + memcpy_P(&new_button,&buttons[new_select],sizeof(new_button)); + + movePuck(&prev_button,&new_button); + playButtonMorse(&new_button,play_type); } } From 5c04e23504551405cf7c31f239fdf5afcda73f66 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 21:45:51 -0800 Subject: [PATCH 159/324] Show puck on first selection --- menu_utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/menu_utils.cpp b/menu_utils.cpp index f68c360..241e1dc 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -95,6 +95,7 @@ void initSelector(int16_t *const raw_select_val_in_out, if(0 < num_buttons){ Button button; memcpy_P(&button,&buttons[0],sizeof(button)); + movePuck(nullptr,&button); playButtonMorse(&button,play_type); } } From cc763a0dce2dc4369815c7ca179a6496860eb20f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 21:59:15 -0800 Subject: [PATCH 160/324] Add endSelector util --- menu_main.cpp | 6 +++++- menu_utils.cpp | 5 +++++ menu_utils.h | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/menu_main.cpp b/menu_main.cpp index 76f6ebe..eceabca 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -118,11 +118,15 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, { if(mainMenuSelecting){ uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + Button button; + memcpy_P(&button,&mainMenuButtons[menu_index],sizeof(button)); + endSelector(&button); + //TODO: activate button Serial.print(F("Select button ")); Serial.print(menu_index); Serial.print(F(":")); - Serial.println(mainMenuButtons[menu_index].text); + Serial.println(button.text); } else{ initSelector(&mainMenuSelectedItemRaw, diff --git a/menu_utils.cpp b/menu_utils.cpp index 241e1dc..a5e394b 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -119,3 +119,8 @@ void adjustSelector(int16_t *const raw_select_val_in_out, playButtonMorse(&new_button,play_type); } } + +void endSelector(const Button *const button) +{ + movePuck(button,nullptr); +} diff --git a/menu_utils.h b/menu_utils.h index 4de02d8..2787213 100644 --- a/menu_utils.h +++ b/menu_utils.h @@ -31,3 +31,5 @@ void adjustSelector(int16_t *const raw_select_val_in_out, const Button *const buttons, const uint8_t num_buttons, const MorsePlaybackType_e); + +void endSelector(const Button *const button); From ecc3b9c1fb26de9934adedb7053f04e4411708f8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 22:01:19 -0800 Subject: [PATCH 161/324] Add an init routine to the menu struct --- menu.h | 1 + menu_main.cpp | 14 +++----------- ubitxv6.ino | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/menu.h b/menu.h index 15a5c60..b54e3ff 100644 --- a/menu.h +++ b/menu.h @@ -16,6 +16,7 @@ enum ButtonPress_e : uint8_t { }; struct Menu_t { + void (*const initMenu)();//Any initial draw routines or state initialization MenuReturn_e (*const runMenu)(const ButtonPress_e tuner_button, const ButtonPress_e touch_button, const Point touch_point, diff --git a/menu_main.cpp b/menu_main.cpp index eceabca..f4ebc32 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -13,23 +13,15 @@ #include "ubitx.h"//THRESHOLD_USB_LSB #include "utils.h" -//The startup menu stuff is a little hack to render the main screen on boot -MenuReturn_e runStartupMenu(const ButtonPress_e tuner_button, - const ButtonPress_e touch_button, - const Point touch_point, - const int16_t knob); -Menu_t startupMenu = { - runStartupMenu, - nullptr -}; - +void drawMainMenu(void); MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, const ButtonPress_e touch_button, const Point touch_point, const int16_t knob); Menu_t mainMenu = { + drawMainMenu, runMainMenu, - &startupMenu + nullptr }; Menu_t* const rootMenu = &mainMenu; diff --git a/ubitxv6.ino b/ubitxv6.ino index beabf41..92ff72a 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -479,7 +479,7 @@ void setup() runBfoSetting(); } - guiUpdate(); + rootMenu->initMenu(); } From bafe61d10a041b2a7a0815bdbead4126bd1c4d07 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 22:17:50 -0800 Subject: [PATCH 162/324] Update button struct to provide more functionality --- button.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/button.h b/button.h index 74976b5..97133e1 100644 --- a/button.h +++ b/button.h @@ -2,10 +2,17 @@ #include +enum ButtonStatus_e : uint8_t { + Stateless, + Inactive, + Active +}; + struct Button { - int x, y, w, h; - unsigned int id; - char text[5]; + int16_t x, y, w, h; + const char* text; + void (*text_override)(char* text_out, uint16_t max_text_size); char morse; - void (*morse_status)(int8_t* val_out);//-1 if a low tone should play, +1 if a high tone should play + ButtonStatus_e (*status)(); + void (*on_select)();//Action to take when selected }; \ No newline at end of file From 7a149a979d035b523f027d9a38e7551fa2f4738d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 22:19:54 -0800 Subject: [PATCH 163/324] Add some comments to button and move char to the end --- button.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/button.h b/button.h index 97133e1..6f863bd 100644 --- a/button.h +++ b/button.h @@ -10,9 +10,9 @@ enum ButtonStatus_e : uint8_t { struct Button { int16_t x, y, w, h; - const char* text; - void (*text_override)(char* text_out, uint16_t max_text_size); - char morse; - ButtonStatus_e (*status)(); + const char* text;//nullptr if text_override should be used + void (*text_override)(char* text_out, uint16_t max_text_size);//nullptr if text should be used + ButtonStatus_e (*status)();//Used for coloring and morse menu void (*on_select)();//Action to take when selected + char morse; }; \ No newline at end of file From bc1e546ece9dfc5fa8dbef8e4e3ff54393ef9b4b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 22:27:49 -0800 Subject: [PATCH 164/324] const the size --- button.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/button.h b/button.h index 6f863bd..c9aec57 100644 --- a/button.h +++ b/button.h @@ -11,7 +11,7 @@ enum ButtonStatus_e : uint8_t { struct Button { int16_t x, y, w, h; const char* text;//nullptr if text_override should be used - void (*text_override)(char* text_out, uint16_t max_text_size);//nullptr if text should be used + void (*text_override)(char* text_out, const uint16_t max_text_size);//nullptr if text should be used ButtonStatus_e (*status)();//Used for coloring and morse menu void (*on_select)();//Action to take when selected char morse; From 6dacc470a2f964f5f2702e1042d9d3fbff694087 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 23:05:41 -0800 Subject: [PATCH 165/324] Copy size of the actual object --- menu_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_main.cpp b/menu_main.cpp index f4ebc32..2a12ced 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -74,7 +74,7 @@ void mainMenuTune(int16_t knob) current_freq = new_freq; Button button; - memcpy_P(&button, &(mainMenuButtons[0]), sizeof(Button)); + memcpy_P(&button, &(mainMenuButtons[0]), sizeof(button)); displayText(button.text, button.x, button.y, button.w, button.h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); } From c4e9d3c1567248eae4b3780cb4fc0aba3c2f3468 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 23:06:44 -0800 Subject: [PATCH 166/324] Add function stub for drawing buttons --- button.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/button.h b/button.h index c9aec57..6aba532 100644 --- a/button.h +++ b/button.h @@ -15,4 +15,6 @@ struct Button { ButtonStatus_e (*status)();//Used for coloring and morse menu void (*on_select)();//Action to take when selected char morse; -}; \ No newline at end of file +}; + +void drawButton(Button* button); From dc5104324ba0ab771560ef53eb1f73349f6c136c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 23:07:12 -0800 Subject: [PATCH 167/324] Start converting buttons. Not expected to compile --- menu_main_buttons.h | 180 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 149 insertions(+), 31 deletions(-) diff --git a/menu_main_buttons.h b/menu_main_buttons.h index b5e0e6e..338db19 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -38,55 +38,173 @@ static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; static const unsigned int LAYOUT_TX_WIDTH = 40; static const unsigned int LAYOUT_TX_HEIGHT = 36; -enum btn_set_e { - BUTTON_VFOA, - BUTTON_VFOB, - BUTTON_RIT, - BUTTON_USB, - BUTTON_LSB, - BUTTON_CW, - BUTTON_SPL, - BUTTON_80, - BUTTON_40, - BUTTON_30, - BUTTON_20, - BUTTON_17, - BUTTON_15, - BUTTON_10, - BUTTON_BLANK_1, - BUTTON_MNU, - BUTTON_FRQ, - BUTTON_TOTAL +void toVfo(char* text_out, const uint16_t max_text_size, const Vfo_e vfo) +{ + if(max_text_size < 2){ + return;//Can't do much with that space + } + if(max_text_size < (3+10+1)){ + //Give an indicator that's debuggable + text_out[0] = 'X'; + text_out[1] = '\0'; + return; + } + + //Normal operation + if (globalSettings.splitOn){ + if(vfo == globalSettings.activeVfo){ + text_out[0] = 'R'; + } + else{ + text_out[0] = 'T'; + } + } + else{ + if(VFO_A == vfo){ + text_out[0] = 'A'; + } + else if(VFO_B == vfo){ + text_out[0] = 'B'; + } + else{ + text_out[0] = '?'; + } + } + text_out[1] = ':'; + text_out[2] = ' '; + if(VFO_A == vfo){ + formatFreq(globalSettings.vfoA.frequency, text_out+3, max_text_size-3, 10); + } + else if(VFO_B == vfo){ + formatFreq(globalSettings.vfoB.frequency, text_out+3, max_text_size-3, 10); + } + else{ + text_out[3] = '?'; + text_out[4] = '\0'; + } +} + +void bsVfo(const Vfo_e vfo){ + (vfo == globalSettings.activeVfo) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osVfo(const Vfo_e vfo){ + globalSettings.activeVfo = vfo; +} + +void toVfoA(char* text_out, const uint16_t max_text_size){ + toVfo(text_out,max_text_size,Vfo_e::VFO_A); +} +ButtonStatus_e bsVfoA(){ + bsVfo(Vfo_e::VFO_A); +} +void osVfoA(){ + osVfo(Vfo_e::VFO_A); +} +constexpr Button bVfoA = { + LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, + nullptr, + toVfoA, + bsVfoA, + osVfoA, + 'A' }; -void msVfoA(int8_t* val_out){ - *val_out = (Vfo_e::VFO_A == globalSettings.activeVfo) ? 1 : -1; +void toVfoB(char* text_out, const uint16_t max_text_size){ + toVfo(text_out,max_text_size,Vfo_e::VFO_B); +} +ButtonStatus_e bsVfoB(){ + bsVfo(Vfo_e::VFO_B); } -void msVfoB(int8_t* val_out){ - *val_out = (Vfo_e::VFO_B == globalSettings.activeVfo) ? 1 : -1; +void osVfoB(){ + osVfo(Vfo_e::VFO_B); } -void msRit(int8_t* val_out){ +constexpr Button bVfoB = { + LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, + nullptr, + toVfoB, + bsVfoB, + osVfoB, + 'B' +}; + +constexpr char txtRit [] PROGMEM = "RIT"; +ButtonStatus_e bsRit(){ *val_out = globalSettings.ritOn ? 1 : -1; } -void msUsb(int8_t* val_out){ +void osRit(){ + Button button; + if(!globalSettings.ritOn){ + globalSettings.ritOn = true; + globalSettings.ritFrequency = GetActiveVfoFreq(); + + strncpy_P(b,(const char*)F("TX: "),sizeof(b)); + formatFreq(globalSettings.ritFrequency, b+3, sizeof(b)-strlen(c)); + if (VFO_A == globalSettings.activeVfo){ + displayText(b, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + } + else{ + displayText(b, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + } + } + else{ + globalSettings.ritOn = false; + setFrequency(globalSettings.ritFrequency); + + displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); + if(Vfo_e::VFO_A == globalSettings.activeVfo){ + memcpy_P(&button,bVfoA,sizeof(button)); + drawButton(&button); + } + else{ + memcpy_P(&button,bVfoB,sizeof(button)); + drawButton(&button); + } + } + + memcpy_P(&button,bRit,sizeof(button)); + drawButton(button); +} +constexpr Button bRit = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtRit, + nullptr, + bsRit, + osRit, + 'R' +}; + + +ButtonStatus_e bsUsb(){ *val_out = (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? 1 : -1; } -void msLsb(int8_t* val_out){ +ButtonStatus_e bsLsb(){ *val_out = (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? 1 : -1; } -void msCw(int8_t* val_out){ +ButtonStatus_e bsCw(){ *val_out = (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? 1 : -1; } -void msSpl(int8_t* val_out){ +ButtonStatus_e bsSpl(){ *val_out = globalSettings.splitOn ? 1 : -1; } -void msIgnore(int8_t* val_out){ +ButtonStatus_e bsIgnore(){ *val_out = 0; } constexpr Button mainMenuButtons[] PROGMEM = { - {LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOA, "VFOA", 'A', msVfoA}, - {LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_VFO_LABEL_HEIGHT, BUTTON_VFOB, "VFOB", 'B', msVfoB}, + bVfoA, + bVfoB, + + bRit, {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R', msRit}, {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U', msUsb}, From 846c59e5cc8ff89ba7dbd5135ade91f38a3a1f2f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 23:32:22 -0800 Subject: [PATCH 168/324] Update more buttons --- menu_main_buttons.h | 135 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 118 insertions(+), 17 deletions(-) diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 338db19..18ab770 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -96,12 +96,12 @@ void toVfoA(char* text_out, const uint16_t max_text_size){ toVfo(text_out,max_text_size,Vfo_e::VFO_A); } ButtonStatus_e bsVfoA(){ - bsVfo(Vfo_e::VFO_A); + return bsVfo(Vfo_e::VFO_A); } void osVfoA(){ osVfo(Vfo_e::VFO_A); } -constexpr Button bVfoA = { +constexpr Button bVfoA PROGMEM = { LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, @@ -117,12 +117,12 @@ void toVfoB(char* text_out, const uint16_t max_text_size){ toVfo(text_out,max_text_size,Vfo_e::VFO_B); } ButtonStatus_e bsVfoB(){ - bsVfo(Vfo_e::VFO_B); + return bsVfo(Vfo_e::VFO_B); } void osVfoB(){ osVfo(Vfo_e::VFO_B); } -constexpr Button bVfoB = { +constexpr Button bVfoB PROGMEM = { LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_VFO_LABEL_Y, LAYOUT_VFO_LABEL_WIDTH, @@ -135,6 +135,7 @@ constexpr Button bVfoB = { }; constexpr char txtRit [] PROGMEM = "RIT"; + ButtonStatus_e bsRit(){ *val_out = globalSettings.ritOn ? 1 : -1; } @@ -171,7 +172,7 @@ void osRit(){ memcpy_P(&button,bRit,sizeof(button)); drawButton(button); } -constexpr Button bRit = { +constexpr Button bRit PROGMEM = { LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, @@ -183,34 +184,134 @@ constexpr Button bRit = { 'R' }; +void osSidebandMode(VfoMode_e mode){ + SetActiveVfoMode(mode); + + Button button; + memcpy_P(&button,&bUsb,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bLsb,sizeof(button)); + drawButton(&button); +} + +constexpr char txtUsb [] PROGMEM = "USB"; ButtonStatus_e bsUsb(){ - *val_out = (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? 1 : -1; + return (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osUsb(){ + osSidebandMode(VfoMode_e::VFO_MODE_USB); } + +constexpr Button bUsb PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtUsb, + nullptr, + bsUsb, + osUsb, + 'U' +}; + +constexpr char txtLsb [] PROGMEM = "LSB"; + ButtonStatus_e bsLsb(){ - *val_out = (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? 1 : -1; + return (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osLsb(){ + osSidebandMode(VfoMode_e::VFO_MODE_LSB); } + +constexpr Button bLsb PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtLsb, + nullptr, + bsLsb, + osLsb, + 'L' +}; + +constexpr char txtCw [] PROGMEM = "CW"; + ButtonStatus_e bsCw(){ - *val_out = (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? 1 : -1; + return (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } + +void osCw(){ + if(TuningMode_e::TUNE_CW != globalSettings.tuningMode){ + globalSettings.tuningMode = TuningMode_e::TUNE_CW; + } + else{ + globalSettings.tuningMode = TuningMode_e::TUNE_SSB; + } + + Button button; + memcpy_P(&button,&bCw,sizeof(button)); + drawButton(button); +} + +constexpr Button bCw PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtCw, + nullptr, + bsCw, + osCw, + 'C' +}; + +constexpr char txtSpl [] PROGMEM = "SPL"; + ButtonStatus_e bsSpl(){ - *val_out = globalSettings.splitOn ? 1 : -1; + return globalSettings.splitOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } + +void osSpl(){ + globalSettings.splitOn = !globalSettings.splitOn; + + Button button; + memcpy_P(&button,&bSpl,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bsVfoA,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bsVfoB,sizeof(button)); + drawButton(&button); +} + +constexpr Button bSpl PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtSpl, + nullptr, + bsSpl, + osSpl, + 'S' +}; + ButtonStatus_e bsIgnore(){ - *val_out = 0; + return ButtonStatus_e::Stateless; } -constexpr Button mainMenuButtons[] PROGMEM = { +constexpr Button *const mainMenuButtons[] PROGMEM = { bVfoA, bVfoB, bRit, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_RIT, "RIT", 'R', msRit}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_USB, "USB", 'U', msUsb}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_LSB, "LSB", 'L', msLsb}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_CW , "CW", 'C', msCw}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_SPL, "SPL", 'S', msSpl}, + bUsb, + bLsb, + bCw, + bSpl, {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8', msIgnore}, {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4', msIgnore}, From 1869e20cf0db4604e8d26245ee97b7c294aaa4e4 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Thu, 6 Feb 2020 23:41:04 -0800 Subject: [PATCH 169/324] Add some band utility functions for later use --- bands.cpp | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ bands.h | 11 ++++++ 2 files changed, 127 insertions(+) create mode 100644 bands.cpp create mode 100644 bands.h diff --git a/bands.cpp b/bands.cpp new file mode 100644 index 0000000..ab900d6 --- /dev/null +++ b/bands.cpp @@ -0,0 +1,116 @@ +#include + +#include "bands.h" +#include "utils.h" + +/* + * These are the bands for USA. Your bands may vary + */ +struct Band_t { + uint32_t min; + uint32_t max; + uint8_t band_meters; + const char name[3];//Two characters + null terminator. Fixed width so we don't need to build separate pointers +}; + +const char UNKNOWN_BAND_NAME [] PROGMEM = "??"; + +constexpr Band_t bands [] PROGMEM { + { 0UL, 255UL, 255, "U8"},//Utility conversion option + { 0UL, 65535UL, 254, "UF"},//Utility conversion option + { 530000UL, 1700000UL, 253, "AM"},//Broadcast AM, actually centers at 268, but uint8 can't do that + { 1800000UL, 2000000UL, 160, "A0"},//0xA0 is 160 + { 3500000UL, 4000000UL, 80, "80"}, + { 5330500UL, 5403500UL, 60, "60"}, + { 7000000UL, 7300000UL, 40, "40"}, + {10100000UL, 10150000UL, 30, "30"}, + {14000000UL, 14350000UL, 20, "20"}, + {18068000UL, 18168000UL, 17, "17"}, + {21000000UL, 21450000UL, 15, "15"}, + {24890000UL, 24990000UL, 12, "12"}, + {26965000UL, 27405000UL, 11, "CB"},//Citizen's Band + {28000000UL, 29700000UL, 10, "10"}, +}; +constexpr uint8_t NUM_BANDS = sizeof(bands)/sizeof(bands[0]); + +int8_t findBandIndexFromBand(const uint8_t band) +{ + for(uint8_t i = 0; i < NUM_BANDS; ++i){ + if(band == bands[i].band_meters){ + return i; + } + } + + return -1; +} + +int8_t findBandIndexFromFreq(uint32_t frequency) +{ + for(uint8_t i = 0; i < NUM_BANDS; ++i){ + if(frequency <= bands[i].max){ + if(bands[i].min <= frequency){ + return i; + } + //No bands overlap, and they are ordered in strictly increasing frequency, so we need search no further + return -1; + } + } + + return -1; +} + +void getBandString(const unsigned long frequency, + char* band_string_out, + uint16_t max_string_length) +{ + int8_t band_index = findBandIndexFromFreq(frequency); + if(-1 == band_index){ + strncpy_P(band_string_out,UNKNOWN_BAND_NAME,max_string_length); + } + else{ + strncpy_P(band_string_out,bands[band_index].name,max_string_length); + } +} + +uint32_t getFreqInBand(const uint32_t frequency, + const uint8_t target_band) +{ + int8_t target_band_index = findBandIndexFromBand(target_band); + if(-1 == target_band_index){ + //Hard to target a band we don't know about... + return frequency; + } + + //See if we're currrently in a valid band + int8_t current_band_index = findBandIndexFromFreq(frequency); + + if(-1 == current_band_index){ + //We're not in a known band - just go to the center of the target band + return ((bands[target_band_index].max - bands[target_band_index].min)/2/100)*100;//truncated 100Hz + } + else{ + //We're in a known band. Match the relative position in the target band. + const uint32_t range_current = bands[current_band_index].max - bands[current_band_index].min; + const uint32_t range_target = bands[target_band_index].max - bands[target_band_index].min; + return (((frequency - bands[current_band_index].min) * range_target / range_current + bands[target_band_index].min)/100)*100;//truncated 100Hz + } +} + +bool isFreqInBand(const uint32_t frequency, + const uint8_t band) +{ + int8_t band_index = findBandIndexFromBand(band); + + if(-1 == band_index){ + //Unknown band - can't be in it + return false; + } + + if( (frequency <= bands[band_index].max) + && (bands[band_index].min <= frequency)){ + return true; + } + + return false; +} + diff --git a/bands.h b/bands.h new file mode 100644 index 0000000..8303e5e --- /dev/null +++ b/bands.h @@ -0,0 +1,11 @@ +#include + +void getBandString(const uint32_t frequency, + char* band_string_out, + const uint16_t max_string_length); + +uint32_t getFreqInBand(const uint32_t frequency, + const uint8_t target_band); + +bool isFreqInBand(const uint32_t frequency, + const uint8_t band); \ No newline at end of file From 254b60d88f5a9f239833bd50cfcac0d95622f7d1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 9 Feb 2020 23:52:02 -0800 Subject: [PATCH 170/324] More button conversion --- menu_main_buttons.h | 187 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 168 insertions(+), 19 deletions(-) diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 18ab770..118f4d6 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -2,6 +2,7 @@ #include +#include "bands.h" #include "button.h" #include "settings.h" @@ -299,28 +300,176 @@ constexpr Button bSpl PROGMEM = { 'S' }; -ButtonStatus_e bsIgnore(){ - return ButtonStatus_e::Stateless; +ButtonStatus_e bsBand(const uint8_t band){ + return isFreqInBand(GetActiveVfoFreq(),band) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } +void osBand(const uint8_t band){ + SetActiveVfoFreq(getFreqInBand(GetActiveVfoFreq(),band)); +} + +constexpr char txt80 [] PROGMEM = "80"; + +ButtonStatus_e bs80(){ + return bsBand(80); +} + +void os80(){ + osBand(80); +} + +constexpr Button b80 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt80, + nullptr, + bs80, + os80, + '8' +}; + +constexpr char txt40 [] PROGMEM = "40"; + +ButtonStatus_e bs40(){ + return bsBand(40); +} + +void os40(){ + osBand(40); +} + +constexpr Button b40 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt40, + nullptr, + bs40, + os40, + '4' +}; + +constexpr char txt30 [] PROGMEM = "30"; + +ButtonStatus_e bs30(){ + return bsBand(30); +} + +void os30(){ + osBand(30); +} + +constexpr Button b30 PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt30, + nullptr, + bs30, + os30, + '3' +}; + +constexpr char txt20 [] PROGMEM = "20"; + +ButtonStatus_e bs20(){ + return bsBand(20); +} + +void os20(){ + osBand(20); +} + +constexpr Button b20 PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt20, + nullptr, + bs20, + os20, + '2' +}; + +constexpr char txt17 [] PROGMEM = "17"; + +ButtonStatus_e bs17(){ + return bsBand(17); +} + +void os17(){ + osBand(17); +} + +constexpr Button b17 PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt17, + nullptr, + bs17, + os17, + '7' +}; + +constexpr char txt15 [] PROGMEM = "15"; + +ButtonStatus_e bs15(){ + return bsBand(15); +} + +void os15(){ + osBand(15); +} + +constexpr Button b15 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt15, + nullptr, + bs15, + os15, + '5' +}; + +constexpr char txt10 [] PROGMEM = "10"; + +ButtonStatus_e bs10(){ + return bsBand(10); +} + +void os10(){ + osBand(10); +} + +constexpr Button b10 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt10, + nullptr, + bs10, + os10, + '1' +}; + constexpr Button *const mainMenuButtons[] PROGMEM = { - bVfoA, - bVfoB, - - bRit, - bUsb, - bLsb, - bCw, - bSpl, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_80, "80", '8', msIgnore}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_40, "40", '4', msIgnore}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_30, "30", '3', msIgnore}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_20, "20", '2', msIgnore}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_17, "17", '7', msIgnore}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_15 , "15", '5', msIgnore}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_10 , "10", '1', msIgnore}, + bVfoA, bVfoB, + + bRit, bUsb, bLsb, bCw, bSpl, + b80, b40, b30, b20, b17, + b15, b10, bMnu, bFrq + + {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0', msIgnore}, {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "\x7F", 'M', msIgnore}, {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F', msIgnore}, From 1077b0bf841fe2b97ced98f34e4ea53562467258 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:01:49 -0800 Subject: [PATCH 171/324] First pass on main menu button conversion complete. Not expected to compile --- menu_main_buttons.h | 55 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 118f4d6..80cf17d 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -462,17 +462,54 @@ constexpr Button b10 PROGMEM = { '1' }; -constexpr Button *const mainMenuButtons[] PROGMEM = { - bVfoA, bVfoB, +ButtonStatus_e bsIgnore(){ + return ButtonStatus_e::Stateless; +} - bRit, bUsb, bLsb, bCw, bSpl, - b80, b40, b30, b20, b17, - b15, b10, bMnu, bFrq +constexpr char txtMenu PROGMEM = "\x7F";//gear icon - - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_BLANK_1, "", '\0', msIgnore}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_MNU, "\x7F", 'M', msIgnore}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, BUTTON_FRQ, "FRQ", 'F', msIgnore}, +void osMenu(){ + rootSettingsMenu->initMenu(); + mainmenu.active_submenu = rootSettingsMenu; +} + +constexpr Button bMenu = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtMenu, + nullptr, + bsIgnore, + osMenu, + 'M' +}; + +constexpr char txtNumpad PROGMEM = "FRQ"; + +void osNumpad(){ + numpadMenu->initMenu(); + mainMenu.active_submenu = numpadMenu; +} + +constexpr Button bNumpad = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtNumpad, + nullptr, + bsIgnore, + osNumpad, + 'F' +}; + +constexpr Button *const mainMenuButtons[] PROGMEM = { + bVfoA, bVfoB, + + bRit, bUsb, bLsb, bCw, bSpl, + b80, b40, b30, b20, b17, + b15, b10, bMenu, bNumpad }; static constexpr uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); From fa62b1136f472317e3e598ca9e58a02e375f2368 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:06:11 -0800 Subject: [PATCH 172/324] Update morse playback to use new version of button --- menu_utils.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/menu_utils.cpp b/menu_utils.cpp index a5e394b..2063294 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -76,12 +76,11 @@ void playButtonMorse(const Button *const button, morseLetter(button->morse); } - int8_t morse_status = 0; - button->morse_status(&morse_status); - if(morse_status < 0){ + const ButtonStatus_e bs = button->status(); + if(ButtonStatus_e::Inactive == bs){ morseBool(false); } - else if(morse_status > 0){ + else if(ButtonStatus_e::Active == bs){ morseBool(true); } } From 5c0ecb087b4cbbc50928add1c4d036dc14fe7de5 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:06:28 -0800 Subject: [PATCH 173/324] Comment out submenus for now --- menu_main_buttons.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 80cf17d..542c8a5 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -469,8 +469,9 @@ ButtonStatus_e bsIgnore(){ constexpr char txtMenu PROGMEM = "\x7F";//gear icon void osMenu(){ - rootSettingsMenu->initMenu(); - mainmenu.active_submenu = rootSettingsMenu; + //TODO + //rootSettingsMenu->initMenu(); + //mainmenu.active_submenu = rootSettingsMenu; } constexpr Button bMenu = { @@ -488,8 +489,9 @@ constexpr Button bMenu = { constexpr char txtNumpad PROGMEM = "FRQ"; void osNumpad(){ - numpadMenu->initMenu(); - mainMenu.active_submenu = numpadMenu; + //TODO + //numpadMenu->initMenu(); + //mainMenu.active_submenu = numpadMenu; } constexpr Button bNumpad = { From 61b79ba06ac002cba7f30f5136522649751ba3a9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:16:15 -0800 Subject: [PATCH 174/324] Move formatFreq to utils --- nano_gui.cpp | 37 ------------------------------------- nano_gui.h | 2 -- utils.cpp | 37 +++++++++++++++++++++++++++++++++++++ utils.h | 4 +++- 4 files changed, 40 insertions(+), 40 deletions(-) create mode 100644 utils.cpp diff --git a/nano_gui.cpp b/nano_gui.cpp index 7e31264..92336d1 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -8,43 +8,6 @@ #include #include -/* - * This formats the frequency given in f - */ -void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width) -{ - memset(buff, 0, buff_size); - - ultoa(freq, buff, DEC); - uint8_t num_digits = strlen(buff); - const uint8_t num_spacers = (num_digits-1) / 3; - const uint8_t num_leading_digits_raw = num_digits % 3; - const uint8_t num_leading_digits = (0 == num_leading_digits_raw) ? 3 : num_leading_digits_raw; - - if(0 < fixed_width){ - while(0 < fixed_width - num_digits - num_spacers){ - if(0 == fixed_width % 4){ - buff[0] = '\x81';//separator size - } - else{ - buff[0] = '\x80';//digit size - } - --fixed_width; - ++buff; - } - } - - ultoa(freq, buff, DEC); - buff += num_leading_digits; - num_digits -= num_leading_digits; - for(int i = num_digits-1; i >= 0; --i){ - buff[i + (i/3 + 1)] = buff[i]; - } - for(unsigned int i = 0; i < num_spacers; ++i){ - memcpy_P(buff,F("."),1); - buff += 4; - } -} /***************** * Begin TFT functions diff --git a/nano_gui.h b/nano_gui.h index 8945efb..e35145d 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -18,8 +18,6 @@ void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg); void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification = TextJustification_e::Center); -void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width = 0); - #define TEXT_LINE_HEIGHT 18 #define TEXT_LINE_INDENT 5 diff --git a/utils.cpp b/utils.cpp new file mode 100644 index 0000000..ebbf737 --- /dev/null +++ b/utils.cpp @@ -0,0 +1,37 @@ +/* + * Formats the frequency given + */ +void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_width) +{ + memset(buff, 0, buff_size); + + ultoa(freq, buff, DEC); + uint8_t num_digits = strlen(buff); + const uint8_t num_spacers = (num_digits-1) / 3; + const uint8_t num_leading_digits_raw = num_digits % 3; + const uint8_t num_leading_digits = (0 == num_leading_digits_raw) ? 3 : num_leading_digits_raw; + + if(0 < fixed_width){ + while(0 < fixed_width - num_digits - num_spacers){ + if(0 == fixed_width % 4){ + buff[0] = '\x81';//separator size + } + else{ + buff[0] = '\x80';//digit size + } + --fixed_width; + ++buff; + } + } + + ultoa(freq, buff, DEC); + buff += num_leading_digits; + num_digits -= num_leading_digits; + for(int i = num_digits-1; i >= 0; --i){ + buff[i + (i/3 + 1)] = buff[i]; + } + for(unsigned int i = 0; i < num_spacers; ++i){ + memcpy_P(buff,F("."),1); + buff += 4; + } +} diff --git a/utils.h b/utils.h index 03ef80c..fac136f 100644 --- a/utils.h +++ b/utils.h @@ -1,3 +1,5 @@ #pragma once -#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) \ No newline at end of file +#define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) + +void formatFreq(uint32_t freq, char* buff_out, uint16_t buff_size, uint8_t fixed_width = 0); From 90d550a03a40b292c7b03bdd34bb67671a4ad5e8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:29:46 -0800 Subject: [PATCH 175/324] Prevent multi-include problems --- ubitx.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ubitx.h b/ubitx.h index 2c5ad65..94e911b 100644 --- a/ubitx.h +++ b/ubitx.h @@ -1,3 +1,5 @@ +#pragma once + #include "settings.h" /* The ubitx is powered by an arduino nano. The pin assignment is as folows From 51288f1db3fbe0176903bab6db1a1f5dac04e249 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:35:32 -0800 Subject: [PATCH 176/324] Define types for formatFreq --- utils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils.h b/utils.h index fac136f..ec1607b 100644 --- a/utils.h +++ b/utils.h @@ -1,5 +1,7 @@ #pragma once +#include + #define LIMIT(val,min,max) ((val) < (min)) ? (min) : (((max) < (val)) ? (max) : (val)) void formatFreq(uint32_t freq, char* buff_out, uint16_t buff_size, uint8_t fixed_width = 0); From 2f9a0a3e04fc90cd1c879ac714e18830c359dfc7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:51:23 -0800 Subject: [PATCH 177/324] Fix compile errors --- utils.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/utils.cpp b/utils.cpp index ebbf737..de6022f 100644 --- a/utils.cpp +++ b/utils.cpp @@ -1,3 +1,10 @@ +#include "utils.h" + +#include +#include //ultoa +#include //memset, strlen +#include //F() + /* * Formats the frequency given */ @@ -5,7 +12,7 @@ void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_wid { memset(buff, 0, buff_size); - ultoa(freq, buff, DEC); + ultoa(freq, buff, 10); uint8_t num_digits = strlen(buff); const uint8_t num_spacers = (num_digits-1) / 3; const uint8_t num_leading_digits_raw = num_digits % 3; @@ -24,7 +31,7 @@ void formatFreq(uint32_t freq, char* buff, uint16_t buff_size, uint8_t fixed_wid } } - ultoa(freq, buff, DEC); + ultoa(freq, buff, 10); buff += num_leading_digits; num_digits -= num_leading_digits; for(int i = num_digits-1; i >= 0; --i){ From 8bd9d59e5a83c600c53bda1965c6cc006048a86e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:51:58 -0800 Subject: [PATCH 178/324] Displaying text should accept const char* --- PDQ_MinLib/PDQ_GFX.h | 4 ++-- nano_gui.cpp | 4 ++-- nano_gui.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/PDQ_MinLib/PDQ_GFX.h b/PDQ_MinLib/PDQ_GFX.h index f2a551e..abc5735 100644 --- a/PDQ_MinLib/PDQ_GFX.h +++ b/PDQ_MinLib/PDQ_GFX.h @@ -158,7 +158,7 @@ class PDQ_GFX : public Print { static inline uint8_t getRotation() __attribute__ ((always_inline)) { return rotation; } static inline coord_t getCursorX() __attribute__ ((always_inline)) { return cursor_x; } static inline coord_t getCursorY() __attribute__ ((always_inline)) { return cursor_y; } - static inline void getTextBounds(char *string, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi = _width); + static inline void getTextBounds(const char *string, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi = _width); static inline void getTextBounds(const __FlashStringHelper *s, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi = _width); virtual size_t write(uint8_t); // used by Arduino "Print.h" (and the one required virtual function) @@ -1061,7 +1061,7 @@ void PDQ_GFX::setFont(const GFXfont *f) // Pass string and a cursor position, returns UL corner and W,H. template -void PDQ_GFX::getTextBounds(char *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi) +void PDQ_GFX::getTextBounds(const char *str, coord_t x, coord_t y, int16_t *x1, int16_t *y1, uint16_t *w, uint16_t *h, coord_t wi) { uint8_t c; // Current character diff --git a/nano_gui.cpp b/nano_gui.cpp index 92336d1..e6590bb 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -64,14 +64,14 @@ void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t tft.drawCharGFX(x,y,c,color,bg,1); } -void displayRawText(char *text, int x1, int y1, int w, int color, int background){ +void displayRawText(const char *text, int x1, int y1, int w, int color, int background){ tft.setTextColor(color,background); tft.setCursor(x1,y1); tft.setBound(x1,x1+w); tft.print(text); } -void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification) +void displayText(const char *const text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification) { displayFillrect(x1, y1, w ,h, background); displayRect(x1, y1, w ,h, border); diff --git a/nano_gui.h b/nano_gui.h index e35145d..71b2d51 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -16,7 +16,7 @@ void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c void displayRect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c); void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c); void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg); -void displayText(char *text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification = TextJustification_e::Center); +void displayText(const char *const text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification = TextJustification_e::Center); #define TEXT_LINE_HEIGHT 18 #define TEXT_LINE_INDENT 5 From 55096c928494420e8b1241c63f9d8e4e451f8776 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:53:17 -0800 Subject: [PATCH 179/324] Fix most compiler errors --- menu_main_buttons.h | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 542c8a5..4b4eb5c 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -1,10 +1,16 @@ //This file is only meant to be included by menu_main.cpp #include +#include +#include //F() #include "bands.h" #include "button.h" +#include "color_theme.h" +#include "nano_gui.h" #include "settings.h" +#include "ubitx.h"//setFrequency +#include "utils.h" static const unsigned int LAYOUT_VFO_LABEL_X = 0; static const unsigned int LAYOUT_VFO_LABEL_Y = 10; @@ -85,8 +91,8 @@ void toVfo(char* text_out, const uint16_t max_text_size, const Vfo_e vfo) } } -void bsVfo(const Vfo_e vfo){ - (vfo == globalSettings.activeVfo) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +ButtonStatus_e bsVfo(const Vfo_e vfo){ + return (vfo == globalSettings.activeVfo) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } void osVfo(const Vfo_e vfo){ @@ -138,7 +144,7 @@ constexpr Button bVfoB PROGMEM = { constexpr char txtRit [] PROGMEM = "RIT"; ButtonStatus_e bsRit(){ - *val_out = globalSettings.ritOn ? 1 : -1; + return globalSettings.ritOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } void osRit(){ Button button; @@ -147,7 +153,7 @@ void osRit(){ globalSettings.ritFrequency = GetActiveVfoFreq(); strncpy_P(b,(const char*)F("TX: "),sizeof(b)); - formatFreq(globalSettings.ritFrequency, b+3, sizeof(b)-strlen(c)); + formatFreq(globalSettings.ritFrequency, b + strlen(b), sizeof(b)-strlen(b)); if (VFO_A == globalSettings.activeVfo){ displayText(b, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); } @@ -161,17 +167,17 @@ void osRit(){ displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,bVfoA,sizeof(button)); + memcpy_P(&button,&bVfoA,sizeof(button)); drawButton(&button); } else{ - memcpy_P(&button,bVfoB,sizeof(button)); + memcpy_P(&button,&bVfoB,sizeof(button)); drawButton(&button); } } - memcpy_P(&button,bRit,sizeof(button)); - drawButton(button); + memcpy_P(&button,&bRit,sizeof(button)); + drawButton(&button); } constexpr Button bRit PROGMEM = { LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, @@ -255,7 +261,7 @@ void osCw(){ Button button; memcpy_P(&button,&bCw,sizeof(button)); - drawButton(button); + drawButton(&button); } constexpr Button bCw PROGMEM = { @@ -282,9 +288,9 @@ void osSpl(){ Button button; memcpy_P(&button,&bSpl,sizeof(button)); drawButton(&button); - memcpy_P(&button,&bsVfoA,sizeof(button)); + memcpy_P(&button,&bVfoA,sizeof(button)); drawButton(&button); - memcpy_P(&button,&bsVfoB,sizeof(button)); + memcpy_P(&button,&bVfoB,sizeof(button)); drawButton(&button); } @@ -466,7 +472,7 @@ ButtonStatus_e bsIgnore(){ return ButtonStatus_e::Stateless; } -constexpr char txtMenu PROGMEM = "\x7F";//gear icon +constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon void osMenu(){ //TODO @@ -486,7 +492,7 @@ constexpr Button bMenu = { 'M' }; -constexpr char txtNumpad PROGMEM = "FRQ"; +constexpr char txtNumpad [] PROGMEM = "FRQ"; void osNumpad(){ //TODO @@ -506,12 +512,13 @@ constexpr Button bNumpad = { 'F' }; -constexpr Button *const mainMenuButtons[] PROGMEM = { - bVfoA, bVfoB, +constexpr const Button *const mainMenuButtons[] PROGMEM = { + &bVfoA, &bVfoB, + + &bRit, &bUsb, &bLsb, &bCw, &bSpl, + &b80, &b40, &b30, &b20, &b17, + &b15, &b10, &bMenu, &bNumpad - bRit, bUsb, bLsb, bCw, bSpl, - b80, b40, b30, b20, b17, - b15, b10, bMenu, bNumpad }; static constexpr uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); From 4583288bfae8e0e354b881f733a0542ce1ffed86 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 00:53:53 -0800 Subject: [PATCH 180/324] Update functions to use new button array --- menu_main.cpp | 6 +++--- menu_utils.cpp | 22 +++++++++++----------- menu_utils.h | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 2a12ced..d5652d9 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -34,7 +34,7 @@ void drawMainMenu(void) displayClear(COLOR_BACKGROUND); Button button; for(uint8_t i = 0; i < MAIN_MENU_NUM_BUTTONS; ++i){ - memcpy_P(&button, &(mainMenuButtons[i]), sizeof(Button)); + memcpy_P(&button, mainMenuButtons[i], sizeof(Button)); displayText(button.text, button.x, button.y, button.w, button.h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); Serial.println(button.text); } @@ -74,7 +74,7 @@ void mainMenuTune(int16_t knob) current_freq = new_freq; Button button; - memcpy_P(&button, &(mainMenuButtons[0]), sizeof(button)); + memcpy_P(&button, mainMenuButtons[0], sizeof(button)); displayText(button.text, button.x, button.y, button.w, button.h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); } @@ -111,7 +111,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, if(mainMenuSelecting){ uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; Button button; - memcpy_P(&button,&mainMenuButtons[menu_index],sizeof(button)); + memcpy_P(&button,mainMenuButtons[menu_index],sizeof(button)); endSelector(&button); //TODO: activate button diff --git a/menu_utils.cpp b/menu_utils.cpp index 2063294..8e5ca20 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -37,17 +37,17 @@ bool runSubmenu(Menu_t* const current_menu, return false; } -bool findPressedButton(const Button *const buttons, +bool findPressedButton(const Button* const* buttons, const uint8_t num_buttons, Button *const button_out, const Point touch_point) { for(uint16_t i = 0; i < num_buttons; ++i){ - if((buttons[i].x <= touch_point.x) - &&(touch_point.x <= buttons[i].x + buttons[i].w) - &&(buttons[i].y <= touch_point.y) - &&(touch_point.y <= buttons[i].y + buttons[i].h)){ - memcpy_P(button_out,&buttons[i],sizeof(button_out)); + if((buttons[i]->x <= touch_point.x) + &&(touch_point.x <= buttons[i]->x + buttons[i]->w) + &&(buttons[i]->y <= touch_point.y) + &&(touch_point.y <= buttons[i]->y + buttons[i]->h)){ + memcpy_P(button_out,buttons[i],sizeof(button_out)); return true; } } @@ -86,14 +86,14 @@ void playButtonMorse(const Button *const button, } void initSelector(int16_t *const raw_select_val_in_out, - const Button *const buttons, + const Button* const* buttons, const uint8_t num_buttons, const MorsePlaybackType_e play_type) { *raw_select_val_in_out = 0; if(0 < num_buttons){ Button button; - memcpy_P(&button,&buttons[0],sizeof(button)); + memcpy_P(&button,buttons[0],sizeof(button)); movePuck(nullptr,&button); playButtonMorse(&button,play_type); } @@ -101,7 +101,7 @@ void initSelector(int16_t *const raw_select_val_in_out, void adjustSelector(int16_t *const raw_select_val_in_out, const int16_t knob, - const Button *const buttons, + const Button* const* buttons, const uint8_t num_buttons, const MorsePlaybackType_e play_type) { @@ -110,9 +110,9 @@ void adjustSelector(int16_t *const raw_select_val_in_out, const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; if(prev_select != new_select){ Button prev_button; - memcpy_P(&prev_button,&buttons[prev_select],sizeof(prev_button)); + memcpy_P(&prev_button,buttons[prev_select],sizeof(prev_button)); Button new_button; - memcpy_P(&new_button,&buttons[new_select],sizeof(new_button)); + memcpy_P(&new_button,buttons[new_select],sizeof(new_button)); movePuck(&prev_button,&new_button); playButtonMorse(&new_button,play_type); diff --git a/menu_utils.h b/menu_utils.h index 2787213..05f43d2 100644 --- a/menu_utils.h +++ b/menu_utils.h @@ -12,7 +12,7 @@ bool runSubmenu(Menu_t* current_menu, const int16_t knob); //Returns true if button was found, false otherwise -bool findPressedButton(const Button *const buttons, +bool findPressedButton(const Button* const* buttons, const uint8_t num_buttons, Button *const button_out, const Point touch_point); @@ -22,13 +22,13 @@ enum MorsePlaybackType_e : uint8_t { PlayText }; void initSelector(int16_t *const raw_select_val_in_out, - const Button *const buttons, + const Button* const* buttons, const uint8_t num_buttons, const MorsePlaybackType_e); void adjustSelector(int16_t *const raw_select_val_in_out, int16_t knob, - const Button *const buttons, + const Button* const* buttons, const uint8_t num_buttons, const MorsePlaybackType_e); From 25d5f3aaa99dc62150453355b24a58eea4ddd889 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 01:02:03 -0800 Subject: [PATCH 181/324] Move most of the button stuff to a separate file --- menu_main_buttons.cpp | 525 ++++++++++++++++++++++++++++++++++++++++++ menu_main_buttons.h | 524 +---------------------------------------- 2 files changed, 529 insertions(+), 520 deletions(-) create mode 100644 menu_main_buttons.cpp diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp new file mode 100644 index 0000000..b22aceb --- /dev/null +++ b/menu_main_buttons.cpp @@ -0,0 +1,525 @@ +#include "menu_main_buttons.h" + +#include +#include +#include //F() + +#include "bands.h" +#include "button.h" +#include "color_theme.h" +#include "nano_gui.h" +#include "settings.h" +#include "ubitx.h"//setFrequency +#include "utils.h" + +static const unsigned int LAYOUT_VFO_LABEL_X = 0; +static const unsigned int LAYOUT_VFO_LABEL_Y = 10; +static const unsigned int LAYOUT_VFO_LABEL_WIDTH = 159; +static const unsigned int LAYOUT_VFO_LABEL_HEIGHT = 36; +static const unsigned int LAYOUT_VFO_LABEL_PITCH_X = 160; + +static const unsigned int LAYOUT_MODE_TEXT_X = 0; +static const unsigned int LAYOUT_MODE_TEXT_Y = LAYOUT_VFO_LABEL_Y + LAYOUT_VFO_LABEL_HEIGHT + 1; +static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; +static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; + +static const unsigned int LAYOUT_BUTTON_X = 2; +static const unsigned int LAYOUT_BUTTON_Y = LAYOUT_MODE_TEXT_Y + LAYOUT_MODE_TEXT_HEIGHT + 1; +static const unsigned int LAYOUT_BUTTON_WIDTH = 60; +static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; +static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; +static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; + +static const unsigned int LAYOUT_CW_TEXT_X = 0; +static const unsigned int LAYOUT_CW_TEXT_Y = LAYOUT_BUTTON_Y + 3*LAYOUT_BUTTON_PITCH_Y + 1; +static const unsigned int LAYOUT_CW_TEXT_WIDTH = 220; +static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 36; + +static const unsigned int LAYOUT_VERSION_TEXT_X = LAYOUT_CW_TEXT_X + LAYOUT_CW_TEXT_WIDTH + 1; +static const unsigned int LAYOUT_VERSION_TEXT_Y = LAYOUT_CW_TEXT_Y; +static const unsigned int LAYOUT_VERSION_TEXT_WIDTH = 320 - LAYOUT_CW_TEXT_WIDTH - 1; +static const unsigned int LAYOUT_VERSION_TEXT_HEIGHT = LAYOUT_CW_TEXT_HEIGHT; + +static const unsigned int LAYOUT_TX_X = 280; +static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; +static const unsigned int LAYOUT_TX_WIDTH = 40; +static const unsigned int LAYOUT_TX_HEIGHT = 36; + +void toVfo(char* text_out, const uint16_t max_text_size, const Vfo_e vfo) +{ + if(max_text_size < 2){ + return;//Can't do much with that space + } + if(max_text_size < (3+10+1)){ + //Give an indicator that's debuggable + text_out[0] = 'X'; + text_out[1] = '\0'; + return; + } + + //Normal operation + if (globalSettings.splitOn){ + if(vfo == globalSettings.activeVfo){ + text_out[0] = 'R'; + } + else{ + text_out[0] = 'T'; + } + } + else{ + if(VFO_A == vfo){ + text_out[0] = 'A'; + } + else if(VFO_B == vfo){ + text_out[0] = 'B'; + } + else{ + text_out[0] = '?'; + } + } + text_out[1] = ':'; + text_out[2] = ' '; + if(VFO_A == vfo){ + formatFreq(globalSettings.vfoA.frequency, text_out+3, max_text_size-3, 10); + } + else if(VFO_B == vfo){ + formatFreq(globalSettings.vfoB.frequency, text_out+3, max_text_size-3, 10); + } + else{ + text_out[3] = '?'; + text_out[4] = '\0'; + } +} + +ButtonStatus_e bsVfo(const Vfo_e vfo){ + return (vfo == globalSettings.activeVfo) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osVfo(const Vfo_e vfo){ + globalSettings.activeVfo = vfo; +} + +void toVfoA(char* text_out, const uint16_t max_text_size){ + toVfo(text_out,max_text_size,Vfo_e::VFO_A); +} +ButtonStatus_e bsVfoA(){ + return bsVfo(Vfo_e::VFO_A); +} +void osVfoA(){ + osVfo(Vfo_e::VFO_A); +} +constexpr Button bVfoA PROGMEM = { + LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, + nullptr, + toVfoA, + bsVfoA, + osVfoA, + 'A' +}; + +void toVfoB(char* text_out, const uint16_t max_text_size){ + toVfo(text_out,max_text_size,Vfo_e::VFO_B); +} +ButtonStatus_e bsVfoB(){ + return bsVfo(Vfo_e::VFO_B); +} +void osVfoB(){ + osVfo(Vfo_e::VFO_B); +} +constexpr Button bVfoB PROGMEM = { + LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, + nullptr, + toVfoB, + bsVfoB, + osVfoB, + 'B' +}; + +constexpr char txtRit [] PROGMEM = "RIT"; + +ButtonStatus_e bsRit(){ + return globalSettings.ritOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} +void osRit(){ + Button button; + if(!globalSettings.ritOn){ + globalSettings.ritOn = true; + globalSettings.ritFrequency = GetActiveVfoFreq(); + + strncpy_P(b,(const char*)F("TX: "),sizeof(b)); + formatFreq(globalSettings.ritFrequency, b + strlen(b), sizeof(b)-strlen(b)); + if (VFO_A == globalSettings.activeVfo){ + displayText(b, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + } + else{ + displayText(b, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + } + } + else{ + globalSettings.ritOn = false; + setFrequency(globalSettings.ritFrequency); + + displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); + if(Vfo_e::VFO_A == globalSettings.activeVfo){ + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); + } + else{ + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); + } + } + + memcpy_P(&button,&bRit,sizeof(button)); + drawButton(&button); +} +constexpr Button bRit PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtRit, + nullptr, + bsRit, + osRit, + 'R' +}; + +void osSidebandMode(VfoMode_e mode){ + SetActiveVfoMode(mode); + + Button button; + memcpy_P(&button,&bUsb,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bLsb,sizeof(button)); + drawButton(&button); +} + +constexpr char txtUsb [] PROGMEM = "USB"; + +ButtonStatus_e bsUsb(){ + return (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osUsb(){ + osSidebandMode(VfoMode_e::VFO_MODE_USB); +} + +constexpr Button bUsb PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtUsb, + nullptr, + bsUsb, + osUsb, + 'U' +}; + +constexpr char txtLsb [] PROGMEM = "LSB"; + +ButtonStatus_e bsLsb(){ + return (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osLsb(){ + osSidebandMode(VfoMode_e::VFO_MODE_LSB); +} + +constexpr Button bLsb PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtLsb, + nullptr, + bsLsb, + osLsb, + 'L' +}; + +constexpr char txtCw [] PROGMEM = "CW"; + +ButtonStatus_e bsCw(){ + return (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osCw(){ + if(TuningMode_e::TUNE_CW != globalSettings.tuningMode){ + globalSettings.tuningMode = TuningMode_e::TUNE_CW; + } + else{ + globalSettings.tuningMode = TuningMode_e::TUNE_SSB; + } + + Button button; + memcpy_P(&button,&bCw,sizeof(button)); + drawButton(&button); +} + +constexpr Button bCw PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtCw, + nullptr, + bsCw, + osCw, + 'C' +}; + +constexpr char txtSpl [] PROGMEM = "SPL"; + +ButtonStatus_e bsSpl(){ + return globalSettings.splitOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osSpl(){ + globalSettings.splitOn = !globalSettings.splitOn; + + Button button; + memcpy_P(&button,&bSpl,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); +} + +constexpr Button bSpl PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtSpl, + nullptr, + bsSpl, + osSpl, + 'S' +}; + +ButtonStatus_e bsBand(const uint8_t band){ + return isFreqInBand(GetActiveVfoFreq(),band) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; +} + +void osBand(const uint8_t band){ + SetActiveVfoFreq(getFreqInBand(GetActiveVfoFreq(),band)); +} + +constexpr char txt80 [] PROGMEM = "80"; + +ButtonStatus_e bs80(){ + return bsBand(80); +} + +void os80(){ + osBand(80); +} + +constexpr Button b80 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt80, + nullptr, + bs80, + os80, + '8' +}; + +constexpr char txt40 [] PROGMEM = "40"; + +ButtonStatus_e bs40(){ + return bsBand(40); +} + +void os40(){ + osBand(40); +} + +constexpr Button b40 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt40, + nullptr, + bs40, + os40, + '4' +}; + +constexpr char txt30 [] PROGMEM = "30"; + +ButtonStatus_e bs30(){ + return bsBand(30); +} + +void os30(){ + osBand(30); +} + +constexpr Button b30 PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt30, + nullptr, + bs30, + os30, + '3' +}; + +constexpr char txt20 [] PROGMEM = "20"; + +ButtonStatus_e bs20(){ + return bsBand(20); +} + +void os20(){ + osBand(20); +} + +constexpr Button b20 PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt20, + nullptr, + bs20, + os20, + '2' +}; + +constexpr char txt17 [] PROGMEM = "17"; + +ButtonStatus_e bs17(){ + return bsBand(17); +} + +void os17(){ + osBand(17); +} + +constexpr Button b17 PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt17, + nullptr, + bs17, + os17, + '7' +}; + +constexpr char txt15 [] PROGMEM = "15"; + +ButtonStatus_e bs15(){ + return bsBand(15); +} + +void os15(){ + osBand(15); +} + +constexpr Button b15 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt15, + nullptr, + bs15, + os15, + '5' +}; + +constexpr char txt10 [] PROGMEM = "10"; + +ButtonStatus_e bs10(){ + return bsBand(10); +} + +void os10(){ + osBand(10); +} + +constexpr Button b10 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt10, + nullptr, + bs10, + os10, + '1' +}; + +ButtonStatus_e bsIgnore(){ + return ButtonStatus_e::Stateless; +} + +constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon + +void osMenu(){ + //TODO + //rootSettingsMenu->initMenu(); + //mainmenu.active_submenu = rootSettingsMenu; +} + +constexpr Button bMenu = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtMenu, + nullptr, + bsIgnore, + osMenu, + 'M' +}; + +constexpr char txtNumpad [] PROGMEM = "FRQ"; + +void osNumpad(){ + //TODO + //numpadMenu->initMenu(); + //mainMenu.active_submenu = numpadMenu; +} + +constexpr Button bNumpad = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtNumpad, + nullptr, + bsIgnore, + osNumpad, + 'F' +}; + +static constexpr const Button *const buttons[] PROGMEM = { + &bVfoA, &bVfoB, + + &bRit, &bUsb, &bLsb, &bCw, &bSpl, + &b80, &b40, &b30, &b20, &b17, + &b15, &b10, &bMenu, &bNumpad + +}; + +const Button* const* mainMenuButtons = buttons; +const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(buttons) / sizeof(buttons[0]); diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 4b4eb5c..c41be19 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -1,524 +1,8 @@ -//This file is only meant to be included by menu_main.cpp +#pragma once -#include -#include -#include //F() +#include -#include "bands.h" #include "button.h" -#include "color_theme.h" -#include "nano_gui.h" -#include "settings.h" -#include "ubitx.h"//setFrequency -#include "utils.h" -static const unsigned int LAYOUT_VFO_LABEL_X = 0; -static const unsigned int LAYOUT_VFO_LABEL_Y = 10; -static const unsigned int LAYOUT_VFO_LABEL_WIDTH = 159; -static const unsigned int LAYOUT_VFO_LABEL_HEIGHT = 36; -static const unsigned int LAYOUT_VFO_LABEL_PITCH_X = 160; - -static const unsigned int LAYOUT_MODE_TEXT_X = 0; -static const unsigned int LAYOUT_MODE_TEXT_Y = LAYOUT_VFO_LABEL_Y + LAYOUT_VFO_LABEL_HEIGHT + 1; -static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; -static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; - -static const unsigned int LAYOUT_BUTTON_X = 2; -static const unsigned int LAYOUT_BUTTON_Y = LAYOUT_MODE_TEXT_Y + LAYOUT_MODE_TEXT_HEIGHT + 1; -static const unsigned int LAYOUT_BUTTON_WIDTH = 60; -static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; -static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; -static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; - -static const unsigned int LAYOUT_CW_TEXT_X = 0; -static const unsigned int LAYOUT_CW_TEXT_Y = LAYOUT_BUTTON_Y + 3*LAYOUT_BUTTON_PITCH_Y + 1; -static const unsigned int LAYOUT_CW_TEXT_WIDTH = 220; -static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 36; - -static const unsigned int LAYOUT_VERSION_TEXT_X = LAYOUT_CW_TEXT_X + LAYOUT_CW_TEXT_WIDTH + 1; -static const unsigned int LAYOUT_VERSION_TEXT_Y = LAYOUT_CW_TEXT_Y; -static const unsigned int LAYOUT_VERSION_TEXT_WIDTH = 320 - LAYOUT_CW_TEXT_WIDTH - 1; -static const unsigned int LAYOUT_VERSION_TEXT_HEIGHT = LAYOUT_CW_TEXT_HEIGHT; - -static const unsigned int LAYOUT_TX_X = 280; -static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; -static const unsigned int LAYOUT_TX_WIDTH = 40; -static const unsigned int LAYOUT_TX_HEIGHT = 36; - -void toVfo(char* text_out, const uint16_t max_text_size, const Vfo_e vfo) -{ - if(max_text_size < 2){ - return;//Can't do much with that space - } - if(max_text_size < (3+10+1)){ - //Give an indicator that's debuggable - text_out[0] = 'X'; - text_out[1] = '\0'; - return; - } - - //Normal operation - if (globalSettings.splitOn){ - if(vfo == globalSettings.activeVfo){ - text_out[0] = 'R'; - } - else{ - text_out[0] = 'T'; - } - } - else{ - if(VFO_A == vfo){ - text_out[0] = 'A'; - } - else if(VFO_B == vfo){ - text_out[0] = 'B'; - } - else{ - text_out[0] = '?'; - } - } - text_out[1] = ':'; - text_out[2] = ' '; - if(VFO_A == vfo){ - formatFreq(globalSettings.vfoA.frequency, text_out+3, max_text_size-3, 10); - } - else if(VFO_B == vfo){ - formatFreq(globalSettings.vfoB.frequency, text_out+3, max_text_size-3, 10); - } - else{ - text_out[3] = '?'; - text_out[4] = '\0'; - } -} - -ButtonStatus_e bsVfo(const Vfo_e vfo){ - return (vfo == globalSettings.activeVfo) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; -} - -void osVfo(const Vfo_e vfo){ - globalSettings.activeVfo = vfo; -} - -void toVfoA(char* text_out, const uint16_t max_text_size){ - toVfo(text_out,max_text_size,Vfo_e::VFO_A); -} -ButtonStatus_e bsVfoA(){ - return bsVfo(Vfo_e::VFO_A); -} -void osVfoA(){ - osVfo(Vfo_e::VFO_A); -} -constexpr Button bVfoA PROGMEM = { - LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, - LAYOUT_VFO_LABEL_Y, - LAYOUT_VFO_LABEL_WIDTH, - LAYOUT_VFO_LABEL_HEIGHT, - nullptr, - toVfoA, - bsVfoA, - osVfoA, - 'A' -}; - -void toVfoB(char* text_out, const uint16_t max_text_size){ - toVfo(text_out,max_text_size,Vfo_e::VFO_B); -} -ButtonStatus_e bsVfoB(){ - return bsVfo(Vfo_e::VFO_B); -} -void osVfoB(){ - osVfo(Vfo_e::VFO_B); -} -constexpr Button bVfoB PROGMEM = { - LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, - LAYOUT_VFO_LABEL_Y, - LAYOUT_VFO_LABEL_WIDTH, - LAYOUT_VFO_LABEL_HEIGHT, - nullptr, - toVfoB, - bsVfoB, - osVfoB, - 'B' -}; - -constexpr char txtRit [] PROGMEM = "RIT"; - -ButtonStatus_e bsRit(){ - return globalSettings.ritOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; -} -void osRit(){ - Button button; - if(!globalSettings.ritOn){ - globalSettings.ritOn = true; - globalSettings.ritFrequency = GetActiveVfoFreq(); - - strncpy_P(b,(const char*)F("TX: "),sizeof(b)); - formatFreq(globalSettings.ritFrequency, b + strlen(b), sizeof(b)-strlen(b)); - if (VFO_A == globalSettings.activeVfo){ - displayText(b, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - } - else{ - displayText(b, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - } - } - else{ - globalSettings.ritOn = false; - setFrequency(globalSettings.ritFrequency); - - displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); - if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); - } - else{ - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); - } - } - - memcpy_P(&button,&bRit,sizeof(button)); - drawButton(&button); -} -constexpr Button bRit PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtRit, - nullptr, - bsRit, - osRit, - 'R' -}; - -void osSidebandMode(VfoMode_e mode){ - SetActiveVfoMode(mode); - - Button button; - memcpy_P(&button,&bUsb,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bLsb,sizeof(button)); - drawButton(&button); -} - -constexpr char txtUsb [] PROGMEM = "USB"; - -ButtonStatus_e bsUsb(){ - return (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; -} - -void osUsb(){ - osSidebandMode(VfoMode_e::VFO_MODE_USB); -} - -constexpr Button bUsb PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtUsb, - nullptr, - bsUsb, - osUsb, - 'U' -}; - -constexpr char txtLsb [] PROGMEM = "LSB"; - -ButtonStatus_e bsLsb(){ - return (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; -} - -void osLsb(){ - osSidebandMode(VfoMode_e::VFO_MODE_LSB); -} - -constexpr Button bLsb PROGMEM = { - LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtLsb, - nullptr, - bsLsb, - osLsb, - 'L' -}; - -constexpr char txtCw [] PROGMEM = "CW"; - -ButtonStatus_e bsCw(){ - return (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; -} - -void osCw(){ - if(TuningMode_e::TUNE_CW != globalSettings.tuningMode){ - globalSettings.tuningMode = TuningMode_e::TUNE_CW; - } - else{ - globalSettings.tuningMode = TuningMode_e::TUNE_SSB; - } - - Button button; - memcpy_P(&button,&bCw,sizeof(button)); - drawButton(&button); -} - -constexpr Button bCw PROGMEM = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtCw, - nullptr, - bsCw, - osCw, - 'C' -}; - -constexpr char txtSpl [] PROGMEM = "SPL"; - -ButtonStatus_e bsSpl(){ - return globalSettings.splitOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; -} - -void osSpl(){ - globalSettings.splitOn = !globalSettings.splitOn; - - Button button; - memcpy_P(&button,&bSpl,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); -} - -constexpr Button bSpl PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtSpl, - nullptr, - bsSpl, - osSpl, - 'S' -}; - -ButtonStatus_e bsBand(const uint8_t band){ - return isFreqInBand(GetActiveVfoFreq(),band) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; -} - -void osBand(const uint8_t band){ - SetActiveVfoFreq(getFreqInBand(GetActiveVfoFreq(),band)); -} - -constexpr char txt80 [] PROGMEM = "80"; - -ButtonStatus_e bs80(){ - return bsBand(80); -} - -void os80(){ - osBand(80); -} - -constexpr Button b80 PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt80, - nullptr, - bs80, - os80, - '8' -}; - -constexpr char txt40 [] PROGMEM = "40"; - -ButtonStatus_e bs40(){ - return bsBand(40); -} - -void os40(){ - osBand(40); -} - -constexpr Button b40 PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt40, - nullptr, - bs40, - os40, - '4' -}; - -constexpr char txt30 [] PROGMEM = "30"; - -ButtonStatus_e bs30(){ - return bsBand(30); -} - -void os30(){ - osBand(30); -} - -constexpr Button b30 PROGMEM = { - LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt30, - nullptr, - bs30, - os30, - '3' -}; - -constexpr char txt20 [] PROGMEM = "20"; - -ButtonStatus_e bs20(){ - return bsBand(20); -} - -void os20(){ - osBand(20); -} - -constexpr Button b20 PROGMEM = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt20, - nullptr, - bs20, - os20, - '2' -}; - -constexpr char txt17 [] PROGMEM = "17"; - -ButtonStatus_e bs17(){ - return bsBand(17); -} - -void os17(){ - osBand(17); -} - -constexpr Button b17 PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt17, - nullptr, - bs17, - os17, - '7' -}; - -constexpr char txt15 [] PROGMEM = "15"; - -ButtonStatus_e bs15(){ - return bsBand(15); -} - -void os15(){ - osBand(15); -} - -constexpr Button b15 PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt15, - nullptr, - bs15, - os15, - '5' -}; - -constexpr char txt10 [] PROGMEM = "10"; - -ButtonStatus_e bs10(){ - return bsBand(10); -} - -void os10(){ - osBand(10); -} - -constexpr Button b10 PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt10, - nullptr, - bs10, - os10, - '1' -}; - -ButtonStatus_e bsIgnore(){ - return ButtonStatus_e::Stateless; -} - -constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon - -void osMenu(){ - //TODO - //rootSettingsMenu->initMenu(); - //mainmenu.active_submenu = rootSettingsMenu; -} - -constexpr Button bMenu = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtMenu, - nullptr, - bsIgnore, - osMenu, - 'M' -}; - -constexpr char txtNumpad [] PROGMEM = "FRQ"; - -void osNumpad(){ - //TODO - //numpadMenu->initMenu(); - //mainMenu.active_submenu = numpadMenu; -} - -constexpr Button bNumpad = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtNumpad, - nullptr, - bsIgnore, - osNumpad, - 'F' -}; - -constexpr const Button *const mainMenuButtons[] PROGMEM = { - &bVfoA, &bVfoB, - - &bRit, &bUsb, &bLsb, &bCw, &bSpl, - &b80, &b40, &b30, &b20, &b17, - &b15, &b10, &bMenu, &bNumpad - -}; - -static constexpr uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); +extern const Button* const* mainMenuButtons; +extern const uint8_t MAIN_MENU_NUM_BUTTONS; From 8239761a267745d98069331c1ee942ea548b2ace Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 01:17:47 -0800 Subject: [PATCH 182/324] Move button declarations together, declaring rather than defining required functions --- menu_main_buttons.cpp | 482 ++++++++++++++++++++++-------------------- 1 file changed, 253 insertions(+), 229 deletions(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index b22aceb..12669ba 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -45,6 +45,259 @@ static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; static const unsigned int LAYOUT_TX_WIDTH = 40; static const unsigned int LAYOUT_TX_HEIGHT = 36; +void toVfoA(char* text_out, const uint16_t max_text_size); +ButtonStatus_e bsVfoA(); +void osVfoA(); +constexpr Button bVfoA PROGMEM = { + LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, + nullptr, + toVfoA, + bsVfoA, + osVfoA, + 'A' +}; + +void toVfoB(char* text_out, const uint16_t max_text_size); +ButtonStatus_e bsVfoB(); +void osVfoB(); +constexpr Button bVfoB PROGMEM = { + LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, + nullptr, + toVfoB, + bsVfoB, + osVfoB, + 'B' +}; + +constexpr char txtRit [] PROGMEM = "RIT"; +ButtonStatus_e bsRit(); +void osRit(); +constexpr Button bRit PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtRit, + nullptr, + bsRit, + osRit, + 'R' +}; + +constexpr char txtUsb [] PROGMEM = "USB"; +ButtonStatus_e bsUsb(); +void osUsb(); +constexpr Button bUsb PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtUsb, + nullptr, + bsUsb, + osUsb, + 'U' +}; + +constexpr char txtLsb [] PROGMEM = "LSB"; +ButtonStatus_e bsLsb(); +void osLsb(); +constexpr Button bLsb PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtLsb, + nullptr, + bsLsb, + osLsb, + 'L' +}; + +constexpr char txtCw [] PROGMEM = "CW"; +ButtonStatus_e bsCw(); +void osCw(); +constexpr Button bCw PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtCw, + nullptr, + bsCw, + osCw, + 'C' +}; + +constexpr char txtSpl [] PROGMEM = "SPL"; +ButtonStatus_e bsSpl(); +void osSpl(); +constexpr Button bSpl PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtSpl, + nullptr, + bsSpl, + osSpl, + 'S' +}; + +constexpr char txt80 [] PROGMEM = "80"; +ButtonStatus_e bs80(); +void os80(); +constexpr Button b80 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt80, + nullptr, + bs80, + os80, + '8' +}; + +constexpr char txt40 [] PROGMEM = "40"; +ButtonStatus_e bs40(); +void os40(); +constexpr Button b40 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt40, + nullptr, + bs40, + os40, + '4' +}; + +constexpr char txt30 [] PROGMEM = "30"; +ButtonStatus_e bs30(); +void os30(); +constexpr Button b30 PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt30, + nullptr, + bs30, + os30, + '3' +}; + +constexpr char txt20 [] PROGMEM = "20"; +ButtonStatus_e bs20(); +void os20(); +constexpr Button b20 PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt20, + nullptr, + bs20, + os20, + '2' +}; + +constexpr char txt17 [] PROGMEM = "17"; +ButtonStatus_e bs17(); +void os17(); +constexpr Button b17 PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt17, + nullptr, + bs17, + os17, + '7' +}; + +constexpr char txt15 [] PROGMEM = "15"; +ButtonStatus_e bs15(); +void os15(); +constexpr Button b15 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt15, + nullptr, + bs15, + os15, + '5' +}; + +constexpr char txt10 [] PROGMEM = "10"; +ButtonStatus_e bs10(); +void os10(); +constexpr Button b10 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txt10, + nullptr, + bs10, + os10, + '1' +}; + +constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon +ButtonStatus_e bsIgnore(); +void osMenu(); +constexpr Button bMenu = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtMenu, + nullptr, + bsIgnore, + osMenu, + 'M' +}; + +constexpr char txtNumpad [] PROGMEM = "FRQ"; +ButtonStatus_e bsIgnore(); +void osNumpad(); +constexpr Button bNumpad = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtNumpad, + nullptr, + bsIgnore, + osNumpad, + 'F' +}; + +static constexpr const Button *const buttons[] PROGMEM = { + &bVfoA, &bVfoB, + + &bRit, &bUsb, &bLsb, &bCw, &bSpl, + &b80, &b40, &b30, &b20, &b17, + &b15, &b10, &bMenu, &bNumpad + +}; + +const Button* const* mainMenuButtons = buttons; +const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(buttons) / sizeof(buttons[0]); + + void toVfo(char* text_out, const uint16_t max_text_size, const Vfo_e vfo) { if(max_text_size < 2){ @@ -108,17 +361,6 @@ ButtonStatus_e bsVfoA(){ void osVfoA(){ osVfo(Vfo_e::VFO_A); } -constexpr Button bVfoA PROGMEM = { - LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, - LAYOUT_VFO_LABEL_Y, - LAYOUT_VFO_LABEL_WIDTH, - LAYOUT_VFO_LABEL_HEIGHT, - nullptr, - toVfoA, - bsVfoA, - osVfoA, - 'A' -}; void toVfoB(char* text_out, const uint16_t max_text_size){ toVfo(text_out,max_text_size,Vfo_e::VFO_B); @@ -129,19 +371,6 @@ ButtonStatus_e bsVfoB(){ void osVfoB(){ osVfo(Vfo_e::VFO_B); } -constexpr Button bVfoB PROGMEM = { - LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, - LAYOUT_VFO_LABEL_Y, - LAYOUT_VFO_LABEL_WIDTH, - LAYOUT_VFO_LABEL_HEIGHT, - nullptr, - toVfoB, - bsVfoB, - osVfoB, - 'B' -}; - -constexpr char txtRit [] PROGMEM = "RIT"; ButtonStatus_e bsRit(){ return globalSettings.ritOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; @@ -179,17 +408,6 @@ void osRit(){ memcpy_P(&button,&bRit,sizeof(button)); drawButton(&button); } -constexpr Button bRit PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtRit, - nullptr, - bsRit, - osRit, - 'R' -}; void osSidebandMode(VfoMode_e mode){ SetActiveVfoMode(mode); @@ -201,8 +419,6 @@ void osSidebandMode(VfoMode_e mode){ drawButton(&button); } -constexpr char txtUsb [] PROGMEM = "USB"; - ButtonStatus_e bsUsb(){ return (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } @@ -211,20 +427,6 @@ void osUsb(){ osSidebandMode(VfoMode_e::VFO_MODE_USB); } -constexpr Button bUsb PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtUsb, - nullptr, - bsUsb, - osUsb, - 'U' -}; - -constexpr char txtLsb [] PROGMEM = "LSB"; - ButtonStatus_e bsLsb(){ return (VfoMode_e::VFO_MODE_LSB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } @@ -233,20 +435,6 @@ void osLsb(){ osSidebandMode(VfoMode_e::VFO_MODE_LSB); } -constexpr Button bLsb PROGMEM = { - LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtLsb, - nullptr, - bsLsb, - osLsb, - 'L' -}; - -constexpr char txtCw [] PROGMEM = "CW"; - ButtonStatus_e bsCw(){ return (TuningMode_e::TUNE_CW == globalSettings.tuningMode) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } @@ -264,20 +452,6 @@ void osCw(){ drawButton(&button); } -constexpr Button bCw PROGMEM = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtCw, - nullptr, - bsCw, - osCw, - 'C' -}; - -constexpr char txtSpl [] PROGMEM = "SPL"; - ButtonStatus_e bsSpl(){ return globalSettings.splitOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } @@ -294,18 +468,6 @@ void osSpl(){ drawButton(&button); } -constexpr Button bSpl PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtSpl, - nullptr, - bsSpl, - osSpl, - 'S' -}; - ButtonStatus_e bsBand(const uint8_t band){ return isFreqInBand(GetActiveVfoFreq(),band) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } @@ -314,8 +476,6 @@ void osBand(const uint8_t band){ SetActiveVfoFreq(getFreqInBand(GetActiveVfoFreq(),band)); } -constexpr char txt80 [] PROGMEM = "80"; - ButtonStatus_e bs80(){ return bsBand(80); } @@ -324,20 +484,6 @@ void os80(){ osBand(80); } -constexpr Button b80 PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt80, - nullptr, - bs80, - os80, - '8' -}; - -constexpr char txt40 [] PROGMEM = "40"; - ButtonStatus_e bs40(){ return bsBand(40); } @@ -346,20 +492,6 @@ void os40(){ osBand(40); } -constexpr Button b40 PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt40, - nullptr, - bs40, - os40, - '4' -}; - -constexpr char txt30 [] PROGMEM = "30"; - ButtonStatus_e bs30(){ return bsBand(30); } @@ -368,20 +500,6 @@ void os30(){ osBand(30); } -constexpr Button b30 PROGMEM = { - LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt30, - nullptr, - bs30, - os30, - '3' -}; - -constexpr char txt20 [] PROGMEM = "20"; - ButtonStatus_e bs20(){ return bsBand(20); } @@ -390,20 +508,6 @@ void os20(){ osBand(20); } -constexpr Button b20 PROGMEM = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt20, - nullptr, - bs20, - os20, - '2' -}; - -constexpr char txt17 [] PROGMEM = "17"; - ButtonStatus_e bs17(){ return bsBand(17); } @@ -412,20 +516,6 @@ void os17(){ osBand(17); } -constexpr Button b17 PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt17, - nullptr, - bs17, - os17, - '7' -}; - -constexpr char txt15 [] PROGMEM = "15"; - ButtonStatus_e bs15(){ return bsBand(15); } @@ -434,20 +524,6 @@ void os15(){ osBand(15); } -constexpr Button b15 PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt15, - nullptr, - bs15, - os15, - '5' -}; - -constexpr char txt10 [] PROGMEM = "10"; - ButtonStatus_e bs10(){ return bsBand(10); } @@ -456,70 +532,18 @@ void os10(){ osBand(10); } -constexpr Button b10 PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txt10, - nullptr, - bs10, - os10, - '1' -}; - ButtonStatus_e bsIgnore(){ return ButtonStatus_e::Stateless; } -constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon - void osMenu(){ //TODO //rootSettingsMenu->initMenu(); //mainmenu.active_submenu = rootSettingsMenu; } -constexpr Button bMenu = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtMenu, - nullptr, - bsIgnore, - osMenu, - 'M' -}; - -constexpr char txtNumpad [] PROGMEM = "FRQ"; - void osNumpad(){ //TODO //numpadMenu->initMenu(); //mainMenu.active_submenu = numpadMenu; } - -constexpr Button bNumpad = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - txtNumpad, - nullptr, - bsIgnore, - osNumpad, - 'F' -}; - -static constexpr const Button *const buttons[] PROGMEM = { - &bVfoA, &bVfoB, - - &bRit, &bUsb, &bLsb, &bCw, &bSpl, - &b80, &b40, &b30, &b20, &b17, - &b15, &b10, &bMenu, &bNumpad - -}; - -const Button* const* mainMenuButtons = buttons; -const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(buttons) / sizeof(buttons[0]); From 2826dfde568ab4da81d44f52f9f22ff02ecaeeeb Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 01:30:01 -0800 Subject: [PATCH 183/324] First pass at button drawing implementation --- button.cpp | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 button.cpp diff --git a/button.cpp b/button.cpp new file mode 100644 index 0000000..50adcb4 --- /dev/null +++ b/button.cpp @@ -0,0 +1,25 @@ +#include "button.h" +#include "nano_gui.h" +#include "color_theme.h" +#include "ubitx.h"//b + +void drawButton(Button* button) +{ + uint16_t tc = COLOR_INACTIVE_TEXT; + uint16_t bgc = COLOR_INACTIVE_BACKGROUND; + const uint16_t bdc = COLOR_INACTIVE_BORDER; + const char* text = nullptr; + if(nullptr != button->text){ + text = button->text; + } + else if(nullptr != button->text_override){ + button->text_override(b,sizeof(b)); + text = b; + } + else{ + //Something's messed up + //Serial.println(F("No text for button!")); + return; + } + displayText(text, button->x, button->y, button->w, button->h, tc, bgc, bdc); +} From 2722b4367abcf504a7c1c79a79db86dbca9a0206 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 01:30:21 -0800 Subject: [PATCH 184/324] Update include annotation --- menu_main_buttons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 12669ba..a5fff3c 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -9,7 +9,7 @@ #include "color_theme.h" #include "nano_gui.h" #include "settings.h" -#include "ubitx.h"//setFrequency +#include "ubitx.h"//setFrequency, b #include "utils.h" static const unsigned int LAYOUT_VFO_LABEL_X = 0; From efd3bfc5ad05f91c07099f2401656125b6b80578 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 10 Feb 2020 01:34:02 -0800 Subject: [PATCH 185/324] Add color distinction to button drawing --- button.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/button.cpp b/button.cpp index 50adcb4..3af0bac 100644 --- a/button.cpp +++ b/button.cpp @@ -8,6 +8,24 @@ void drawButton(Button* button) uint16_t tc = COLOR_INACTIVE_TEXT; uint16_t bgc = COLOR_INACTIVE_BACKGROUND; const uint16_t bdc = COLOR_INACTIVE_BORDER; + switch(button->status()) + { + case ButtonStatus_e::Stateless://Fallthrough intended + case ButtonStatus_e::Inactive://Fallthrough intended + default: + { + //Colors are initialized for this, so we're done + break; + } + case ButtonStatus_e::Active: + { + tc = COLOR_ACTIVE_TEXT; + bgc = COLOR_ACTIVE_BACKGROUND; + break; + } + } + + const char* text = nullptr; if(nullptr != button->text){ text = button->text; From c727d876eb648a367dce1feb94e6836ad10985d8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 21:42:50 -0800 Subject: [PATCH 186/324] Fix button drawing routine --- button.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/button.cpp b/button.cpp index 3af0bac..2c742c6 100644 --- a/button.cpp +++ b/button.cpp @@ -1,6 +1,9 @@ #include "button.h" -#include "nano_gui.h" + +#include + #include "color_theme.h" +#include "nano_gui.h" #include "ubitx.h"//b void drawButton(Button* button) @@ -26,18 +29,16 @@ void drawButton(Button* button) } - const char* text = nullptr; if(nullptr != button->text){ - text = button->text; + strncpy_P(b,button->text,sizeof(b)); } else if(nullptr != button->text_override){ button->text_override(b,sizeof(b)); - text = b; } else{ //Something's messed up //Serial.println(F("No text for button!")); return; } - displayText(text, button->x, button->y, button->w, button->h, tc, bgc, bdc); + displayText(b, button->x, button->y, button->w, button->h, tc, bgc, bdc); } From 2ff1d0d7e856eda328efa3d204b64b0cdfe89015 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 21:44:40 -0800 Subject: [PATCH 187/324] Fix types and expose some buttons --- menu_main_buttons.cpp | 7 +++---- menu_main_buttons.h | 3 +++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index a5fff3c..ccd155d 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -258,7 +258,7 @@ constexpr Button b10 PROGMEM = { constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon ButtonStatus_e bsIgnore(); void osMenu(); -constexpr Button bMenu = { +constexpr Button bMenu PROGMEM = { LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, @@ -273,7 +273,7 @@ constexpr Button bMenu = { constexpr char txtNumpad [] PROGMEM = "FRQ"; ButtonStatus_e bsIgnore(); void osNumpad(); -constexpr Button bNumpad = { +constexpr Button bNumpad PROGMEM = { LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, @@ -285,13 +285,12 @@ constexpr Button bNumpad = { 'F' }; -static constexpr const Button *const buttons[] PROGMEM = { +const Button* const buttons[] PROGMEM = { &bVfoA, &bVfoB, &bRit, &bUsb, &bLsb, &bCw, &bSpl, &b80, &b40, &b30, &b20, &b17, &b15, &b10, &bMenu, &bNumpad - }; const Button* const* mainMenuButtons = buttons; diff --git a/menu_main_buttons.h b/menu_main_buttons.h index c41be19..7efb414 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -6,3 +6,6 @@ extern const Button* const* mainMenuButtons; extern const uint8_t MAIN_MENU_NUM_BUTTONS; + +extern const Button bVfoA; +extern const Button bVfoB; From 6686f199b053dd1eb55d59b5f732f589534d35f9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 21:45:26 -0800 Subject: [PATCH 188/324] Unpack progmem fully --- menu_main.cpp | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index d5652d9..0db9a3d 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -29,14 +29,17 @@ Menu_t* const rootMenu = &mainMenu; bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or adjusting frequency int16_t mainMenuSelectedItemRaw = 0;//Allow negative only for easier checks on wrap around +extern Button* const* buttons; + void drawMainMenu(void) { displayClear(COLOR_BACKGROUND); Button button; + Button* bp; for(uint8_t i = 0; i < MAIN_MENU_NUM_BUTTONS; ++i){ - memcpy_P(&button, mainMenuButtons[i], sizeof(Button)); - displayText(button.text, button.x, button.y, button.w, button.h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); - Serial.println(button.text); + memcpy_P(&bp, &(mainMenuButtons[i]), sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + drawButton(&button); } } @@ -74,8 +77,13 @@ void mainMenuTune(int16_t knob) current_freq = new_freq; Button button; - memcpy_P(&button, mainMenuButtons[0], sizeof(button)); - displayText(button.text, button.x, button.y, button.w, button.h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); + if(Vfo_e::VFO_A == globalSettings.activeVfo){ + memcpy_P(&button,&bVfoA,sizeof(button)); + } + else{ + memcpy_P(&button,&bVfoB,sizeof(button)); + } + drawButton(&button); } MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, @@ -111,7 +119,9 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, if(mainMenuSelecting){ uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; Button button; - memcpy_P(&button,mainMenuButtons[menu_index],sizeof(button)); + Button* bp; + memcpy_P(&bp,&(mainMenuButtons[menu_index]),sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); endSelector(&button); //TODO: activate button From 2c20483931fc2854f592ad10e582b38abdbc54cd Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 21:55:23 -0800 Subject: [PATCH 189/324] Fix extraction in menu_utils --- menu_utils.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/menu_utils.cpp b/menu_utils.cpp index 8e5ca20..481161d 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -42,12 +42,16 @@ bool findPressedButton(const Button* const* buttons, Button *const button_out, const Point touch_point) { + Button button; + Button* bp; for(uint16_t i = 0; i < num_buttons; ++i){ - if((buttons[i]->x <= touch_point.x) - &&(touch_point.x <= buttons[i]->x + buttons[i]->w) - &&(buttons[i]->y <= touch_point.y) - &&(touch_point.y <= buttons[i]->y + buttons[i]->h)){ - memcpy_P(button_out,buttons[i],sizeof(button_out)); + memcpy_P(&bp,&(buttons[i]),sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + if((button.x <= touch_point.x) + &&(touch_point.x <= button.x + button.w) + &&(button.y <= touch_point.y) + &&(touch_point.y <= button.y + button.h)){ + memcpy_P(button_out,&button,sizeof(button_out)); return true; } } @@ -93,7 +97,9 @@ void initSelector(int16_t *const raw_select_val_in_out, *raw_select_val_in_out = 0; if(0 < num_buttons){ Button button; - memcpy_P(&button,buttons[0],sizeof(button)); + Button* bp; + memcpy_P(&bp,&(buttons[0]),sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); movePuck(nullptr,&button); playButtonMorse(&button,play_type); } @@ -110,9 +116,12 @@ void adjustSelector(int16_t *const raw_select_val_in_out, const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; if(prev_select != new_select){ Button prev_button; - memcpy_P(&prev_button,buttons[prev_select],sizeof(prev_button)); + Button* bp; + memcpy_P(&bp,&(buttons[prev_select]),sizeof(bp)); + memcpy_P(&prev_button,bp,sizeof(prev_button)); Button new_button; - memcpy_P(&new_button,buttons[new_select],sizeof(new_button)); + memcpy_P(&bp,&(buttons[new_select]),sizeof(bp)); + memcpy_P(&new_button,bp,sizeof(new_button)); movePuck(&prev_button,&new_button); playButtonMorse(&new_button,play_type); From c176604320cf0867d49cef9c885709e2f6456c8a Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 22:15:46 -0800 Subject: [PATCH 190/324] Use pointer passed in for work space --- menu_utils.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/menu_utils.cpp b/menu_utils.cpp index 481161d..a2531f6 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -42,16 +42,14 @@ bool findPressedButton(const Button* const* buttons, Button *const button_out, const Point touch_point) { - Button button; Button* bp; for(uint16_t i = 0; i < num_buttons; ++i){ memcpy_P(&bp,&(buttons[i]),sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - if((button.x <= touch_point.x) - &&(touch_point.x <= button.x + button.w) - &&(button.y <= touch_point.y) - &&(touch_point.y <= button.y + button.h)){ - memcpy_P(button_out,&button,sizeof(button_out)); + memcpy_P(button_out,bp,sizeof(*button_out)); + if((button_out->x <= touch_point.x) + &&(touch_point.x <= button_out->x + button_out->w) + &&(button_out->y <= touch_point.y) + &&(touch_point.y <= button_out->y + button_out->h)){ return true; } } From 3b932d54b486d2e670b81ce345fc4065636f99f7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 22:17:30 -0800 Subject: [PATCH 191/324] Actually activate buttons! --- menu_main.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 0db9a3d..0610f9d 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -123,12 +123,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, memcpy_P(&bp,&(mainMenuButtons[menu_index]),sizeof(bp)); memcpy_P(&button,bp,sizeof(button)); endSelector(&button); - - //TODO: activate button - Serial.print(F("Select button ")); - Serial.print(menu_index); - Serial.print(F(":")); - Serial.println(button.text); + button.on_select(); } else{ initSelector(&mainMenuSelectedItemRaw, @@ -164,13 +159,10 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, //We treat long and short presses the same, so no need to have a switch Button button; if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&button,touch_point)){ - //TODO: activate button - Serial.print(F("Touch button ")); - Serial.println(button.text); + button.on_select(); } else{ //Touch detected, but not on our buttons, so ignore - Serial.println(F("Touch not on button")); } }//touch_button From 4a27962a5b844e849c5a2ae9045d4ffebdab1675 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 22:18:52 -0800 Subject: [PATCH 192/324] Save settings on VFO change or sideband change --- menu_main_buttons.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index ccd155d..bf78694 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -349,6 +349,7 @@ ButtonStatus_e bsVfo(const Vfo_e vfo){ void osVfo(const Vfo_e vfo){ globalSettings.activeVfo = vfo; + SaveSettingsToEeprom(); } void toVfoA(char* text_out, const uint16_t max_text_size){ @@ -410,6 +411,7 @@ void osRit(){ void osSidebandMode(VfoMode_e mode){ SetActiveVfoMode(mode); + SaveSettingsToEeprom(); Button button; memcpy_P(&button,&bUsb,sizeof(button)); From 70a1025603e7cb64a62b547fb12849c507a5267b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 22:59:44 -0800 Subject: [PATCH 193/324] Fix progmem extraction --- bands.cpp | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/bands.cpp b/bands.cpp index ab900d6..2f3c1f4 100644 --- a/bands.cpp +++ b/bands.cpp @@ -10,7 +10,7 @@ struct Band_t { uint32_t min; uint32_t max; uint8_t band_meters; - const char name[3];//Two characters + null terminator. Fixed width so we don't need to build separate pointers + char name[3];//Two characters + null terminator. Fixed width so we don't need to build separate pointers }; const char UNKNOWN_BAND_NAME [] PROGMEM = "??"; @@ -33,10 +33,12 @@ constexpr Band_t bands [] PROGMEM { }; constexpr uint8_t NUM_BANDS = sizeof(bands)/sizeof(bands[0]); -int8_t findBandIndexFromBand(const uint8_t band) +int8_t findBandIndexFromBand(const uint8_t target_band) { + Band_t band; for(uint8_t i = 0; i < NUM_BANDS; ++i){ - if(band == bands[i].band_meters){ + memcpy_P(&band,&bands[i],sizeof(band)); + if(target_band == band.band_meters){ return i; } } @@ -46,9 +48,11 @@ int8_t findBandIndexFromBand(const uint8_t band) int8_t findBandIndexFromFreq(uint32_t frequency) { + Band_t band; for(uint8_t i = 0; i < NUM_BANDS; ++i){ - if(frequency <= bands[i].max){ - if(bands[i].min <= frequency){ + memcpy_P(&band,&bands[i],sizeof(band)); + if(frequency <= band.max){ + if(band.min <= frequency){ return i; } //No bands overlap, and they are ordered in strictly increasing frequency, so we need search no further @@ -68,7 +72,9 @@ void getBandString(const unsigned long frequency, strncpy_P(band_string_out,UNKNOWN_BAND_NAME,max_string_length); } else{ - strncpy_P(band_string_out,bands[band_index].name,max_string_length); + Band_t band; + memcpy_P(&band,&bands[band_index],sizeof(band)); + strncpy_P(band_string_out,band.name,max_string_length); } } @@ -86,28 +92,36 @@ uint32_t getFreqInBand(const uint32_t frequency, if(-1 == current_band_index){ //We're not in a known band - just go to the center of the target band - return ((bands[target_band_index].max - bands[target_band_index].min)/2/100)*100;//truncated 100Hz + Band_t band; + memcpy_P(&band,&bands[target_band_index],sizeof(band)); + return ((band.max - band.min)/2/100)*100;//truncated 100Hz } else{ //We're in a known band. Match the relative position in the target band. - const uint32_t range_current = bands[current_band_index].max - bands[current_band_index].min; - const uint32_t range_target = bands[target_band_index].max - bands[target_band_index].min; - return (((frequency - bands[current_band_index].min) * range_target / range_current + bands[target_band_index].min)/100)*100;//truncated 100Hz + Band_t current_band; + memcpy_P(¤t_band,&bands[current_band_index],sizeof(current_band)); + Band_t target_band; + memcpy_P(&target_band,&bands[target_band_index],sizeof(target_band)); + const uint32_t range_current = current_band.max - current_band.min; + const uint32_t range_target = target_band.max - target_band.min; + return (((frequency - current_band.min) * range_target / range_current + target_band.min)/100)*100;//truncated 100Hz } } bool isFreqInBand(const uint32_t frequency, - const uint8_t band) + const uint8_t check_band) { - int8_t band_index = findBandIndexFromBand(band); + int8_t band_index = findBandIndexFromBand(check_band); if(-1 == band_index){ //Unknown band - can't be in it return false; } - if( (frequency <= bands[band_index].max) - && (bands[band_index].min <= frequency)){ + Band_t band; + memcpy_P(&band,&bands[band_index],sizeof(band)); + if( (frequency <= band.max) + && (band.min <= frequency)){ return true; } From 405df5a7576fdef579d1a56fac9656421762f65b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 23:09:18 -0800 Subject: [PATCH 194/324] Add method to update band buttons --- menu_main_buttons.cpp | 37 ++++++++++++++++++++++++++++++++++++- menu_main_buttons.h | 1 + 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index bf78694..8d7113b 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -296,6 +296,20 @@ const Button* const buttons[] PROGMEM = { const Button* const* mainMenuButtons = buttons; const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(buttons) / sizeof(buttons[0]); +void updateBandButtons(const uint32_t old_freq) +{ + const Button* band_buttons[] = {&b80,&b40,&b30,&b20,&b17,&b15,&b10}; + const uint8_t bands [] = { 80, 40, 30, 20, 17, 15, 10}; + const uint32_t curr_freq = GetActiveVfoFreq(); + + Button button; + for(uint8_t i = 0; i < sizeof(bands)/sizeof(bands[0]); ++i){ + if(isFreqInBand(old_freq,bands[i]) != isFreqInBand(curr_freq,bands[i])){ + memcpy_P(&button,band_buttons[i],sizeof(button)); + drawButton(&button); + } + } +} void toVfo(char* text_out, const uint16_t max_text_size, const Vfo_e vfo) { @@ -348,8 +362,16 @@ ButtonStatus_e bsVfo(const Vfo_e vfo){ } void osVfo(const Vfo_e vfo){ + const uint32_t old_freq = GetActiveVfoFreq(); globalSettings.activeVfo = vfo; SaveSettingsToEeprom(); + + Button button; + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); + updateBandButtons(old_freq); } void toVfoA(char* text_out, const uint16_t max_text_size){ @@ -474,7 +496,20 @@ ButtonStatus_e bsBand(const uint8_t band){ } void osBand(const uint8_t band){ - SetActiveVfoFreq(getFreqInBand(GetActiveVfoFreq(),band)); + const uint32_t old_freq = GetActiveVfoFreq(); + SetActiveVfoFreq(getFreqInBand(old_freq,band)); + + Button button; + if(Vfo_e::VFO_A == globalSettings.activeVfo){ + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); + } + else if(Vfo_e::VFO_B == globalSettings.activeVfo){ + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); + } + + updateBandButtons(old_freq); } ButtonStatus_e bs80(){ diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 7efb414..9bb7319 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -9,3 +9,4 @@ extern const uint8_t MAIN_MENU_NUM_BUTTONS; extern const Button bVfoA; extern const Button bVfoB; +void updateBandButtons(const uint32_t old_freq); From 77fffccb467514d448e34504184e5a077261b535 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 23:10:06 -0800 Subject: [PATCH 195/324] update band buttons when tuning --- menu_main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/menu_main.cpp b/menu_main.cpp index 0610f9d..54a6bd9 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -61,7 +61,7 @@ void mainMenuTune(int16_t knob) } current_freq = GetActiveVfoFreq(); - uint32_t new_freq = current_freq + (50 * knob); + const uint32_t new_freq = current_freq + (50 * knob); //Transition from below to above the traditional threshold for USB if(current_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ @@ -74,6 +74,7 @@ void mainMenuTune(int16_t knob) } setFrequency(new_freq); + const uint32_t old_freq = current_freq; current_freq = new_freq; Button button; @@ -84,6 +85,7 @@ void mainMenuTune(int16_t knob) memcpy_P(&button,&bVfoB,sizeof(button)); } drawButton(&button); + updateBandButtons(old_freq); } MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, From 23ecb4e4b28fc5b28330e520bc96f705dfdab6d4 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 23:24:37 -0800 Subject: [PATCH 196/324] Upcast to uint64 to avoid overflow --- bands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bands.cpp b/bands.cpp index 2f3c1f4..353e7a5 100644 --- a/bands.cpp +++ b/bands.cpp @@ -104,7 +104,7 @@ uint32_t getFreqInBand(const uint32_t frequency, memcpy_P(&target_band,&bands[target_band_index],sizeof(target_band)); const uint32_t range_current = current_band.max - current_band.min; const uint32_t range_target = target_band.max - target_band.min; - return (((frequency - current_band.min) * range_target / range_current + target_band.min)/100)*100;//truncated 100Hz + return (((frequency - current_band.min) * (uint64_t)range_target / range_current + target_band.min)/100)*100;//truncated 100Hz } } From 5721e06a5152a3f07cc77ea0d3c21e770d0ddd4b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 23:31:14 -0800 Subject: [PATCH 197/324] Instantly update tuning when changing modes --- menu_main_buttons.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 8d7113b..a7083ec 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -433,6 +433,7 @@ void osRit(){ void osSidebandMode(VfoMode_e mode){ SetActiveVfoMode(mode); + setFrequency(GetActiveVfoFreq()); SaveSettingsToEeprom(); Button button; @@ -470,6 +471,8 @@ void osCw(){ globalSettings.tuningMode = TuningMode_e::TUNE_SSB; } + setFrequency(GetActiveVfoFreq()); + Button button; memcpy_P(&button,&bCw,sizeof(button)); drawButton(&button); From 423246f2b81a80f098bcc03f444698d2a3ec6560 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 11 Feb 2020 23:36:43 -0800 Subject: [PATCH 198/324] Add audio feedback for when entering/exiting bands --- menu_main_buttons.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index a7083ec..c11780b 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -7,6 +7,7 @@ #include "bands.h" #include "button.h" #include "color_theme.h" +#include "morse.h" #include "nano_gui.h" #include "settings.h" #include "ubitx.h"//setFrequency, b @@ -307,6 +308,7 @@ void updateBandButtons(const uint32_t old_freq) if(isFreqInBand(old_freq,bands[i]) != isFreqInBand(curr_freq,bands[i])){ memcpy_P(&button,band_buttons[i],sizeof(button)); drawButton(&button); + morseBool(ButtonStatus_e::Active == button.status()); } } } From 2d3cc48b199692279733a03b530633bf26ec37fd Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Wed, 12 Feb 2020 22:18:02 -0800 Subject: [PATCH 199/324] Play current frequency when VFO is selected --- menu_main_buttons.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index c11780b..e9f959e 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -368,6 +368,9 @@ void osVfo(const Vfo_e vfo){ globalSettings.activeVfo = vfo; SaveSettingsToEeprom(); + ltoa(GetActiveVfoFreq(),b,10); + morseText(b); + Button button; memcpy_P(&button,&bVfoA,sizeof(button)); drawButton(&button); From 4a0b0ec653d7cd9bf25e25a751cdf32d361149cf Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 14 Feb 2020 18:50:26 -0800 Subject: [PATCH 200/324] First pass at making numpad buttons --- menu_numpad_buttons.cpp | 158 ++++++++++++++++++++++++++++++++++++++++ menu_numpad_buttons.h | 11 +++ 2 files changed, 169 insertions(+) create mode 100644 menu_numpad_buttons.cpp create mode 100644 menu_numpad_buttons.h diff --git a/menu_numpad_buttons.cpp b/menu_numpad_buttons.cpp new file mode 100644 index 0000000..260b83d --- /dev/null +++ b/menu_numpad_buttons.cpp @@ -0,0 +1,158 @@ +#include "menu_numpad_buttons.h" + +#include + +#include "color_theme.h" +#include "nano_gui.h" +#include "settings.h" +#include "ubitx.h"//setFrequency, b +#include "utils.h" + +static const unsigned int LAYOUT_MODE_TEXT_X = 0; +static const unsigned int LAYOUT_MODE_TEXT_Y = 47; +static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; +static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; + +static const unsigned int LAYOUT_BUTTON_X = 2; +static const unsigned int LAYOUT_BUTTON_Y = LAYOUT_MODE_TEXT_Y + LAYOUT_MODE_TEXT_HEIGHT + 1; +static const unsigned int LAYOUT_BUTTON_WIDTH = 60; +static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; +static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; +static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; + +const uint32_t NUMPAD_MENU_EXIT_FREQ = -1; +uint32_t numpadMenuFrequency; + +#define D_STRINGIFY(x) #x +#define D_STRING(x) D_STRINGIFY(x) +#define NUMBER_BUTTON_GENERATE(number,x,y) \ + constexpr char txt##number [] PROGMEM = "" D_STRING(number);\ + ButtonStatus_e bs##number();\ + void os##number();\ + constexpr Button b##number PROGMEM = {\ + LAYOUT_BUTTON_X + x*LAYOUT_BUTTON_PITCH_X,\ + LAYOUT_BUTTON_Y + y*LAYOUT_BUTTON_PITCH_Y,\ + LAYOUT_BUTTON_WIDTH,\ + LAYOUT_BUTTON_HEIGHT,\ + txt##number,\ + nullptr,\ + bsNumpad,\ + os##number,\ + '0'+number\ + } + +ButtonStatus_e bsNumpad(void){ + return ButtonStatus_e::Stateless; +} + + +// 1 2 3 Ok +// 4 5 6 0 <- +// 7 8 9 Can +NUMBER_BUTTON_GENERATE(1,0,0); +NUMBER_BUTTON_GENERATE(2,1,0); +NUMBER_BUTTON_GENERATE(3,2,0); +NUMBER_BUTTON_GENERATE(4,0,1); +NUMBER_BUTTON_GENERATE(5,1,1); +NUMBER_BUTTON_GENERATE(6,2,1); +NUMBER_BUTTON_GENERATE(7,0,2); +NUMBER_BUTTON_GENERATE(8,1,2); +NUMBER_BUTTON_GENERATE(9,2,2); +NUMBER_BUTTON_GENERATE(0,3,1); + +constexpr char txtOk [] PROGMEM = "OK"; +void osOk(); +constexpr Button bOk PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtOk, + nullptr, + bsNumpad, + osOk, + 'K' +}; + +constexpr char txtBackspace [] PROGMEM = "<-"; +void osBackspace(); +constexpr Button bBackspace PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtBackspace, + nullptr, + bsNumpad, + osBackspace, + 'B' +}; + +constexpr char txtCancel [] PROGMEM = "Can"; +void osCancel(); +constexpr Button bCancel PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtCancel, + nullptr, + bsNumpad, + osCancel, + 'C' +}; + +//Declare in menu select order, not graphical order +const Button* const numpadMenuButtons [] PROGMEM = { + &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &b9, &b0, + &bOk, &bBackspace, &bCancel +}; +const uint8_t NUMPAD_MENU_NUM_BUTTONS = sizeof(numpadMenuButtons)/sizeof(numpadMenuButtons[0]); + +void updateCurrentEnteredFrequency(void) +{ + formatFreq(numpadMenuFrequency,b,sizeof(b),0); + displayText(b,LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT,COLOR_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); +} + +void osNumpad(uint8_t new_digit) +{ + numpadMenuFrequency *= 10; + numpadMenuFrequency += new_digit; + updateCurrentEnteredFrequency(); +} + +void osBackspace(void) +{ + numpadMenuFrequency /= 10; + updateCurrentEnteredFrequency(); +} + +#define NUMBER_ONSELECT_GENERATE(number) \ + void os##number(void){\ + osNumpad(number);\ + } + +NUMBER_ONSELECT_GENERATE(0); +NUMBER_ONSELECT_GENERATE(1); +NUMBER_ONSELECT_GENERATE(2); +NUMBER_ONSELECT_GENERATE(3); +NUMBER_ONSELECT_GENERATE(4); +NUMBER_ONSELECT_GENERATE(5); +NUMBER_ONSELECT_GENERATE(6); +NUMBER_ONSELECT_GENERATE(7); +NUMBER_ONSELECT_GENERATE(8); +NUMBER_ONSELECT_GENERATE(9); + +void osOk(void) +{ + SetActiveVfoFreq(numpadMenuFrequency); + SaveSettingsToEeprom(); + setFrequency(numpadMenuFrequency); + numpadMenuFrequency = NUMPAD_MENU_EXIT_FREQ; +} + +void osCancel(void) +{ + numpadMenuFrequency = NUMPAD_MENU_EXIT_FREQ; +} diff --git a/menu_numpad_buttons.h b/menu_numpad_buttons.h new file mode 100644 index 0000000..a7d555e --- /dev/null +++ b/menu_numpad_buttons.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "button.h" + +extern const Button* const numpadMenuButtons[]; +extern const uint8_t NUMPAD_MENU_NUM_BUTTONS; + +extern const uint32_t NUMPAD_MENU_EXIT_FREQ; +extern uint32_t numpadMenuFrequency; From d42571f7a5466e4d2df77fa148d52d86f387c91c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 14 Feb 2020 18:50:57 -0800 Subject: [PATCH 201/324] Start building out numpad menu --- menu_numpad.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++ menu_numpad.h | 2 ++ 2 files changed, 55 insertions(+) create mode 100644 menu_numpad.cpp create mode 100644 menu_numpad.h diff --git a/menu_numpad.cpp b/menu_numpad.cpp new file mode 100644 index 0000000..1f0d86d --- /dev/null +++ b/menu_numpad.cpp @@ -0,0 +1,53 @@ +#include "menu_numpad.h" +#include "menu_numpad_buttons.h" + +#include + +#include "color_theme.h" +#include "nano_gui.h" + +void initNumpad(void); +MenuReturn_e runNumpad(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); +Menu_t numpad_menu = { + initNumpad, + runNumpad, + nullptr +}; + +Menu_t *const numpadMenu = &numpad_menu; + +void drawNumpad(void) +{ + displayFillrect(0,47,320,200,COLOR_BACKGROUND); + Button button; + Button* bp; + for(uint8_t i = 0; i < NUMPAD_MENU_NUM_BUTTONS; ++i){ + memcpy_P(&bp, &(numpadMenuButtons[i]), sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + drawButton(&button); + } +} + +void initNumpad(void) +{ + numpadMenuFrequency = 0; + drawNumpad(); +} + +MenuReturn_e runNumpad(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob) +{ + (void)tuner_button;(void)touch_button;(void)touch_point;(void)knob;//TODO + + if(NUMPAD_MENU_EXIT_FREQ == numpadMenuFrequency){ + return MenuReturn_e::ExitedRedraw; + } + else{ + return MenuReturn_e::StillActive; + } +} \ No newline at end of file diff --git a/menu_numpad.h b/menu_numpad.h new file mode 100644 index 0000000..ae53306 --- /dev/null +++ b/menu_numpad.h @@ -0,0 +1,2 @@ +#include "menu.h" +extern Menu_t* const numpadMenu; From 04560ef8b63d4f33e1a01f8af8e9b5a49055db2e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 14 Feb 2020 18:51:28 -0800 Subject: [PATCH 202/324] Add numpad functionality to main menu --- menu_main.cpp | 2 -- menu_main_buttons.cpp | 12 ++++++------ menu_main_buttons.h | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 54a6bd9..50a2807 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -29,8 +29,6 @@ Menu_t* const rootMenu = &mainMenu; bool mainMenuSelecting = false;//Tracks if we're selecting buttons with knob, or adjusting frequency int16_t mainMenuSelectedItemRaw = 0;//Allow negative only for easier checks on wrap around -extern Button* const* buttons; - void drawMainMenu(void) { displayClear(COLOR_BACKGROUND); diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index e9f959e..42c6266 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -7,6 +7,8 @@ #include "bands.h" #include "button.h" #include "color_theme.h" +#include "menu_main.h" +#include "menu_numpad.h" #include "morse.h" #include "nano_gui.h" #include "settings.h" @@ -286,7 +288,7 @@ constexpr Button bNumpad PROGMEM = { 'F' }; -const Button* const buttons[] PROGMEM = { +const Button* const mainMenuButtons [] PROGMEM = { &bVfoA, &bVfoB, &bRit, &bUsb, &bLsb, &bCw, &bSpl, @@ -294,8 +296,7 @@ const Button* const buttons[] PROGMEM = { &b15, &b10, &bMenu, &bNumpad }; -const Button* const* mainMenuButtons = buttons; -const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(buttons) / sizeof(buttons[0]); +const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); void updateBandButtons(const uint32_t old_freq) { @@ -587,7 +588,6 @@ void osMenu(){ } void osNumpad(){ - //TODO - //numpadMenu->initMenu(); - //mainMenu.active_submenu = numpadMenu; + numpadMenu->initMenu(); + rootMenu->active_submenu = numpadMenu; } diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 9bb7319..91df8fa 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -4,7 +4,7 @@ #include "button.h" -extern const Button* const* mainMenuButtons; +extern const Button* const mainMenuButtons[]; extern const uint8_t MAIN_MENU_NUM_BUTTONS; extern const Button bVfoA; From 2f964b3ffbd0dda3fb0e0061fbfd42f57a0374bc Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 14 Feb 2020 18:53:04 -0800 Subject: [PATCH 203/324] Remove unused function --- menu_main.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 50a2807..9830557 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -41,14 +41,6 @@ void drawMainMenu(void) } } -MenuReturn_e runStartupMenu(const ButtonPress_e, - const ButtonPress_e, - const Point, - const int16_t) -{ - return MenuReturn_e::ExitedRedraw; -} - void mainMenuTune(int16_t knob) { static uint32_t current_freq = 0; From f47c45194e7233fd847fc09a87231fac458df77e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 14 Feb 2020 19:05:12 -0800 Subject: [PATCH 204/324] Add actual menu running functions --- menu_numpad.cpp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/menu_numpad.cpp b/menu_numpad.cpp index 1f0d86d..847fb2e 100644 --- a/menu_numpad.cpp +++ b/menu_numpad.cpp @@ -4,6 +4,7 @@ #include #include "color_theme.h" +#include "menu_utils.h" #include "nano_gui.h" void initNumpad(void); @@ -19,6 +20,8 @@ Menu_t numpad_menu = { Menu_t *const numpadMenu = &numpad_menu; +int16_t numpadMenuSelectedItemRaw = 0;//Allow negative only for easier checks on wrap around + void drawNumpad(void) { displayFillrect(0,47,320,200,COLOR_BACKGROUND); @@ -35,6 +38,10 @@ void initNumpad(void) { numpadMenuFrequency = 0; drawNumpad(); + initSelector(&numpadMenuSelectedItemRaw, + numpadMenuButtons, + NUMPAD_MENU_NUM_BUTTONS, + MorsePlaybackType_e::PlayChar); } MenuReturn_e runNumpad(const ButtonPress_e tuner_button, @@ -42,7 +49,34 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button, const Point touch_point, const int16_t knob) { - (void)tuner_button;(void)touch_button;(void)touch_point;(void)knob;//TODO + if(ButtonPress_e::NotPressed != tuner_button){ + //We treat long and short presses the same, so no need to have a switch + uint8_t menu_index = numpadMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + Button button; + Button* bp; + memcpy_P(&bp,&(numpadMenuButtons[menu_index]),sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + button.on_select(); + }//tuner_button + + else if(ButtonPress_e::NotPressed != touch_button){ + //We treat long and short presses the same, so no need to have a switch + Button button; + if(findPressedButton(numpadMenuButtons,NUMPAD_MENU_NUM_BUTTONS,&button,touch_point)){ + button.on_select(); + } + else{ + //Touch detected, but not on our buttons, so ignore + } + }//touch_button + + else{//Neither button input type found, so handle the knob + adjustSelector(&numpadMenuSelectedItemRaw, + knob, + numpadMenuButtons, + NUMPAD_MENU_NUM_BUTTONS, + MorsePlaybackType_e::PlayChar); + } if(NUMPAD_MENU_EXIT_FREQ == numpadMenuFrequency){ return MenuReturn_e::ExitedRedraw; From bba125590b0e686a4143b5d8bbe28aedf54fccd7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 14 Feb 2020 19:16:11 -0800 Subject: [PATCH 205/324] Change rendering of the input frequency --- menu_numpad_buttons.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/menu_numpad_buttons.cpp b/menu_numpad_buttons.cpp index 260b83d..a70bf17 100644 --- a/menu_numpad_buttons.cpp +++ b/menu_numpad_buttons.cpp @@ -1,6 +1,7 @@ #include "menu_numpad_buttons.h" #include +#include //F() #include "color_theme.h" #include "nano_gui.h" @@ -8,9 +9,9 @@ #include "ubitx.h"//setFrequency, b #include "utils.h" -static const unsigned int LAYOUT_MODE_TEXT_X = 0; +static const unsigned int LAYOUT_MODE_TEXT_X = 60; static const unsigned int LAYOUT_MODE_TEXT_Y = 47; -static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; +static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 140; static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; static const unsigned int LAYOUT_BUTTON_X = 2; @@ -112,7 +113,8 @@ const uint8_t NUMPAD_MENU_NUM_BUTTONS = sizeof(numpadMenuButtons)/sizeof(numpadM void updateCurrentEnteredFrequency(void) { formatFreq(numpadMenuFrequency,b,sizeof(b),0); - displayText(b,LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT,COLOR_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); + strncat_P(b,(const char*)F(" Hz"),sizeof(b)-strlen(b)); + displayText(b,LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT,COLOR_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND,TextJustification_e::Right); } void osNumpad(uint8_t new_digit) From 4582521f1b68bd9162b231c98a37ee87e4f4f62e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Fri, 14 Feb 2020 19:28:58 -0800 Subject: [PATCH 206/324] Play current frequency on entering --- menu_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/menu_main.cpp b/menu_main.cpp index 9830557..9532e0c 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -39,6 +39,8 @@ void drawMainMenu(void) memcpy_P(&button,bp,sizeof(button)); drawButton(&button); } + ltoa(GetActiveVfoFreq(),b,10); + morseText(b); } void mainMenuTune(int16_t knob) From 72e4a71a4da3015b54b8dbc37b7bcb9c249d82ac Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 12:36:01 -0800 Subject: [PATCH 207/324] First pass at splitting runSetting into Menu_t-compatible functions --- setup.cpp | 61 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/setup.cpp b/setup.cpp index 7f7085a..83deed5 100644 --- a/setup.cpp +++ b/setup.cpp @@ -87,58 +87,61 @@ struct SettingScreen_t { void (*Finalize)(const long int final_value); }; -void runSetting(const SettingScreen_t* const p_screen) +void drawSetting(const SettingScreen_t* const p_screen) { SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; memcpy_P(&screen,p_screen,sizeof(screen)); displayDialog(screen.Title, screen.AdditionalText); +} - //Wait for button to stop being pressed - while(btnDown()){ - active_delay(10); - } - active_delay(10); - long int raw_value = 0; - long int last_value = 0; +int32_t setupMenuRawValue = 0; +int32_t setupMenuLastValue = 0; - screen.Initialize(&last_value); - screen.OnValueChange(last_value,b,sizeof(b)); +void initSetting(const SettingScreen_t* const p_screen) +{ + drawSetting(p_screen); + screen.Initialize(&setupMenuLastValue); + screen.OnValueChange(setupMenuLastValue,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); + setupMenuRawValue = setupMenuLastValue * (int32_t)screen.KnobDivider; +} - raw_value = last_value * (int32_t)screen.KnobDivider; +MenuReturn_e runSetting(const SettingScreen_t* const p_screen, + const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob) +{ + if(ButtonPress_e::NotPressed != tuner_button){ + //Long or short press, we do the same thing + screen.Finalize(setupMenuLastValue); + return MenuReturn_e::ExitedRedraw; + } - while (!btnDown()) - { - int knob = enc_read(); - if(knob != 0){ - raw_value += knob * screen.StepSize; - } - else{ - continue; - } + //TODO: handle touch input? - const long int candidate_value = raw_value / (int32_t)screen.KnobDivider; - long int value = 0; + else if(0 != knob){ + setupMenuRawValue += knob * screen.StepSize; + + const int32_t candidate_value = setupMenuRawValue / (int32_t)screen.KnobDivider; + int32_t value = 0; screen.Validate(candidate_value,&value); //If we're going out of bounds, prevent the raw value from going too far out if(candidate_value != value){ - raw_value = value * (int32_t)screen.KnobDivider; + setupMenuRawValue = value * (int32_t)screen.KnobDivider; } - if(value == last_value){ - continue; - } - else{ + if(value != setupMenuLastValue){{ screen.OnValueChange(value,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); - last_value = value; + setupMenuLastValue = value; } } - screen.Finalize(last_value); + return MenuReturn_e::StillActive; } //Local Oscillator From c8a90efee86cab248f7b4fdc7af443695a4299b7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 13:49:09 -0800 Subject: [PATCH 208/324] First pass at making menu selector run like a Menu_t --- setup.cpp | 122 ++++++++++++++++++++++++------------------------------ 1 file changed, 53 insertions(+), 69 deletions(-) diff --git a/setup.cpp b/setup.cpp index 83deed5..cdea9d1 100644 --- a/setup.cpp +++ b/setup.cpp @@ -1,5 +1,6 @@ #include #include "colors.h" +#include "menu.h" #include "morse.h" #include "nano_gui.h" #include "setup.h" @@ -101,6 +102,8 @@ int32_t setupMenuLastValue = 0; void initSetting(const SettingScreen_t* const p_screen) { + SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; + memcpy_P(&screen,p_screen,sizeof(screen)); drawSetting(p_screen); screen.Initialize(&setupMenuLastValue); screen.OnValueChange(setupMenuLastValue,b,sizeof(b)); @@ -114,13 +117,18 @@ MenuReturn_e runSetting(const SettingScreen_t* const p_screen, const Point touch_point, const int16_t knob) { + SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; + memcpy_P(&screen,p_screen,sizeof(screen)); + if(ButtonPress_e::NotPressed != tuner_button){ //Long or short press, we do the same thing + SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; + memcpy_P(&screen,p_screen,sizeof(screen)); screen.Finalize(setupMenuLastValue); return MenuReturn_e::ExitedRedraw; } - //TODO: handle touch input? + (void)touch_button;(void)touch_point;//TODO: handle touch input? else if(0 != knob){ setupMenuRawValue += knob * screen.StepSize; @@ -134,7 +142,7 @@ MenuReturn_e runSetting(const SettingScreen_t* const p_screen, setupMenuRawValue = value * (int32_t)screen.KnobDivider; } - if(value != setupMenuLastValue){{ + if(value != setupMenuLastValue){ screen.OnValueChange(value,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); setupMenuLastValue = value; @@ -523,7 +531,8 @@ void drawMenu(const MenuItem_t* const items, const uint16_t num_items) displayText(b, LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (num_items-1)*LAYOUT_ITEM_PITCH_Y, LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_INACTIVE_BORDER, TextJustification_e::Left); } -void movePuck(unsigned int old_index, unsigned int new_index) +void movePuck(unsigned int old_index, + unsigned int new_index) { //Don't update if we're already on the right selection if(old_index == new_index){ @@ -537,81 +546,56 @@ void movePuck(unsigned int old_index, unsigned int new_index) displayRect(LAYOUT_ITEM_X, LAYOUT_ITEM_Y + (new_index*LAYOUT_ITEM_PITCH_Y), LAYOUT_ITEM_WIDTH, LAYOUT_ITEM_HEIGHT, COLOR_ACTIVE_BORDER); } -void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items) -{ - static const unsigned int COUNTS_PER_ITEM = 10; - const int MAX_KNOB_VALUE = num_items*COUNTS_PER_ITEM - 1; - int knob_sum = 0; - unsigned int old_index = -1; +int16_t setupMenuSelector = 0; +void initSetupMenu(const MenuItem_t* const menu_items, + const uint16_t num_items) +{ drawMenu(menu_items,num_items); + setupMenuSelector = 0; movePuck(-1,0);//Force draw of puck +} - //wait for the button to be raised up - while(btnDown()){ - active_delay(50); - } - active_delay(50); //debounce - - while (true){ - knob_sum += enc_read(); - if(knob_sum < 0){ - knob_sum = 0; - } - else if(MAX_KNOB_VALUE < knob_sum){ - knob_sum = MAX_KNOB_VALUE; - } - - uint16_t index = knob_sum/COUNTS_PER_ITEM; - movePuck(old_index,index); +MenuReturn_e runSetupMenu(const MenuItem_t* const menu_items, + const uint16_t num_items, + const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob) +{ + const int16_t cur_index = setupMenuSelector/MENU_KNOB_COUNTS_PER_ITEM; + const int16_t exit_index = num_items - 1; - if(globalSettings.morseMenuOn //Only spend cycles copying menu item into RAM if we actually need to - && (old_index != index)){ - if(num_items-1 > index){ - MenuItem_t mi = {"",nullptr}; - memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 - strncpy_P(b,mi.ItemName,sizeof(b)); - } - else{ - strncpy_P(b,MI_EXIT,sizeof(b)); - } - morseText(b); - enc_read();//Consume any rotations during morse playback + if(ButtonPress_e::NotPressed != tuner_button){ + //Don't care what kind of press + if(exit_index <= cur_index){ + return MenuReturn_e::ExitedRedraw; } - old_index = index; + MenuItem_t mi = {"",nullptr}; + memcpy_P(&mi,&menu_items[cur_index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 + mi.OnSelect(); + } - if (!btnDown()){ - active_delay(50); - continue; - } + (void)touch_button;(void)touch_point;//TODO: handle touch input? - //wait for the touch to lift off and debounce - while(btnDown()){ - active_delay(50); - } - active_delay(50);//debounce - - if(num_items-1 > index){ - MenuItem_t mi = {"",nullptr}; - memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 - mi.OnSelect(); - drawMenu(menu_items,num_items);//Need to re-render, since whatever ran just now is assumed to have drawn something - old_index = -1;//Force redraw - } - else{ - break; + else if(0 != knob){ + setupMenuSelector += knob; + LIMIT(setupMenuSelector,0,num_items*MENU_KNOB_COUNTS_PER_ITEM - 1); + const int16_t new_index = setupMenuSelector/MENU_KNOB_COUNTS_PER_ITEM; + if(cur_index != new_index){ + movePuck(cur_index,newindex); + if(globalSettings.morseMenuOn){//Only spend cycles copying menu item into RAM if we actually need to + if(exit_index <= cur_index){ + strncpy_P(b,MI_EXIT,sizeof(b)); + } + else{ + MenuItem_t mi = {"",nullptr}; + memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 + strncpy_P(b,mi.ItemName,sizeof(b)); + } + morseText(b); + } } } - - //debounce the button - while(btnDown()){ - active_delay(50); - } - active_delay(50);//debounce -} - -void doSetup2(){ - RUN_MENU(mainMenu); - guiUpdate(); } From e9e134079a6fdc585d3b45c50f07b80f5b9bdd23 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 13:49:30 -0800 Subject: [PATCH 209/324] Create a root menu for setup --- setup.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/setup.h b/setup.h index 16b5b0d..16e6c07 100644 --- a/setup.h +++ b/setup.h @@ -1,6 +1,9 @@ #pragma once -void doSetup2(); //main setup function, displays the setup menu, calls various dialog boxes +#include "menu.h" + +extern Menu_t* const setupMenu; + void setupTouch(); void runLocalOscSetting(); void runBfoSetting(); \ No newline at end of file From 3dcbb8a0fe7b11cd83228fc96ee44860ee98a614 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 14:14:44 -0800 Subject: [PATCH 210/324] Small whitespace change --- menu_utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_utils.cpp b/menu_utils.cpp index a2531f6..11e0fe7 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -8,7 +8,7 @@ #include "nano_gui.h" #include "utils.h" -bool runSubmenu(Menu_t* const current_menu, +bool runSubmenu(Menu_t *const current_menu, void(*const redraw_callback)(), const ButtonPress_e tuner_button, const ButtonPress_e touch_button, From 0b96cfb1f78dc70f0685802b4d1ca8442b8251b0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 14:17:55 -0800 Subject: [PATCH 211/324] Simplification of setting extraction, and setting menu running --- setup.cpp | 78 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/setup.cpp b/setup.cpp index cdea9d1..fb0d12c 100644 --- a/setup.cpp +++ b/setup.cpp @@ -88,49 +88,64 @@ struct SettingScreen_t { void (*Finalize)(const long int final_value); }; -void drawSetting(const SettingScreen_t* const p_screen) +void drawSetting(const SettingScreen_t* const screen) { - SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; - memcpy_P(&screen,p_screen,sizeof(screen)); displayDialog(screen.Title, screen.AdditionalText); } - +//State variables for settings int32_t setupMenuRawValue = 0; int32_t setupMenuLastValue = 0; +SettingScreen_t* activeSettingP; + +void activateSetting(SettingScreen_t* new_setting_P); + +void initSetting(); +MenuReturn_e runSetting(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); +Menu_t setupMenuActiveSettingMenu = { + initSetting, + runSetting, + nullptr +}; -void initSetting(const SettingScreen_t* const p_screen) +void initSetting() { + if(nullptr == activeSettingP){ + return; + } SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; - memcpy_P(&screen,p_screen,sizeof(screen)); - drawSetting(p_screen); + memcpy_P(&screen,activeSettingP,sizeof(screen)); + drawSetting(screen); screen.Initialize(&setupMenuLastValue); screen.OnValueChange(setupMenuLastValue,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); setupMenuRawValue = setupMenuLastValue * (int32_t)screen.KnobDivider; } -MenuReturn_e runSetting(const SettingScreen_t* const p_screen, - const ButtonPress_e tuner_button, +MenuReturn_e runSetting(const ButtonPress_e tuner_button, const ButtonPress_e touch_button, const Point touch_point, const int16_t knob) { + if(nullptr == activeSettingP){ + return MenuReturn_e::ExitedRedraw; + } SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; - memcpy_P(&screen,p_screen,sizeof(screen)); + memcpy_P(&screen,activeSettingP,sizeof(screen)); if(ButtonPress_e::NotPressed != tuner_button){ //Long or short press, we do the same thing - SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; - memcpy_P(&screen,p_screen,sizeof(screen)); screen.Finalize(setupMenuLastValue); return MenuReturn_e::ExitedRedraw; } (void)touch_button;(void)touch_point;//TODO: handle touch input? - else if(0 != knob){ + if(0 != knob){ setupMenuRawValue += knob * screen.StepSize; const int32_t candidate_value = setupMenuRawValue / (int32_t)screen.KnobDivider; @@ -152,6 +167,16 @@ MenuReturn_e runSetting(const SettingScreen_t* const p_screen, return MenuReturn_e::StillActive; } +void activateSetting(SettingScreen_t* new_setting_P) +{ + Menu_t* current_menu = setupMenu; + while(nullptr != current_menu->active_submenu){ + current_menu = current_menu->active_submenu; + } + current_menu->active_submenu = &setupMenuActiveSettingMenu; + activeSettingP = new_setting_P; +} + //Local Oscillator void ssLocalOscInitialize(long int* start_value_out){ { @@ -196,7 +221,7 @@ const SettingScreen_t ssLocalOsc PROGMEM = { ssLocalOscChange, ssLocalOscFinalize }; -void runLocalOscSetting(){runSetting(&ssLocalOsc);} +void runLocalOscSetting(){activateSetting(&ssLocalOsc);} //BFO void ssBfoInitialize(long int* start_value_out){ @@ -234,7 +259,7 @@ const SettingScreen_t ssBfo PROGMEM = { ssBfoChange, ssBfoFinalize }; -void runBfoSetting(){runSetting(&ssBfo);} +void runBfoSetting(){activateSetting(&ssBfo);} //CW Tone void ssCwToneInitialize(long int* start_value_out) @@ -270,7 +295,7 @@ const SettingScreen_t ssTone PROGMEM = { ssCwToneChange, ssCwToneFinalize }; -void runToneSetting(){runSetting(&ssTone);} +void runToneSetting(){activateSetting(&ssTone);} //CW Switch Delay void ssCwSwitchDelayInitialize(long int* start_value_out) @@ -305,7 +330,7 @@ const SettingScreen_t ssCwSwitchDelay PROGMEM = { ssCwSwitchDelayChange, ssCwSwitchDelayFinalize }; -void runCwSwitchDelaySetting(){runSetting(&ssCwSwitchDelay);} +void runCwSwitchDelaySetting(){activateSetting(&ssCwSwitchDelay);} //CW Keyer void ssKeyerInitialize(long int* start_value_out) @@ -351,7 +376,7 @@ const SettingScreen_t ssKeyer PROGMEM = { ssKeyerChange, ssKeyerFinalize }; -void runKeyerSetting(){runSetting(&ssKeyer);} +void runKeyerSetting(){activateSetting(&ssKeyer);} //Morse menu playback void ssMorseMenuInitialize(long int* start_value_out) @@ -393,7 +418,7 @@ const SettingScreen_t ssMorseMenu PROGMEM = { ssMorseMenuChange, ssMorseMenuFinalize }; -void runMorseMenuSetting(){runSetting(&ssMorseMenu);} +void runMorseMenuSetting(){activateSetting(&ssMorseMenu);} //CW Speed void ssCwSpeedInitialize(long int* start_value_out) @@ -427,7 +452,7 @@ const SettingScreen_t ssCwSpeed PROGMEM = { ssCwSpeedChange, ssCwSpeedFinalize }; -void runCwSpeedSetting(){runSetting(&ssCwSpeed);} +void runCwSpeedSetting(){activateSetting(&ssCwSpeed);} //Reset all settings void ssResetAllInitialize(long int* start_value_out) @@ -472,11 +497,16 @@ const SettingScreen_t ssResetAll PROGMEM = { ssResetAllChange, ssResetAllFinalize }; -void runResetAllSetting(){runSetting(&ssResetAll);} +void runResetAllSetting(){activateSetting(&ssResetAll);} + +void osResetAllSettings(Menu_t *const current_menu) +{ + current_menu->active_submenu = +} struct MenuItem_t { const char* const ItemName; - void (*OnSelect)(); + void (*OnSelect)(Menu_t *const current_menu); }; void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); @@ -579,7 +609,7 @@ MenuReturn_e runSetupMenu(const MenuItem_t* const menu_items, (void)touch_button;(void)touch_point;//TODO: handle touch input? - else if(0 != knob){ + if(0 != knob){ setupMenuSelector += knob; LIMIT(setupMenuSelector,0,num_items*MENU_KNOB_COUNTS_PER_ITEM - 1); const int16_t new_index = setupMenuSelector/MENU_KNOB_COUNTS_PER_ITEM; @@ -598,4 +628,6 @@ MenuReturn_e runSetupMenu(const MenuItem_t* const menu_items, } } } + + return MenuReturn_e::StillActive; } From 2bfa97687d6620f5a8eeff5f7fc2a80963d1e44b Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 14:29:23 -0800 Subject: [PATCH 212/324] Fix compiler errors --- setup.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/setup.cpp b/setup.cpp index fb0d12c..25994de 100644 --- a/setup.cpp +++ b/setup.cpp @@ -90,14 +90,14 @@ struct SettingScreen_t { void drawSetting(const SettingScreen_t* const screen) { - displayDialog(screen.Title, - screen.AdditionalText); + displayDialog(screen->Title, + screen->AdditionalText); } //State variables for settings int32_t setupMenuRawValue = 0; int32_t setupMenuLastValue = 0; -SettingScreen_t* activeSettingP; +const SettingScreen_t* activeSettingP; void activateSetting(SettingScreen_t* new_setting_P); @@ -119,7 +119,7 @@ void initSetting() } SettingScreen_t screen = {nullptr,nullptr,0,0,nullptr,nullptr,nullptr,nullptr}; memcpy_P(&screen,activeSettingP,sizeof(screen)); - drawSetting(screen); + drawSetting(&screen); screen.Initialize(&setupMenuLastValue); screen.OnValueChange(setupMenuLastValue,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); @@ -167,7 +167,7 @@ MenuReturn_e runSetting(const ButtonPress_e tuner_button, return MenuReturn_e::StillActive; } -void activateSetting(SettingScreen_t* new_setting_P) +void activateSetting(const SettingScreen_t *const new_setting_P) { Menu_t* current_menu = setupMenu; while(nullptr != current_menu->active_submenu){ @@ -499,14 +499,9 @@ const SettingScreen_t ssResetAll PROGMEM = { }; void runResetAllSetting(){activateSetting(&ssResetAll);} -void osResetAllSettings(Menu_t *const current_menu) -{ - current_menu->active_submenu = -} - struct MenuItem_t { const char* const ItemName; - void (*OnSelect)(Menu_t *const current_menu); + void (*OnSelect)(); }; void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); @@ -578,6 +573,13 @@ void movePuck(unsigned int old_index, int16_t setupMenuSelector = 0; +Menu_t setup_menu = { + nullptr,//TODO + nullptr,//TODO + nullptr +}; +Menu_t *const setupMenu = &setup_menu; + void initSetupMenu(const MenuItem_t* const menu_items, const uint16_t num_items) { @@ -610,18 +612,17 @@ MenuReturn_e runSetupMenu(const MenuItem_t* const menu_items, (void)touch_button;(void)touch_point;//TODO: handle touch input? if(0 != knob){ - setupMenuSelector += knob; - LIMIT(setupMenuSelector,0,num_items*MENU_KNOB_COUNTS_PER_ITEM - 1); + setupMenuSelector = LIMIT(setupMenuSelector + knob,0,(int16_t)(num_items*MENU_KNOB_COUNTS_PER_ITEM - 1)); const int16_t new_index = setupMenuSelector/MENU_KNOB_COUNTS_PER_ITEM; if(cur_index != new_index){ - movePuck(cur_index,newindex); + movePuck(cur_index,new_index); if(globalSettings.morseMenuOn){//Only spend cycles copying menu item into RAM if we actually need to if(exit_index <= cur_index){ strncpy_P(b,MI_EXIT,sizeof(b)); } else{ MenuItem_t mi = {"",nullptr}; - memcpy_P(&mi,&menu_items[index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 + memcpy_P(&mi,&menu_items[cur_index+1],sizeof(mi));//The 0th element in the array is the title, so offset by 1 strncpy_P(b,mi.ItemName,sizeof(b)); } morseText(b); From 98adba28ba7afaec0feb4f005f865751ca09eff4 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 14:43:05 -0800 Subject: [PATCH 213/324] Have a high level function in charge of finding the active submenu --- menu.cpp | 32 ++++++++++++++++++++++++++++++++ menu.h | 5 +++++ menu_main.cpp | 14 -------------- menu_utils.cpp | 29 ----------------------------- menu_utils.h | 8 -------- ubitxv6.ino | 2 +- 6 files changed, 38 insertions(+), 52 deletions(-) create mode 100644 menu.cpp diff --git a/menu.cpp b/menu.cpp new file mode 100644 index 0000000..dd00a78 --- /dev/null +++ b/menu.cpp @@ -0,0 +1,32 @@ +#include "menu.h" +#include "menu_main.h" + +void runActiveMenu(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob) +{ + Menu_t* parent_menu = rootMenu;//rootMenu is it's own parent + Menu_t* active_menu = rootMenu; + while(nullptr != active_menu->active_submenu){ + parent_menu = active_menu; + active_menu = parent_menu->active_submenu; + } + MenuReturn_e mr = active_menu->runMenu(tuner_button,touch_button,touch_point,knob); + switch(mr){ + case MenuReturn_e::StillActive://Fallthrough intended + case MenuReturn_e::ExitedNoRedraw: + { + //Nothing to do here - just return + break; + } + default://Fallthrough intended. Default to this menu being active + case MenuReturn_e::ExitedRedraw: + { + //Turn off submenu, redraw, then return + parent_menu->active_submenu = nullptr; + parent_menu->initMenu(); + break; + } + }//end switch +} diff --git a/menu.h b/menu.h index b54e3ff..97d06a6 100644 --- a/menu.h +++ b/menu.h @@ -25,3 +25,8 @@ struct Menu_t { }; static const uint8_t MENU_KNOB_COUNTS_PER_ITEM = 10; + +void runActiveMenu(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); diff --git a/menu_main.cpp b/menu_main.cpp index 9532e0c..fb824ad 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -85,20 +85,6 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, const Point touch_point, const int16_t knob) { - if(runSubmenu(&mainMenu, - drawMainMenu, - tuner_button, - touch_button, - touch_point, - knob)){ - //Submenu processed the input, so return now - mainMenuSelectedItemRaw = 0; - mainMenuSelecting = false; - return MenuReturn_e::StillActive;//main menu always returns StillActive - }//end submenu - - //Submenu didn't run, so handle the inputs ourselves - //Check tuner_button if(ButtonPress_e::NotPressed != tuner_button){ switch(tuner_button){ diff --git a/menu_utils.cpp b/menu_utils.cpp index 11e0fe7..d5fcf6e 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -8,35 +8,6 @@ #include "nano_gui.h" #include "utils.h" -bool runSubmenu(Menu_t *const current_menu, - void(*const redraw_callback)(), - const ButtonPress_e tuner_button, - const ButtonPress_e touch_button, - const Point touch_point, - const int16_t knob){ - if(nullptr != current_menu->active_submenu){ - auto ret = current_menu->active_submenu->runMenu(tuner_button,touch_button,touch_point,knob); - switch(ret){ - case MenuReturn_e::StillActive://Fallthrough intended - case MenuReturn_e::ExitedNoRedraw: - { - //Nothing to do here - just return - break; - } - default://Fallthrough intended. Default to this menu being active - case MenuReturn_e::ExitedRedraw: - { - //Turn off submenu, redraw, then return - current_menu->active_submenu = nullptr; - redraw_callback(); - break; - } - }//end switch - return true; - }//end submenu - return false; -} - bool findPressedButton(const Button* const* buttons, const uint8_t num_buttons, Button *const button_out, diff --git a/menu_utils.h b/menu_utils.h index 05f43d2..d84be30 100644 --- a/menu_utils.h +++ b/menu_utils.h @@ -3,14 +3,6 @@ #include "button.h" #include "menu.h" -//Returns true if submenu was run, false otherwise -bool runSubmenu(Menu_t* current_menu, - void(*const redraw_callback)(), - const ButtonPress_e tuner_button, - const ButtonPress_e touch_button, - const Point touch_point, - const int16_t knob); - //Returns true if button was found, false otherwise bool findPressedButton(const Button* const* buttons, const uint8_t num_buttons, diff --git a/ubitxv6.ino b/ubitxv6.ino index 92ff72a..6c6c5b7 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -506,5 +506,5 @@ void loop(){ Point touch_point; ButtonPress_e touch_button = checkTouch(&touch_point); int16_t knob = enc_read(); - rootMenu->runMenu(tuner_button,touch_button,touch_point,knob); + runActiveMenu(tuner_button,touch_button,touch_point,knob); } From cad3c3c57e1592685f040b06580c8d4976b716c2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 15:27:48 -0800 Subject: [PATCH 214/324] Add an enterSubmenu routine to centralize that behavior --- menu.cpp | 11 +++++++++++ menu.h | 2 ++ menu_main_buttons.cpp | 3 +-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/menu.cpp b/menu.cpp index dd00a78..680716d 100644 --- a/menu.cpp +++ b/menu.cpp @@ -30,3 +30,14 @@ void runActiveMenu(const ButtonPress_e tuner_button, } }//end switch } + +void enterSubmenu(Menu_t *const submenu) +{ + Menu_t* current_menu = rootMenu; + while(nullptr != current_menu->active_submenu){ + current_menu = current_menu->active_submenu; + } + current_menu->active_submenu = submenu; + submenu->initMenu(); +} + diff --git a/menu.h b/menu.h index 97d06a6..82a755e 100644 --- a/menu.h +++ b/menu.h @@ -30,3 +30,5 @@ void runActiveMenu(const ButtonPress_e tuner_button, const ButtonPress_e touch_button, const Point touch_point, const int16_t knob); + +void enterSubmenu(Menu_t *const submenu); diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 42c6266..ecd4982 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -588,6 +588,5 @@ void osMenu(){ } void osNumpad(){ - numpadMenu->initMenu(); - rootMenu->active_submenu = numpadMenu; + enterSubmenu(numpadMenu); } From 6481812b4f6a98d6394cc1e176731db5593c81a2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 15:31:14 -0800 Subject: [PATCH 215/324] Link in the setup menu. Exceeds available space :( --- menu_main_buttons.cpp | 5 ++-- setup.cpp | 63 ++++++++++++++++++++++++++++++------------- 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index ecd4982..534473d 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -12,6 +12,7 @@ #include "morse.h" #include "nano_gui.h" #include "settings.h" +#include "setup.h" #include "ubitx.h"//setFrequency, b #include "utils.h" @@ -582,9 +583,7 @@ ButtonStatus_e bsIgnore(){ } void osMenu(){ - //TODO - //rootSettingsMenu->initMenu(); - //mainmenu.active_submenu = rootSettingsMenu; + enterSubmenu(setupMenu); } void osNumpad(){ diff --git a/setup.cpp b/setup.cpp index 25994de..a43fbe1 100644 --- a/setup.cpp +++ b/setup.cpp @@ -169,12 +169,8 @@ MenuReturn_e runSetting(const ButtonPress_e tuner_button, void activateSetting(const SettingScreen_t *const new_setting_P) { - Menu_t* current_menu = setupMenu; - while(nullptr != current_menu->active_submenu){ - current_menu = current_menu->active_submenu; - } - current_menu->active_submenu = &setupMenuActiveSettingMenu; activeSettingP = new_setting_P; + enterSubmenu(&setupMenuActiveSettingMenu); } //Local Oscillator @@ -504,21 +500,55 @@ struct MenuItem_t { void (*OnSelect)(); }; -void runMenu(const MenuItem_t* const menu_items, const uint16_t num_items); -#define RUN_MENU(menu) runMenu(menu,sizeof(menu)/sizeof(menu[0])) +void initSetupMenu(const MenuItem_t* const menu_items, + const uint16_t num_items); +MenuReturn_e runSetupMenu(const MenuItem_t* const menu_items, + const uint16_t num_items, + const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); + +#define GENERATE_MENU_T(menu_name) \ + void initSetupMenu##menu_name(void)\ + {\ + initSetupMenu(menuItems##menu_name,sizeof(menuItems##menu_name)/sizeof(menuItems##menu_name[0]));\ + }\ + MenuReturn_e runSetupMenu##menu_name(const ButtonPress_e tuner_button,\ + const ButtonPress_e touch_button,\ + const Point touch_point,\ + const int16_t knob)\ + {\ + return runSetupMenu(menuItems##menu_name,\ + sizeof(menuItems##menu_name)/sizeof(menuItems##menu_name[0]),\ + tuner_button,\ + touch_button,\ + touch_point,\ + knob\ + );\ + }\ + Menu_t setupMenu##menu_name = {\ + initSetupMenu##menu_name,\ + runSetupMenu##menu_name,\ + nullptr\ + };\ + void run##menu_name##Menu(void)\ + {\ + enterSubmenu(&setupMenu##menu_name);\ + }\ const char MT_CAL [] PROGMEM = "Calibrations"; const char MI_TOUCH [] PROGMEM = "Touch Screen"; -const MenuItem_t calibrationMenu [] PROGMEM { +const MenuItem_t menuItemsCalibration [] PROGMEM { {MT_CAL,nullptr},//Title {SS_LOCAL_OSC_T,runLocalOscSetting}, {SS_BFO_T,runBfoSetting}, {MI_TOUCH,setupTouch}, }; -void runCalibrationMenu(){RUN_MENU(calibrationMenu);} +GENERATE_MENU_T(Calibration); const char MT_CW [] PROGMEM = "CW Setup"; -const MenuItem_t cwMenu [] PROGMEM { +const MenuItem_t menuItemsCw [] PROGMEM { {MT_CW,nullptr},//Title {SS_CW_TONE_T,runToneSetting}, {SS_CW_SWITCH_T,runCwSwitchDelaySetting}, @@ -526,15 +556,17 @@ const MenuItem_t cwMenu [] PROGMEM { {SS_MORSE_MENU_T,runMorseMenuSetting}, {SS_CW_SPEED_T,runCwSpeedSetting}, }; -void runCwMenu(){RUN_MENU(cwMenu);} +GENERATE_MENU_T(Cw); const char MT_SETTINGS [] PROGMEM = "Settings"; -const MenuItem_t mainMenu [] PROGMEM { +const MenuItem_t menuItemsSetupRoot [] PROGMEM { {MT_SETTINGS,nullptr},//Title {MT_CAL,runCalibrationMenu}, {MT_CW,runCwMenu}, {SS_RESET_ALL_T,runResetAllSetting}, }; +GENERATE_MENU_T(SetupRoot); +Menu_t *const setupMenu = &setupMenuSetupRoot; const char MI_EXIT [] PROGMEM = "Exit"; const MenuItem_t exitMenu PROGMEM = {MI_EXIT,nullptr}; @@ -573,13 +605,6 @@ void movePuck(unsigned int old_index, int16_t setupMenuSelector = 0; -Menu_t setup_menu = { - nullptr,//TODO - nullptr,//TODO - nullptr -}; -Menu_t *const setupMenu = &setup_menu; - void initSetupMenu(const MenuItem_t* const menu_items, const uint16_t num_items) { From f7229ebaf2b20135c778390d6c481fc8135d66ba Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 17:07:18 -0800 Subject: [PATCH 216/324] Save 406 bytes by refactoring the touch calibration routine --- nano_gui.cpp | 122 ++++++++++++++++++++------------------------------- 1 file changed, 47 insertions(+), 75 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index e6590bb..e3c699d 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -94,87 +94,59 @@ void displayText(const char *const text, int x1, int y1, int w, int h, int color displayRawText(text,x1,y1,w,color,background); } +void drawCross(int16_t x_center,int16_t y_center,uint16_t color) +{ + constexpr uint8_t HALF_SIZE = 10; + displayHline(x_center-HALF_SIZE,y_center,2*HALF_SIZE,color); + displayVline(x_center,y_center-HALF_SIZE,2*HALF_SIZE,color); +} + void setupTouch(){ - int x1, y1, x2, y2, x3, y3, x4, y4; - Point ts_point; + constexpr int16_t CROSS_CORNER_OFFSET = 20; + constexpr Point CROSS_CORNER_POINTS [] = { + {CROSS_CORNER_OFFSET,CROSS_CORNER_OFFSET},//Top left + {PDQ_ILI9341::ILI9341_TFTHEIGHT-CROSS_CORNER_OFFSET,CROSS_CORNER_OFFSET},//Top right + {CROSS_CORNER_OFFSET, PDQ_ILI9341::ILI9341_TFTWIDTH-CROSS_CORNER_OFFSET},//Bottom left + {PDQ_ILI9341::ILI9341_TFTHEIGHT-CROSS_CORNER_OFFSET,PDQ_ILI9341::ILI9341_TFTWIDTH-CROSS_CORNER_OFFSET}//Bottom right + }; displayClear(DISPLAY_BLACK); strncpy_P(b,(const char*)F("Click on the cross"),sizeof(b)); displayText(b, 20,100, 200, 50, DISPLAY_WHITE, DISPLAY_BLACK, DISPLAY_BLACK); - // TOP-LEFT - displayHline(10,20,20,DISPLAY_WHITE); - displayVline(20,10,20, DISPLAY_WHITE); - - while(!readTouch(&ts_point)) - delay(100); - while(readTouch(&ts_point)) - delay(100); - x1 = ts_point.x; - y1 = ts_point.y; - - //rubout the previous one - displayHline(10,20,20,DISPLAY_BLACK); - displayVline(20,10,20, DISPLAY_BLACK); - - delay(1000); - - //TOP RIGHT - displayHline(290,20,20,DISPLAY_WHITE); - displayVline(300,10,20, DISPLAY_WHITE); - - while(!readTouch(&ts_point)) - delay(100); - while(readTouch(&ts_point)) - delay(100); - x2 = ts_point.x; - y2 = ts_point.y; - - displayHline(290,20,20,DISPLAY_BLACK); - displayVline(300,10,20, DISPLAY_BLACK); - - delay(1000); - - //BOTTOM LEFT - displayHline(10,220,20,DISPLAY_WHITE); - displayVline(20,210,20, DISPLAY_WHITE); - - while(!readTouch(&ts_point)) - delay(100); - x3 = ts_point.x; - y3 = ts_point.y; - - while(readTouch(&ts_point)) - delay(100); - displayHline(10,220,20,DISPLAY_BLACK); - displayVline(20,210,20, DISPLAY_BLACK); - - delay(1000); - - //BOTTOM RIGHT - displayHline(290,220,20,DISPLAY_WHITE); - displayVline(300,210,20, DISPLAY_WHITE); - - while(!readTouch(&ts_point)) - delay(100); - x4 = ts_point.x; - y4 = ts_point.y; - - - displayHline(290,220,20,DISPLAY_BLACK); - displayVline(300,210,20, DISPLAY_BLACK); - - // we average two readings and divide them by half and store them as scaled integers 10 times their actual, fractional value - //the x points are located at 20 and 300 on x axis, hence, the delta x is 280, we take 28 instead, to preserve fractional value, - //there are two readings (x1,x2) and (x3, x4). Hence, we have to divide by 28 * 2 = 56 - globalSettings.touchSlopeX = ((x4 - x3) + (x2 - x1))/56; - //the y points are located at 20 and 220 on the y axis, hence, the delta is 200. we take it as 20 instead, to preserve the fraction value - //there are two readings (y1, y2) and (y3, y4). Hence we have to divide by 20 * 2 = 40 - globalSettings.touchSlopeY = ((y3 - y1) + (y4 - y2))/40; - - //x1, y1 is at 20 pixels - globalSettings.touchOffsetX = x1 + -((20 * globalSettings.touchSlopeX)/10); - globalSettings.touchOffsetY = y1 + -((20 * globalSettings.touchSlopeY)/10); + Point cal_points[sizeof(CROSS_CORNER_POINTS)/sizeof(CROSS_CORNER_POINTS[0])]; + + for(uint8_t i = 0; i < sizeof(CROSS_CORNER_POINTS)/sizeof(CROSS_CORNER_POINTS[0]); ++i){ + drawCross(CROSS_CORNER_POINTS[i].x,CROSS_CORNER_POINTS[i].y,DISPLAY_WHITE); + while(!readTouch(&cal_points[i])){ + delay(100); + } + while(readTouch(&cal_points[i])){ + delay(100); + } + drawCross(CROSS_CORNER_POINTS[i].x,CROSS_CORNER_POINTS[i].y,DISPLAY_BLACK); + delay(1000);//Ensure that nobody is pressing the screen before we do the next point + } + + //We can get nicer scaling if we allow more resolution on the divisor + constexpr int32_t SCALE_SENSITIVITY_MULTIPLIER = 10; + + const int16_t diff_x_top = cal_points[1].x - cal_points[0].x; + const int16_t diff_x_bottom = cal_points[3].x - cal_points[2].x; + constexpr int32_t diff_x_target = CROSS_CORNER_POINTS[1].x - CROSS_CORNER_POINTS[0].x; + + //Average the measured differences + globalSettings.touchSlopeX = SCALE_SENSITIVITY_MULTIPLIER*(diff_x_top + diff_x_bottom) / (2*diff_x_target); + + const int16_t diff_y_left = cal_points[2].y - cal_points[0].y; + const int16_t diff_y_right = cal_points[3].y - cal_points[1].y; + constexpr int32_t diff_y_target = CROSS_CORNER_POINTS[2].y - CROSS_CORNER_POINTS[0].y; + + //Average the measured differences + globalSettings.touchSlopeY = SCALE_SENSITIVITY_MULTIPLIER*(diff_y_left + diff_y_right) / (2*diff_y_target); + + globalSettings.touchOffsetX = cal_points[0].x - ((CROSS_CORNER_OFFSET * globalSettings.touchSlopeX)/SCALE_SENSITIVITY_MULTIPLIER); + globalSettings.touchOffsetY = cal_points[0].y - ((CROSS_CORNER_OFFSET * globalSettings.touchSlopeY)/SCALE_SENSITIVITY_MULTIPLIER); /* Serial.print(x1);Serial.print(':');Serial.println(y1); From b909f4d652675b776a58bb3cc80c4ab45996278e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 17:10:27 -0800 Subject: [PATCH 217/324] Remove active delay --- keyer.cpp | 3 +-- morse.cpp | 2 +- ubitx.h | 1 - ubitxv6.ino | 13 +------------ 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index 121477f..c802c2f 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -205,8 +205,7 @@ void cwKeyer(void){ } cwKeydown(); - while ( update_PaddleLatch(0) == DIT_L ) - active_delay(1); + while ( update_PaddleLatch(0) == DIT_L ); cwKeyUp(); } diff --git a/morse.cpp b/morse.cpp index 0a9596d..dde51c9 100644 --- a/morse.cpp +++ b/morse.cpp @@ -66,7 +66,7 @@ void morseLetter(char c, uint16_t dit_duration_ms){ //handle space character as three dashes if (c == ' '){ - active_delay(7 * dit_duration_ms); + delay(7 * dit_duration_ms); //Serial.print(' '); return; } diff --git a/ubitx.h b/ubitx.h index 94e911b..37b2c51 100644 --- a/ubitx.h +++ b/ubitx.h @@ -95,7 +95,6 @@ extern char c[30], b[128]; static const uint32_t THRESHOLD_USB_LSB = 10000000L; /* these are functions implemented in the main file named as ubitx_xxx.ino */ -void active_delay(int delay_by); void saveVFOs(); void setFrequency(const unsigned long freq, const bool transmit = false); void startTx(TuningMode_e tx_mode); diff --git a/ubitxv6.ino b/ubitxv6.ino index 6c6c5b7..30330d9 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -64,17 +64,6 @@ unsigned char doingCAT = 0; * you start hacking around */ -/** - * Our own delay. During any delay, the raduino should still be processing a few times. - */ - -void active_delay(int delay_by){ - unsigned long timeStart = millis(); - while (millis() - timeStart <= (unsigned long)delay_by) { - checkCAT(); - } -} - void saveVFOs() { SaveSettingsToEeprom(); @@ -299,7 +288,7 @@ void checkPTT(){ if(digitalRead(PTT) == 0 && !globalSettings.txActive){ startTx(TuningMode_e::TUNE_SSB); - active_delay(50); //debounce the PTT + delay(50); //debounce the PTT } if (digitalRead(PTT) == 1 && globalSettings.txActive) From 3438bef4fbf215452fe2f124b692a6b7143c9945 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 18:42:06 -0800 Subject: [PATCH 218/324] Clean up types a bit --- touch.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/touch.cpp b/touch.cpp index 181bb4e..98b89bd 100644 --- a/touch.cpp +++ b/touch.cpp @@ -4,13 +4,12 @@ #include "ubitx.h"//pin assignments -#define Z_THRESHOLD 400 -#define Z_THRESHOLD_INT 75 -#define MSEC_THRESHOLD 3 +constexpr int16_t Z_THRESHOLD = 400; +constexpr uint8_t MSEC_THRESHOLD = 3; -static uint32_t msraw=0x80000000; -static int16_t xraw=0, yraw=0, zraw=0; -static uint8_t rotation = 1; +uint32_t msraw=0x80000000; +int16_t xraw=0, yraw=0, zraw=0; +constexpr uint8_t rotation = 1; int16_t touch_besttwoavg( int16_t x , int16_t y , int16_t z ) { int16_t da, db, dc; From b116be8644bb28372ce976d1125751eca0ced2d2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 18:43:10 -0800 Subject: [PATCH 219/324] Remove redundant check --- touch.cpp | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/touch.cpp b/touch.cpp index 98b89bd..80569be 100644 --- a/touch.cpp +++ b/touch.cpp @@ -64,25 +64,23 @@ void touch_update(){ //Serial.printf(" %d,%d", x, y); //Serial.println(); - if (z >= Z_THRESHOLD) { - msraw = now; // good read completed, set wait - switch (rotation) { - case 0: - xraw = 4095 - y; - yraw = x; - break; - case 1: - xraw = x; - yraw = y; - break; - case 2: - xraw = y; - yraw = 4095 - x; - break; - default: // 3 - xraw = 4095 - x; - yraw = 4095 - y; - } + msraw = now; // good read completed, set wait + switch (rotation) { + case 0: + xraw = 4095 - y; + yraw = x; + break; + case 1: + xraw = x; + yraw = y; + break; + case 2: + xraw = y; + yraw = 4095 - x; + break; + default: // 3 + xraw = 4095 - x; + yraw = 4095 - y; } } From b2e17548c2bdb9f78783dd4ecf8fc60471d5c325 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 15 Feb 2020 18:44:29 -0800 Subject: [PATCH 220/324] Remove more redundant checks --- touch.cpp | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/touch.cpp b/touch.cpp index 80569be..a880d5a 100644 --- a/touch.cpp +++ b/touch.cpp @@ -38,19 +38,6 @@ void touch_update(){ int z = z1 + 4095; int16_t z2 = SPI.transfer16(0x91 /* X */) >> 3; z -= z2; - if (z >= Z_THRESHOLD) { - SPI.transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy - data[0] = SPI.transfer16(0xD1 /* Y */) >> 3; - data[1] = SPI.transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements - data[2] = SPI.transfer16(0xD1 /* Y */) >> 3; - data[3] = SPI.transfer16(0x91 /* X */) >> 3; - } - else data[0] = data[1] = data[2] = data[3] = 0; // Compiler warns these values may be used unset on early exit. - data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down - data[5] = SPI.transfer16(0) >> 3; - digitalWrite(CS_PIN, HIGH); - SPI.setClockDivider(SPI_CLOCK_DIV2);//Return to full speed for TFT - if (z < 0) z = 0; if (z < Z_THRESHOLD) { // if ( !touched ) { // Serial.println(); @@ -58,6 +45,16 @@ void touch_update(){ return; } zraw = z; + + SPI.transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy + data[0] = SPI.transfer16(0xD1 /* Y */) >> 3; + data[1] = SPI.transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements + data[2] = SPI.transfer16(0xD1 /* Y */) >> 3; + data[3] = SPI.transfer16(0x91 /* X */) >> 3; + data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down + data[5] = SPI.transfer16(0) >> 3; + digitalWrite(CS_PIN, HIGH); + SPI.setClockDivider(SPI_CLOCK_DIV2);//Return to full speed for TFT int16_t x = touch_besttwoavg( data[0], data[2], data[4] ); int16_t y = touch_besttwoavg( data[1], data[3], data[5] ); From 1e66731649e08d214d9ea586071680186f21e20c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 12 Apr 2020 17:45:06 -0700 Subject: [PATCH 221/324] Remove unnecessary file --- ubitx_ui.cpp | 876 --------------------------------------------------- 1 file changed, 876 deletions(-) delete mode 100644 ubitx_ui.cpp diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp deleted file mode 100644 index b60a0d2..0000000 --- a/ubitx_ui.cpp +++ /dev/null @@ -1,876 +0,0 @@ -#include -#include "button.h" -#include "color_theme.h" -#include "morse.h" -#include "nano_gui.h" -#include "settings.h" -#include "setup.h" -#include "touch.h" -#include "ubitx.h" -#include "version.h" - -static const unsigned int LAYOUT_VFO_LABEL_X = 0; -static const unsigned int LAYOUT_VFO_LABEL_Y = 10; -static const unsigned int LAYOUT_VFO_LABEL_WIDTH = 159; -static const unsigned int LAYOUT_VFO_LABEL_HEIGHT = 36; -static const unsigned int LAYOUT_VFO_LABEL_PITCH_X = 160; - -static const unsigned int LAYOUT_MODE_TEXT_X = 0; -static const unsigned int LAYOUT_MODE_TEXT_Y = LAYOUT_VFO_LABEL_Y + LAYOUT_VFO_LABEL_HEIGHT + 1; -static const unsigned int LAYOUT_MODE_TEXT_WIDTH = 320; -static const unsigned int LAYOUT_MODE_TEXT_HEIGHT = 36; - -static const unsigned int LAYOUT_BUTTON_X = 2; -static const unsigned int LAYOUT_BUTTON_Y = LAYOUT_MODE_TEXT_Y + LAYOUT_MODE_TEXT_HEIGHT + 1; -static const unsigned int LAYOUT_BUTTON_WIDTH = 60; -static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; -static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; -static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; - -static const unsigned int LAYOUT_CW_TEXT_X = 0; -static const unsigned int LAYOUT_CW_TEXT_Y = LAYOUT_BUTTON_Y + 3*LAYOUT_BUTTON_PITCH_Y + 1; -static const unsigned int LAYOUT_CW_TEXT_WIDTH = 220; -static const unsigned int LAYOUT_CW_TEXT_HEIGHT = 36; - -static const unsigned int LAYOUT_VERSION_TEXT_X = LAYOUT_CW_TEXT_X + LAYOUT_CW_TEXT_WIDTH + 1; -static const unsigned int LAYOUT_VERSION_TEXT_Y = LAYOUT_CW_TEXT_Y; -static const unsigned int LAYOUT_VERSION_TEXT_WIDTH = 320 - LAYOUT_CW_TEXT_WIDTH - 1; -static const unsigned int LAYOUT_VERSION_TEXT_HEIGHT = LAYOUT_CW_TEXT_HEIGHT; - -static const unsigned int LAYOUT_TX_X = 280; -static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; -static const unsigned int LAYOUT_TX_WIDTH = 40; -static const unsigned int LAYOUT_TX_HEIGHT = 36; - -enum btn_set_e { - BUTTON_VFOA, - BUTTON_VFOB, - BUTTON_RIT, - BUTTON_USB, - BUTTON_LSB, - BUTTON_CW, - BUTTON_SPL, - BUTTON_80, - BUTTON_40, - BUTTON_30, - BUTTON_20, - BUTTON_17, - BUTTON_15, - BUTTON_10, - BUTTON_BLANK_1, - BUTTON_MNU, - BUTTON_FRQ, - BUTTON_TOTAL -}; - -void msIgnore(int8_t* val_out); - -Button* btn_set; - -static const unsigned int KEYS_OFFSET = 256;//Unique from buttons -enum keypad_e { - KEYS_1 = KEYS_OFFSET, - KEYS_2, - KEYS_3, - KEYS_BLANK_1, - KEYS_OK, - KEYS_4, - KEYS_5, - KEYS_6, - KEYS_0, - KEYS_BACKSPACE, - KEYS_7, - KEYS_8, - KEYS_9, - KEYS_BLANK_2, - KEYS_CANCEL, - KEYS_TOTAL = KEYS_CANCEL - KEYS_OFFSET + 1 -}; -constexpr Button keypad[KEYS_TOTAL] PROGMEM = { - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_1, "1", '1', msIgnore}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_2, "2", '2', msIgnore}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_3, "3", '3', msIgnore}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_1, "", '\0', msIgnore}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_OK, "OK", 'K', msIgnore}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_4, "4", '4', msIgnore}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_5, "5", '5', msIgnore}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_6, "6", '6', msIgnore}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_0, "0", '0', msIgnore}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BACKSPACE, "<-", 'B', msIgnore}, - - {LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_7, "7", '7', msIgnore}, - {LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_8, "8", '8', msIgnore}, - {LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_9, "9", '9', msIgnore}, - {LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_BLANK_2, "", '\0', msIgnore}, - {LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, LAYOUT_BUTTON_WIDTH, LAYOUT_BUTTON_HEIGHT, KEYS_CANCEL, "Can", 'C', msIgnore}, -}; - -bool getButton(btn_set_e index, Button* button){ - if(BUTTON_TOTAL == index){ - return false; - } - memcpy_P(button, &(btn_set[index]), sizeof(Button)); - return true; -} - -inline void drawCommandbar(char* text){ - displayText(text, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); -} - -/** A generic control to read variable values -*/ -int getValueByKnob(int minimum, int maximum, int step_size, int initial, const __FlashStringHelper* prefix, const __FlashStringHelper* postfix) -{ - int knob = 0; - int knob_value; - - while (btnDown()) - active_delay(100); - - active_delay(200); - knob_value = initial; - - strncpy_P(b,(const char*)prefix,sizeof(b)); - itoa(knob_value, c, 10); - strncat(b, c, sizeof(b) - strlen(b)); - strncat_P(b, (const char*)postfix, sizeof(b) - strlen(b)); - drawCommandbar(b); - - while(!btnDown() && digitalRead(PTT) == HIGH){ - knob = enc_read(); - if (knob != 0){ - if (knob_value > minimum && knob < 0) - knob_value -= step_size; - if (knob_value < maximum && knob > 0) - knob_value += step_size; - - strncpy_P(b,(const char*)prefix,sizeof(b)); - itoa(knob_value, c, 10); - strncat(b, c, sizeof(b) - strlen(b)); - strncat_P(b,(const char*)postfix, sizeof(b) - strlen(b)); - drawCommandbar(b); - } - checkCAT(); - } - b[0] = 0; - drawCommandbar(b); - return knob_value; -} - -void displayVFO(Vfo_e vfo){ - uint16_t displayColor = COLOR_INACTIVE_TEXT; - uint16_t displayBackground = COLOR_INACTIVE_BACKGROUND; - uint16_t displayBorder = COLOR_INACTIVE_BORDER; - Button button; - - if (globalSettings.splitOn){ - if (vfo == globalSettings.activeVfo){ - c[0] = 'R'; - } - else{ - c[0] = 'T'; - } - } - else{ - if(VFO_A == vfo){ - c[0] = 'A'; - } - else if(VFO_B == vfo){ - c[0] = 'B'; - } - else{ - c[0] = '?'; - } - } - c[1] = ':'; - c[2] = ' '; - - - if (VFO_A == vfo){ - getButton(BUTTON_VFOA, &button); - formatFreq(globalSettings.vfoA.frequency, c+3, sizeof(c)-3, 10); - - if (VFO_A == globalSettings.activeVfo){ - displayColor = COLOR_ACTIVE_VFO_TEXT; - displayBackground = COLOR_ACTIVE_VFO_BACKGROUND; - displayBorder = COLOR_ACTIVE_BORDER; - }else{ - displayColor = COLOR_INACTIVE_VFO_TEXT; - displayBackground = COLOR_INACTIVE_VFO_BACKGROUND; - displayBorder = COLOR_INACTIVE_BORDER; - } - } - - if (VFO_B == vfo){ - getButton(BUTTON_VFOB, &button); - formatFreq(globalSettings.vfoB.frequency, c+3, sizeof(c)-3, 10); - - if (VFO_B == globalSettings.activeVfo){ - displayColor = COLOR_ACTIVE_VFO_TEXT; - displayBackground = COLOR_ACTIVE_VFO_BACKGROUND; - displayBorder = COLOR_ACTIVE_BORDER; - } else { - displayColor = COLOR_INACTIVE_VFO_TEXT; - displayBackground = COLOR_INACTIVE_VFO_BACKGROUND; - displayBorder = COLOR_INACTIVE_BORDER; - } - } - - displayText(c, button.x, button.y, button.w, button.h, displayColor, displayBackground, displayBorder); -} - -void btnDrawActive(Button* button){ - displayText(button->text, button->x, button->y, button->w, button->h, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); -} -void btnDrawInactive(Button* button){ - displayText(button->text, button->x, button->y, button->w, button->h, COLOR_INACTIVE_TEXT, COLOR_INACTIVE_BACKGROUND, COLOR_INACTIVE_BORDER); -} - -void btnDraw(struct Button *button){ - switch(button->id){ - case BUTTON_VFOA: - { - displayVFO(VFO_A); - break; - } - case BUTTON_VFOB: - { - displayVFO(VFO_B); - break; - } - case BUTTON_RIT: - { - if(globalSettings.ritOn){ - btnDrawActive(button); - } - else{ - btnDrawInactive(button); - } - break; - } - case BUTTON_USB: - { - if(VFO_MODE_USB == GetActiveVfoMode()){ - btnDrawActive(button); - } - else{ - btnDrawInactive(button); - } - break; - } - case BUTTON_LSB: - { - if(VFO_MODE_LSB == GetActiveVfoMode()){ - btnDrawActive(button); - } - else{ - btnDrawInactive(button); - } - break; - } - case BUTTON_SPL: - { - if(globalSettings.splitOn){ - btnDrawActive(button); - } - else{ - btnDrawInactive(button); - } - break; - } - case BUTTON_CW: - { - if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ - btnDrawActive(button); - } - else{ - btnDrawInactive(button); - } - break; - } - default: - { - btnDrawInactive(button); - break; - } - }//End switch -} - - -void displayRIT(){ - c[0] = 0; - displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); - if(globalSettings.ritOn){ - strncpy_P(c,(const char*)F("TX:"),sizeof(c)); - formatFreq(globalSettings.ritFrequency, c+3, sizeof(c)-strlen(c)); - if (VFO_A == globalSettings.activeVfo) - displayText(c, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - else - displayText(c, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - } -} - -void fastTune(){ - //if the btn is down, wait until it is up - while(btnDown()) - active_delay(50); - active_delay(50); - - strncpy_P(c,(const char*)F("Fast tune"),sizeof(c)); - displayText(c, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - while(true){ - checkCAT(); - - //exit after debouncing the btnDown - if (btnDown()){ - displayFillrect(LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); - - //wait until the button is realsed and then return - while(btnDown()) - active_delay(50); - active_delay(50); - return; - } - - int encoder = enc_read(); - if (encoder != 0){ - uint32_t freq = GetActiveVfoFreq(); - if (encoder > 0 && freq < 30000000l){ - freq += 50000l; - } - else if (encoder < 0 && freq > 600000l){ - freq -= 50000l; - } - setFrequency(freq); - displayVFO(globalSettings.activeVfo); - } - }// end of the event loop -} - -void enterFreq(){ - //force the display to refresh everything - //display all the buttons - - Point ts_point; - - for (int i = 0; i < KEYS_TOTAL; i++){ - Button button; - memcpy_P(&button, &(keypad[i]), sizeof(Button)); - btnDraw(&button); - } - - while(btnDown()) - active_delay(50); - active_delay(50); - - int cursor_pos = 0; - memset(c, 0, sizeof(c)); - - bool exit = false; - while(!exit){ - - checkCAT(); - if(btnDown()){ - while(btnDown()) - active_delay(50); - active_delay(50); - break; - } - if(!readTouch(&ts_point)) - continue; - - scaleTouch(&ts_point); - - for (int i = 0; i < KEYS_TOTAL; i++){ - Button button; - memcpy_P(&button, &(keypad[i]), sizeof(Button)); - - int x2 = button.x + button.w; - int y2 = button.y + button.h; - - if(button.x < ts_point.x && ts_point.x < x2 && - button.y < ts_point.y && ts_point.y < y2){ - //Serial.print(F("Entered key: ")); - //Serial.println(button.text); - switch(button.id){ - case KEYS_OK: - { - uint32_t new_freq = atol(c); - if((LOWEST_FREQ/1000 <= new_freq) && (new_freq <= HIGHEST_FREQ/1000)){ - new_freq *= 1000L; - - uint32_t prev_freq = GetActiveVfoFreq(); - //Transition from below to above the traditional threshold for USB - if(prev_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); - } - - //Transition from aboveo to below the traditional threshold for USB - if(prev_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - } - - if (VFO_A == globalSettings.activeVfo){ - globalSettings.vfoA.frequency = new_freq; - } - else{ - globalSettings.vfoB.frequency = new_freq; - } - - setFrequency(new_freq); - saveVFOs(); - } - exit = true; - break; - } - - case KEYS_BACKSPACE: - { - c[cursor_pos] = 0; - if (cursor_pos > 0){ - cursor_pos--; - } - c[cursor_pos] = 0; - break; - } - case KEYS_CANCEL: - { - exit = true; - break; - } - case KEYS_0: - case KEYS_1: - case KEYS_2: - case KEYS_3: - case KEYS_4: - case KEYS_5: - case KEYS_6: - case KEYS_7: - case KEYS_8: - case KEYS_9: - { - c[cursor_pos++] = button.text[0]; - c[cursor_pos] = 0; - break; - } - default: - { - //Serial.print(F("Unknown key id: ")); - //Serial.println(button.id); - break; - } - }//switch - }//if button hit test - }// end of the button scanning loop - strncpy(b, c, sizeof(b)); - strncat_P(b,(const char*)F(" KHz"),sizeof(b) - strlen(b)); - displayText(b, LAYOUT_MODE_TEXT_X, LAYOUT_MODE_TEXT_Y, LAYOUT_MODE_TEXT_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); - active_delay(300); - while(readTouch(&ts_point)) - checkCAT(); - } // end of event loop : while(!exit) - - guiUpdate(); - enc_read();//clear out any tuner turning that happened during entry -} - -void drawCWStatus(){ - strncpy_P(b,(const char*)F(" cw: "),sizeof(b)); - int wpm = 1200/globalSettings.cwDitDurationMs; - itoa(wpm,c, 10); - strncat(b, c, sizeof(b) - strlen(b)); - strncat_P(b,(const char*)F("wpm, "), sizeof(b) - strlen(b)); - itoa(globalSettings.cwSideToneFreq, c, 10); - strncat(b, c, sizeof(b) - strlen(b)); - strncat_P(b,(const char*)F("hz"), sizeof(b) - strlen(b)); - displayText(b, LAYOUT_CW_TEXT_X, LAYOUT_CW_TEXT_Y, LAYOUT_CW_TEXT_WIDTH, LAYOUT_CW_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND, TextJustification_e::Left); -} - -void drawVersion() -{ - strncpy_P(b,VERSION_STRING,sizeof(b)); - displayText(b, LAYOUT_VERSION_TEXT_X, LAYOUT_VERSION_TEXT_Y, LAYOUT_VERSION_TEXT_WIDTH, LAYOUT_VERSION_TEXT_HEIGHT, COLOR_VERSION_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND, TextJustification_e::Right); -} - -void drawTx(){ - if (globalSettings.txActive){ - strncpy_P(b,(const char*)F("TX"), sizeof(b)); - displayText(b, LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_ACTIVE_TEXT, COLOR_ACTIVE_BACKGROUND, COLOR_BACKGROUND); - } - else{ - displayFillrect(LAYOUT_TX_X, LAYOUT_TX_Y, LAYOUT_TX_WIDTH, LAYOUT_TX_HEIGHT, COLOR_BACKGROUND); - } -} -void drawStatusbar(){ - drawCWStatus(); - drawVersion(); -} - -void guiUpdate(){ - -/* - if (doingCAT) - return; -*/ - // use the current frequency as the VFO frequency for the active VFO - displayClear(COLOR_BACKGROUND); - - displayVFO(VFO_A); - displayVFO(VFO_B); - - checkCAT(); - displayRIT(); - checkCAT(); - - //force the display to refresh everything - //display all the buttons - for (int i = 0; i < BUTTON_TOTAL; i++){ - Button button; - memcpy_P(&button, &(btn_set[i]), sizeof(Button)); - btnDraw(&button); - checkCAT(); - } - drawStatusbar(); - checkCAT(); -} - - - -// this builds up the top line of the display with frequency and mode -void updateDisplay() { - displayVFO(globalSettings.activeVfo); -} - -void ritToggle(struct Button *button){ - if(!globalSettings.ritOn){ - ritEnable(GetActiveVfoFreq()); - } - else{ - ritDisable(); - } - btnDraw(button); - displayRIT(); -} - -void splitToggle(Button *button){ - - globalSettings.splitOn = !globalSettings.splitOn; - - btnDraw(button); - - //disable rit as well - ritDisable(); - - Button button2; - getButton(BUTTON_RIT, &button2); - btnDraw(&button2); - - displayRIT(); - displayVFO(VFO_A); - displayVFO(VFO_B); -} - -void vfoReset(){ - Button button; - if (VFO_A == globalSettings.activeVfo) - globalSettings.vfoB.frequency = globalSettings.vfoA.frequency; - else - globalSettings.vfoA.frequency = globalSettings.vfoB.frequency; - - if(globalSettings.splitOn){ - getButton(BUTTON_SPL, &button); - splitToggle(&button); - } - - if(globalSettings.ritOn){ - getButton(BUTTON_RIT, &button); - ritToggle(&button); - } - - displayVFO(VFO_A); - displayVFO(VFO_B); - - saveVFOs(); -} - -void cwToggle(struct Button *b){ - if (TuningMode_e::TUNE_SSB == globalSettings.tuningMode){ - globalSettings.tuningMode = TuningMode_e::TUNE_CW; - } - else{ - globalSettings.tuningMode = TuningMode_e::TUNE_SSB; - } - - setFrequency(GetActiveVfoFreq()); - btnDraw(b); -} - -void sidebandToggle(Button* button){ - if(BUTTON_LSB == button->id){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - } - else{ - SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); - } - setFrequency(GetActiveVfoFreq()); - - struct Button button2; - getButton(BUTTON_USB, &button2); - btnDraw(&button2); - getButton(BUTTON_LSB, &button2); - btnDraw(&button2); - - saveVFOs(); -} - - -void redrawVFOs(){ - struct Button button; - ritDisable(); - getButton(BUTTON_RIT, &button); - btnDraw(&button); - displayRIT(); - displayVFO(VFO_A); - displayVFO(VFO_B); - - //draw the lsb/usb buttons, the sidebands might have changed - getButton(BUTTON_LSB, &button); - btnDraw(&button); - getButton(BUTTON_USB, &button); - btnDraw(&button); -} - - -void switchBand(uint32_t bandfreq){ - - //Serial.println(frequency); - //Serial.println(bandfreq); - uint32_t offset; - uint32_t freq = GetActiveVfoFreq(); - if (3500000L <= freq && freq <= 4000000L) - offset = freq - 3500000l; - else if (24800000L <= freq && freq <= 25000000L) - offset = freq - 24800000L; - else - offset = freq % 1000000L; - - //Serial.println(offset); - - setFrequency(bandfreq + offset); - - if(bandfreq >= THRESHOLD_USB_LSB){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); - } - else{ - SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - } - - updateDisplay(); - saveVFOs(); -} - -void doCommand(Button* button){ - //Serial.print(F("Doing command: ")); - //Serial.print(button->text); - //Serial.print(F(", Hitbox: ")); - //Serial.print(button->x);Serial.print(F(",")); - //Serial.print(button->y);Serial.print(F(";")); - //Serial.print(button->x + button->w);Serial.print(F(",")); - //Serial.println(button->y + button->h); - switch(button->id){ - case BUTTON_RIT: - { - ritToggle(button); - break; - } - case BUTTON_LSB: - case BUTTON_USB: - { - sidebandToggle(button); - break; - } - case BUTTON_CW: - { - cwToggle(button); - break; - } - case BUTTON_SPL: - { - splitToggle(button); - break; - } - case BUTTON_VFOA: - { - switchVFO(VFO_A); - uint32_t freq = globalSettings.vfoA.frequency; - ltoa(freq,b,10); - morseText(b); - break; - } - case BUTTON_VFOB: - { - switchVFO(VFO_B); - uint32_t freq = globalSettings.vfoB.frequency; - ltoa(freq,b,10); - morseText(b); - break; - } - case BUTTON_80: - { - switchBand(3500000L); - break; - } - case BUTTON_40: - { - switchBand(7000000L); - break; - } - case BUTTON_30: - { - switchBand(10000000L); - break; - } - case BUTTON_20: - { - switchBand(14000000L); - break; - } - case BUTTON_17: - { - switchBand(18000000L); - break; - } - case BUTTON_15: - { - switchBand(21000000L); - break; - } - case BUTTON_10: - { - switchBand(28000000L); - break; - } - case BUTTON_FRQ: - { - enterFreq(); - break; - } - case BUTTON_MNU: - { - doSetup2(); - break; - } - default: - { - //Serial.print(F("Unknown command: ")); - //Serial.println(button.id); - break; - } - } -} - -//returns true if the button is pressed -int btnDown(){ - if (digitalRead(FBUTTON) == HIGH) - return 0; - else - return 1; -} - - -void drawFocus(int ibtn, int color){ - Button button; - - memcpy_P(&button, &(btn_set[ibtn]), sizeof(Button)); - displayRect(button.x, button.y, button.w, button.h, color); -} - -void doCommands(){ - int select = 0; - int prev_button = 0; - - //wait for the button to be raised up - while(btnDown()) - active_delay(50); - active_delay(50); //debounce - - Button button; - memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); - morseLetter(button.morse); - int8_t morse_status = 0; - button.morse_status(&morse_status); - if(morse_status){ - if(morse_status > 0){ - morseBool(true); - } - else{ - morseBool(false); - } - } - - while (true){ - //check if the knob's button was pressed - if (btnDown()){ - doCommand(&button); - - //unfocus the buttons - drawFocus(select, COLOR_INACTIVE_BORDER); - if (VFO_A == globalSettings.activeVfo) - drawFocus(BUTTON_VFOA, COLOR_ACTIVE_BORDER); - else - drawFocus(BUTTON_VFOB, COLOR_ACTIVE_BORDER); - - //wait for the button to be up and debounce - while(btnDown()) - active_delay(100); - active_delay(500); - return; - } - - int knob = enc_read(); - - if (knob == 0){ - active_delay(50); - continue; - } - - if (knob > 0){ - if (select + knob < BUTTON_TOTAL * 10) - select += knob; - } - if (knob < 0 && select + knob >= 0) - select += knob; //caught ya, i is already -ve here, so you add it - - if (prev_button == select / 10) - continue; - - //we are on a new button - drawFocus(prev_button, COLOR_INACTIVE_BORDER); - drawFocus(select/10, COLOR_ACTIVE_BORDER); - memcpy_P(&button, &(btn_set[select/10]), sizeof(Button)); - morseLetter(button.morse); - morse_status = 0; - button.morse_status(&morse_status); - Serial.println((uint16_t)button.morse_status); - Serial.println(morse_status); - if(morse_status){ - if(morse_status > 0){ - morseBool(true); - } - else{ - morseBool(false); - } - } - enc_read();//Clear any rotation that was done while the letter was playing - prev_button = select/10; - } -// guiUpdate(); - - //debounce the button - while(btnDown()) - active_delay(50); - active_delay(50); - - checkCAT(); -} From f113551aa6f99b4ab404585ecdf1e0839a59a7ac Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:06:19 -0700 Subject: [PATCH 222/324] Use beginTransaction for spi, since it's surprisingly less additional memory than the setClockDivider call. Also, add SPI cleanup to early return case --- ubitx.h => pin_definitions.h | 0 touch.cpp | 19 ++++++++++++------- 2 files changed, 12 insertions(+), 7 deletions(-) rename ubitx.h => pin_definitions.h (100%) diff --git a/ubitx.h b/pin_definitions.h similarity index 100% rename from ubitx.h rename to pin_definitions.h diff --git a/touch.cpp b/touch.cpp index a880d5a..74756cd 100644 --- a/touch.cpp +++ b/touch.cpp @@ -2,7 +2,8 @@ #include -#include "ubitx.h"//pin assignments +#include "pin_definitions.h" +#include "settings.h" constexpr int16_t Z_THRESHOLD = 400; constexpr uint8_t MSEC_THRESHOLD = 3; @@ -11,6 +12,8 @@ uint32_t msraw=0x80000000; int16_t xraw=0, yraw=0, zraw=0; constexpr uint8_t rotation = 1; +SPISettings spiSettingsTouch(2000000,MSBFIRST,SPI_MODE0); + int16_t touch_besttwoavg( int16_t x , int16_t y , int16_t z ) { int16_t da, db, dc; int16_t reta = 0; @@ -31,8 +34,8 @@ void touch_update(){ uint32_t now = millis(); if (now - msraw < MSEC_THRESHOLD) return; - SPI.setClockDivider(SPI_CLOCK_DIV8);//2MHz - digitalWrite(CS_PIN, LOW); + SPI.beginTransaction(spiSettingsTouch); + digitalWrite(PIN_TOUCH_CS, LOW); SPI.transfer(0xB1 /* Z1 */); int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3; int z = z1 + 4095; @@ -42,6 +45,8 @@ void touch_update(){ if (z < Z_THRESHOLD) { // if ( !touched ) { // Serial.println(); zraw = 0; + digitalWrite(PIN_TOUCH_CS, HIGH); + SPI.endTransaction(); return; } zraw = z; @@ -53,8 +58,8 @@ void touch_update(){ data[3] = SPI.transfer16(0x91 /* X */) >> 3; data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down data[5] = SPI.transfer16(0) >> 3; - digitalWrite(CS_PIN, HIGH); - SPI.setClockDivider(SPI_CLOCK_DIV2);//Return to full speed for TFT + digitalWrite(PIN_TOUCH_CS, HIGH); + SPI.endTransaction(); int16_t x = touch_besttwoavg( data[0], data[2], data[4] ); int16_t y = touch_besttwoavg( data[1], data[3], data[5] ); @@ -82,8 +87,8 @@ void touch_update(){ } void initTouch(){ - pinMode(CS_PIN, OUTPUT); - digitalWrite(CS_PIN, HIGH); + pinMode(PIN_TOUCH_CS, OUTPUT); + digitalWrite(PIN_TOUCH_CS, HIGH); } bool readTouch(Point *const touch_point_out){ From f090a75221391ec10df5c7b32ca0feeef0827ac8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:08:51 -0700 Subject: [PATCH 223/324] Add dedicated scratch-space header so that we can track where these are still used --- scratch_space.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 scratch_space.h diff --git a/scratch_space.h b/scratch_space.h new file mode 100644 index 0000000..50b1f5a --- /dev/null +++ b/scratch_space.h @@ -0,0 +1,13 @@ +/** + * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. + * We have to be very careful with variables that are declared inside the functions as they are + * created in a memory region called the stack. The stack has just a few bytes of space on the Arduino + * if you declare large strings inside functions, they can easily exceed the capacity of the stack + * and mess up your programs. + * We circumvent this by declaring a few global buffers as kitchen counters where we can + * slice and dice our strings. These strings are mostly used to control the display or handle + * the input and output from the USB port. We must keep a count of the bytes used while reading + * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. + */ + +extern char c[30], b[128]; \ No newline at end of file From b87ef7575a8c93dee29944bb93c690530709a550 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:09:21 -0700 Subject: [PATCH 224/324] Move tuning functions to a single file --- tuner.cpp | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tuner.h | 22 ++++++ 2 files changed, 223 insertions(+) create mode 100644 tuner.cpp create mode 100644 tuner.h diff --git a/tuner.cpp b/tuner.cpp new file mode 100644 index 0000000..0bebb98 --- /dev/null +++ b/tuner.cpp @@ -0,0 +1,201 @@ +#include "tuner.h" + +#include + +#include "nano_gui.h" +#include "pin_definitions.h" + +/** + * Below are the basic functions that control the uBitx. Understanding the functions before + * you start hacking around + */ + +void saveVFOs() +{ + SaveSettingsToEeprom(); +} + + +void switchVFO(Vfo_e new_vfo){ + ritDisable();//If we are in RIT mode, we need to disable it before setting the active VFO so that the correct VFO gets it's frequency restored + + globalSettings.activeVfo = new_vfo; + setFrequency(GetActiveVfoFreq()); + redrawVFOs(); + saveVFOs(); +} + +/** + * Select the properly tx harmonic filters + * The four harmonic filters use only three relays + * the four LPFs cover 30-21 Mhz, 18 - 14 Mhz, 7-10 MHz and 3.5 to 5 Mhz + * Briefly, it works like this, + * - When KT1 is OFF, the 'off' position routes the PA output through the 30 MHz LPF + * - When KT1 is ON, it routes the PA output to KT2. Which is why you will see that + * the KT1 is on for the three other cases. + * - When the KT1 is ON and KT2 is off, the off position of KT2 routes the PA output + * to 18 MHz LPF (That also works for 14 Mhz) + * - When KT1 is On, KT2 is On, it routes the PA output to KT3 + * - KT3, when switched on selects the 7-10 Mhz filter + * - KT3 when switched off selects the 3.5-5 Mhz filter + * See the circuit to understand this + */ + +void setTXFilters(unsigned long freq){ + + if (freq > 21000000L){ // the default filter is with 35 MHz cut-off + digitalWrite(PIN_TX_LPF_A, 0); + digitalWrite(PIN_TX_LPF_B, 0); + digitalWrite(PIN_TX_LPF_C, 0); + } + else if (freq >= 14000000L){ //thrown the KT1 relay on, the 30 MHz LPF is bypassed and the 14-18 MHz LPF is allowd to go through + digitalWrite(PIN_TX_LPF_A, 1); + digitalWrite(PIN_TX_LPF_B, 0); + digitalWrite(PIN_TX_LPF_C, 0); + } + else if (freq > 7000000L){ + digitalWrite(PIN_TX_LPF_A, 0); + digitalWrite(PIN_TX_LPF_B, 1); + digitalWrite(PIN_TX_LPF_C, 0); + } + else { + digitalWrite(PIN_TX_LPF_A, 0); + digitalWrite(PIN_TX_LPF_B, 0); + digitalWrite(PIN_TX_LPF_C, 1); + } +} + +/** + * This is the most frequently called function that configures the + * radio to a particular frequeny, sideband and sets up the transmit filters + * + * The transmit filter relays are powered up only during the tx so they dont + * draw any current during rx. + * + * The carrier oscillator of the detector/modulator is permanently fixed at + * uppper sideband. The sideband selection is done by placing the second oscillator + * either 12 Mhz below or above the 45 Mhz signal thereby inverting the sidebands + * through mixing of the second local oscillator. + */ + +void setFrequency(const unsigned long freq, + const bool transmit){ + static const unsigned long FIRST_IF = 45005000UL; + + setTXFilters(freq); + + //Nominal values for the oscillators + uint32_t local_osc_freq = FIRST_IF + freq; + uint32_t ssb_osc_freq = FIRST_IF;//will be changed depending on sideband + uint32_t bfo_osc_freq = globalSettings.usbCarrierFreq; + + if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ + if(transmit){ + //We don't do any mixing or converting when transmitting + local_osc_freq = freq; + ssb_osc_freq = 0; + bfo_osc_freq = 0; + } + else{ + //We offset when receiving CW so that it's audible + if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + local_osc_freq -= globalSettings.cwSideToneFreq; + ssb_osc_freq += globalSettings.usbCarrierFreq; + } + else{ + local_osc_freq += globalSettings.cwSideToneFreq; + ssb_osc_freq -= globalSettings.usbCarrierFreq; + } + } + } + else{//SSB mode + if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + ssb_osc_freq += globalSettings.usbCarrierFreq; + } + else{ + ssb_osc_freq -= globalSettings.usbCarrierFreq; + } + } + + si5351bx_setfreq(2, local_osc_freq); + si5351bx_setfreq(1, ssb_osc_freq); + si5351bx_setfreq(0, bfo_osc_freq); + + SetActiveVfoFreq(freq); +} + +/** + * startTx is called by the PTT, cw keyer and CAT protocol to + * put the uBitx in tx mode. It takes care of rit settings, sideband settings + * Note: In cw mode, doesnt key the radio, only puts it in tx mode + * CW offest is calculated as lower than the operating frequency when in LSB mode, and vice versa in USB mode + */ + +void startTx(TuningMode_e tx_mode){ + globalSettings.tuningMode = tx_mode; + + if (globalSettings.ritOn){ + //save the current as the rx frequency + uint32_t rit_tx_freq = globalSettings.ritFrequency; + globalSettings.ritFrequency = GetActiveVfoFreq(); + setFrequency(rit_tx_freq,true); + } + else{ + if(globalSettings.splitOn){ + if(Vfo_e::VFO_B == globalSettings.activeVfo){ + globalSettings.activeVfo = Vfo_e::VFO_A; + } + else{ + globalSettings.activeVfo = Vfo_e::VFO_B; + } + } + setFrequency(GetActiveVfoFreq(),true); + } + + digitalWrite(PIN_TX_RXn, 1);//turn on the tx + globalSettings.txActive = true; + drawTx(); +} + +void stopTx(){ + digitalWrite(PIN_TX_RXn, 0);//turn off the tx + globalSettings.txActive = false; + + if(globalSettings.ritOn){ + uint32_t rit_rx_freq = globalSettings.ritFrequency; + globalSettings.ritFrequency = GetActiveVfoFreq(); + setFrequency(rit_rx_freq); + } + else{ + if(globalSettings.splitOn){ + if(Vfo_e::VFO_B == globalSettings.activeVfo){ + globalSettings.activeVfo = Vfo_e::VFO_A; + } + else{ + globalSettings.activeVfo = Vfo_e::VFO_B; + } + } + setFrequency(GetActiveVfoFreq()); + } + drawTx(); +} + +/** + * ritEnable is called with a frequency parameter that determines + * what the tx frequency will be + */ +void ritEnable(unsigned long freq){ + globalSettings.ritOn = true; + //save the non-rit frequency back into the VFO memory + //as RIT is a temporary shift, this is not saved to EEPROM + globalSettings.ritFrequency = freq; +} + +// this is called by the RIT menu routine +void ritDisable(){ + if(globalSettings.ritOn){ + globalSettings.ritOn = false; + setFrequency(globalSettings.ritFrequency); + updateDisplay(); + } +} \ No newline at end of file diff --git a/tuner.h b/tuner.h new file mode 100644 index 0000000..dc4cf27 --- /dev/null +++ b/tuner.h @@ -0,0 +1,22 @@ +#pragma once + +#include "settings.h" + +/* these are functions implemented in the main file named as ubitx_xxx.ino */ +void saveVFOs(); +void setFrequency(const unsigned long freq, const bool transmit = false); +void startTx(TuningMode_e tx_mode); +void stopTx(); +void ritEnable(unsigned long f); +void ritDisable(); +void checkCAT(); +void cwKeyer(void); +void switchVFO(Vfo_e vfoSelect); + +/* these are functiosn implemented in ubitx_si5351.cpp */ +void si5351bx_setfreq(uint8_t clknum, uint32_t fout); +void initOscillators(); +void si5351_set_calibration(int32_t cal); //calibration is a small value that is nudged to make up for the inaccuracies of the reference 25 MHz crystal frequency + +// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz +static const uint32_t THRESHOLD_USB_LSB = 10000000L; From 7d84ab744bfbb94e5b0338afff8bf68ae16bcc84 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:09:55 -0700 Subject: [PATCH 225/324] Remove include --- ubitx_si5351.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/ubitx_si5351.cpp b/ubitx_si5351.cpp index 27f1b7a..ec4879b 100644 --- a/ubitx_si5351.cpp +++ b/ubitx_si5351.cpp @@ -1,7 +1,6 @@ #include #include #include "settings.h" -#include "ubitx.h" // ************* SI5315 routines - tks Jerry Gaffke, KE7ER *********************** From 0091a1e17ae7c174dd9c655b020eda8b551dd3d6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:10:24 -0700 Subject: [PATCH 226/324] Update includes, and make VFO switch explicit --- ubitx_cat.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 27d9707..a034bc5 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -1,7 +1,8 @@ #include -#include "settings.h" -#include "ubitx.h" #include "nano_gui.h" +#include "scratch_space.h" +#include "settings.h" +#include "tuner.h" /** * The CAT protocol is used by many radios to provide remote control to comptuers through @@ -336,11 +337,12 @@ void processCATCommand2(byte* cmd) { case 0x81: //toggle the VFOs response[0] = 0; - if (VFO_A == globalSettings.activeVfo) - switchVFO(VFO_B); - else - switchVFO(VFO_A); - //menuVfoToggle(1); // '1' forces it to change the VFO + if (Vfo_e::VFO_A == globalSettings.activeVfo){ + globalSettings.activeVfo = Vfo_e::VFO_B; + } + else{ + globalSettings.activeVfo = Vfo_e::VFO_A; + } Serial.write(response,1); updateDisplay(); break; From ff4cc62e70d186126ce4edddfbed504b397dbdc6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:10:48 -0700 Subject: [PATCH 227/324] Update includes and pin names --- setup.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/setup.cpp b/setup.cpp index a43fbe1..679f127 100644 --- a/setup.cpp +++ b/setup.cpp @@ -3,9 +3,11 @@ #include "menu.h" #include "morse.h" #include "nano_gui.h" +#include "pin_definitions.h" +#include "scratch_space.h" #include "setup.h" #include "settings.h" -#include "ubitx.h" +#include "tuner.h" #include "utils.h" /** Menus @@ -269,13 +271,13 @@ void ssCwToneValidate(const long int candidate_value_in, long int* validated_val void ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) { globalSettings.cwSideToneFreq = new_value; - tone(CW_TONE, globalSettings.cwSideToneFreq); + tone(PIN_CW_TONE, globalSettings.cwSideToneFreq); ltoa(globalSettings.cwSideToneFreq,buff_out,10); strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); } void ssCwToneFinalize(const long int final_value) { - noTone(CW_TONE); + noTone(PIN_CW_TONE); globalSettings.cwSideToneFreq = final_value; SaveSettingsToEeprom(); } From f5f914a2a9b429cb2f6ea4e01be9e7baf4d280c5 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:12:02 -0700 Subject: [PATCH 228/324] Update includes --- settings.cpp | 2 +- settings.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/settings.cpp b/settings.cpp index a17ea65..16fd2d1 100644 --- a/settings.cpp +++ b/settings.cpp @@ -2,8 +2,8 @@ #include #include #include //only needed for debugging's Serial.print stuff +#include "nano_gui.h"//redrawVFOs() function #include "settings.h" -#include "ubitx.h"//redrawVFOs() function /** * These are the "magic" indices where these user changable settinngs are stored in the EEPROM diff --git a/settings.h b/settings.h index a87f08f..7c0caf1 100644 --- a/settings.h +++ b/settings.h @@ -12,6 +12,8 @@ #pragma once +#include //uint8_t etc. + /* * Loads default values for all settings */ From 363ea027f92e1430baea5410cc8c15499ff778f4 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:12:51 -0700 Subject: [PATCH 229/324] Update includes and pin names --- nano_gui.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index e3c699d..b46b4cf 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -1,8 +1,9 @@ #include +#include "nano_gui.h" #include "colors.h" +#include "pin_definitions.h" +#include "scratch_space.h" #include "settings.h" -#include "ubitx.h" -#include "nano_gui.h" #include "touch.h" #include @@ -12,8 +13,9 @@ /***************** * Begin TFT functions *****************/ -#define ILI9341_CS_PIN TFT_CS -#define ILI9341_DC_PIN TFT_DC +#define ILI9341_CS_PIN PIN_TFT_CS +#define ILI9341_DC_PIN PIN_TFT_DC +#define ILI9341_SAVE_SPCR (1) //Save state before/after to play nice with the touch screen #include "PDQ_MinLib/PDQ_ILI9341.h" PDQ_ILI9341 tft; @@ -21,12 +23,12 @@ PDQ_ILI9341 tft; void displayInit(void){ //Pulling this low 6 times should exit deep sleep mode - pinMode(TFT_CS,OUTPUT); + pinMode(PIN_TFT_CS,OUTPUT); for(uint8_t i = 0; i < 6; ++i){ - digitalWrite(TFT_CS,HIGH); - digitalWrite(TFT_CS,LOW); + digitalWrite(PIN_TFT_CS,HIGH); + digitalWrite(PIN_TFT_CS,LOW); } - digitalWrite(TFT_CS,HIGH);//Disable writing for now + digitalWrite(PIN_TFT_CS,HIGH);//Disable writing for now tft.begin(); tft.setFont(ubitx_font); From 5217858e23d8ca84f1ebf6ecfa2d32d4d9e74e3f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:13:14 -0700 Subject: [PATCH 230/324] Update includes and pin names --- morse.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/morse.cpp b/morse.cpp index dde51c9..b1d5586 100644 --- a/morse.cpp +++ b/morse.cpp @@ -1,7 +1,8 @@ -#include -#include "ubitx.h" -#include "settings.h" +#include //tone + #include "morse.h" +#include "pin_definitions.h" +#include "settings.h" struct Morse { char letter; @@ -84,7 +85,7 @@ void morseLetter(char c, uint16_t dit_duration_ms){ //now we are at the first zero, skip and carry on mask = mask >> 1; while(mask){ - tone(CW_TONE, globalSettings.cwSideToneFreq,10000); + tone(PIN_CW_TONE, globalSettings.cwSideToneFreq,10000); if (mask & code){ delay(3 * dit_duration_ms); //Serial.print('-'); @@ -94,7 +95,7 @@ void morseLetter(char c, uint16_t dit_duration_ms){ //Serial.print('.'); } //Serial.print('#'); - noTone(CW_TONE); + noTone(PIN_CW_TONE); delay(dit_duration_ms); // space between dots and dashes mask = mask >> 1; } @@ -120,8 +121,8 @@ void morseBool(bool val){ if(!globalSettings.morseMenuOn){ return; } - tone(CW_TONE, globalSettings.cwSideToneFreq + (val ? RELATIVE_OFFSET_HZ : -RELATIVE_OFFSET_HZ)); + tone(PIN_CW_TONE, globalSettings.cwSideToneFreq + (val ? RELATIVE_OFFSET_HZ : -RELATIVE_OFFSET_HZ)); delay(3*globalSettings.cwDitDurationMs); - noTone(CW_TONE); + noTone(PIN_CW_TONE); delay(3*globalSettings.cwDitDurationMs); } From e593e0a06040550db7eec7126b7dcd54ac5ca240 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:13:33 -0700 Subject: [PATCH 231/324] Update includes --- button.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/button.cpp b/button.cpp index 2c742c6..ac221ac 100644 --- a/button.cpp +++ b/button.cpp @@ -4,7 +4,7 @@ #include "color_theme.h" #include "nano_gui.h" -#include "ubitx.h"//b +#include "scratch_space.h" void drawButton(Button* button) { From 6face82c36bb8f0c61cbf7784c9bf4b8d070c5c5 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:13:55 -0700 Subject: [PATCH 232/324] Update includes and pin names --- encoder.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/encoder.cpp b/encoder.cpp index 7eb57d5..55ec6e4 100644 --- a/encoder.cpp +++ b/encoder.cpp @@ -2,7 +2,7 @@ #include #include "encoder.h" -#include "ubitx.h"//Pin definitions +#include "pin_definitions.h" //Normal encoder state uint8_t prev_enc = 0; @@ -16,7 +16,7 @@ static const uint8_t MOMENTUM_MULTIPLIER = 1; uint8_t enc_state (void) { - return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0); + return (digitalRead(PIN_ENC_A)?1:0 + digitalRead(PIN_ENC_B)?2:0); } /* @@ -71,13 +71,13 @@ void enc_setup(void) { enc_count = 0; // This is already done in setup() ? - //pinMode(ENC_A, INPUT); - //pinMode(ENC_B, INPUT); + //pinMode(PIN_ENC_A, INPUT); + //pinMode(PIN_ENC_B, INPUT); prev_enc = enc_state(); // Setup Pin Change Interrupts for the encoder inputs - pci_setup(ENC_A); - pci_setup(ENC_B); + pci_setup(PIN_ENC_A); + pci_setup(PIN_ENC_B); //Set up timer interrupt for momentum TCCR1A = 0;//"normal" mode From 67d34a346107ae513a8cc9c9bc5124e98a14e0a0 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:14:24 -0700 Subject: [PATCH 233/324] Update includes and pin names --- keyer.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index c802c2f..d7d798f 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -1,6 +1,7 @@ #include +#include "pin_definitions.h" #include "settings.h" -#include "ubitx.h" +#include "tuner.h" /** CW Keyer @@ -44,8 +45,8 @@ static const unsigned int cwAdcDashTo = 800; * each time it is called, the cwTimeOut is pushed further into the future */ void cwKeydown(){ - tone(CW_TONE, globalSettings.cwSideToneFreq); - digitalWrite(CW_KEY, 1); + tone(PIN_CW_TONE, globalSettings.cwSideToneFreq); + digitalWrite(PIN_CW_KEY, 1); globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; } @@ -55,8 +56,8 @@ void cwKeydown(){ * Pushes the cwTimeout further into the future */ void cwKeyUp(){ - noTone(CW_TONE); - digitalWrite(CW_KEY, 0); + noTone(PIN_CW_TONE); + digitalWrite(PIN_CW_KEY, 0); globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; } @@ -77,10 +78,10 @@ uint8_t keyerControl = 0; char update_PaddleLatch(bool isUpdateKeyState) { unsigned char tmpKeyerControl = 0; - unsigned int paddle = analogRead(ANALOG_KEYER); + unsigned int paddle = analogRead(PIN_ANALOG_KEYER); //use the PTT as the key for tune up, quick QSOs - if (digitalRead(PTT) == 0) + if (digitalRead(PIN_PTT) == 0) tmpKeyerControl |= DIT_L; else if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo) tmpKeyerControl |= DAH_L; From 4a96027a078dc0338109e6b71ed2df890a5e5360 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:14:42 -0700 Subject: [PATCH 234/324] Update includes --- menu_main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/menu_main.cpp b/menu_main.cpp index fb824ad..0c15cd0 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -9,8 +9,9 @@ #include "menu_utils.h" #include "morse.h" #include "nano_gui.h" +#include "scratch_space.h" #include "settings.h" -#include "ubitx.h"//THRESHOLD_USB_LSB +#include "tuner.h"//THRESHOLD_USB_LSB #include "utils.h" void drawMainMenu(void); From 1622d0ebe7f4e7b4b473f431a55eeabcd863f406 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:15:14 -0700 Subject: [PATCH 235/324] Update includes --- menu_numpad_buttons.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/menu_numpad_buttons.cpp b/menu_numpad_buttons.cpp index a70bf17..252eaa6 100644 --- a/menu_numpad_buttons.cpp +++ b/menu_numpad_buttons.cpp @@ -5,8 +5,9 @@ #include "color_theme.h" #include "nano_gui.h" +#include "scratch_space.h" #include "settings.h" -#include "ubitx.h"//setFrequency, b +#include "tuner.h"//setFrequency #include "utils.h" static const unsigned int LAYOUT_MODE_TEXT_X = 60; From a2eae897336cee5f5a7b0888eff6b0670f4fcc01 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:16:10 -0700 Subject: [PATCH 236/324] Remove code that was moved to tuner, update includes and pin names --- ubitxv6.ino | 342 ++++------------------------------------------------ 1 file changed, 25 insertions(+), 317 deletions(-) diff --git a/ubitxv6.ino b/ubitxv6.ino index 30330d9..075ef9d 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -34,12 +34,13 @@ #include "menu.h" #include "menu_main.h" #include "morse.h" +#include "pin_definitions.h" #include "nano_gui.h" #include "settings.h" #include "setup.h" #include "touch.h" +#include "tuner.h" #include "ui_touch.h" -#include "ubitx.h" /** * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. @@ -58,218 +59,6 @@ char c[30]; //during CAT commands, we will freeeze the display until CAT is disengaged unsigned char doingCAT = 0; - -/** - * Below are the basic functions that control the uBitx. Understanding the functions before - * you start hacking around - */ - -void saveVFOs() -{ - SaveSettingsToEeprom(); -} - -/** - * Select the properly tx harmonic filters - * The four harmonic filters use only three relays - * the four LPFs cover 30-21 Mhz, 18 - 14 Mhz, 7-10 MHz and 3.5 to 5 Mhz - * Briefly, it works like this, - * - When KT1 is OFF, the 'off' position routes the PA output through the 30 MHz LPF - * - When KT1 is ON, it routes the PA output to KT2. Which is why you will see that - * the KT1 is on for the three other cases. - * - When the KT1 is ON and KT2 is off, the off position of KT2 routes the PA output - * to 18 MHz LPF (That also works for 14 Mhz) - * - When KT1 is On, KT2 is On, it routes the PA output to KT3 - * - KT3, when switched on selects the 7-10 Mhz filter - * - KT3 when switched off selects the 3.5-5 Mhz filter - * See the circuit to understand this - */ - -void setTXFilters(unsigned long freq){ - - if (freq > 21000000L){ // the default filter is with 35 MHz cut-off - digitalWrite(TX_LPF_A, 0); - digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 0); - } - else if (freq >= 14000000L){ //thrown the KT1 relay on, the 30 MHz LPF is bypassed and the 14-18 MHz LPF is allowd to go through - digitalWrite(TX_LPF_A, 1); - digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 0); - } - else if (freq > 7000000L){ - digitalWrite(TX_LPF_A, 0); - digitalWrite(TX_LPF_B, 1); - digitalWrite(TX_LPF_C, 0); - } - else { - digitalWrite(TX_LPF_A, 0); - digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 1); - } -} - - -void setTXFilters_v5(unsigned long freq){ - - if (freq > 21000000L){ // the default filter is with 35 MHz cut-off - digitalWrite(TX_LPF_A, 0); - digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 0); - } - else if (freq >= 14000000L){ //thrown the KT1 relay on, the 30 MHz LPF is bypassed and the 14-18 MHz LPF is allowd to go through - digitalWrite(TX_LPF_A, 1); - digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 0); - } - else if (freq > 7000000L){ - digitalWrite(TX_LPF_A, 0); - digitalWrite(TX_LPF_B, 1); - digitalWrite(TX_LPF_C, 0); - } - else { - digitalWrite(TX_LPF_A, 0); - digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 1); - } -} - - -/** - * This is the most frequently called function that configures the - * radio to a particular frequeny, sideband and sets up the transmit filters - * - * The transmit filter relays are powered up only during the tx so they dont - * draw any current during rx. - * - * The carrier oscillator of the detector/modulator is permanently fixed at - * uppper sideband. The sideband selection is done by placing the second oscillator - * either 12 Mhz below or above the 45 Mhz signal thereby inverting the sidebands - * through mixing of the second local oscillator. - */ - -void setFrequency(const unsigned long freq, - const bool transmit){ - static const unsigned long FIRST_IF = 45005000UL; - - setTXFilters(freq); - - //Nominal values for the oscillators - uint32_t local_osc_freq = FIRST_IF + freq; - uint32_t ssb_osc_freq = FIRST_IF;//will be changed depending on sideband - uint32_t bfo_osc_freq = globalSettings.usbCarrierFreq; - - if(TuningMode_e::TUNE_CW == globalSettings.tuningMode){ - if(transmit){ - //We don't do any mixing or converting when transmitting - local_osc_freq = freq; - ssb_osc_freq = 0; - bfo_osc_freq = 0; - } - else{ - //We offset when receiving CW so that it's audible - if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ - local_osc_freq -= globalSettings.cwSideToneFreq; - ssb_osc_freq += globalSettings.usbCarrierFreq; - } - else{ - local_osc_freq += globalSettings.cwSideToneFreq; - ssb_osc_freq -= globalSettings.usbCarrierFreq; - } - } - } - else{//SSB mode - if(VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ - ssb_osc_freq += globalSettings.usbCarrierFreq; - } - else{ - ssb_osc_freq -= globalSettings.usbCarrierFreq; - } - } - - si5351bx_setfreq(2, local_osc_freq); - si5351bx_setfreq(1, ssb_osc_freq); - si5351bx_setfreq(0, bfo_osc_freq); - - SetActiveVfoFreq(freq); -} - -/** - * startTx is called by the PTT, cw keyer and CAT protocol to - * put the uBitx in tx mode. It takes care of rit settings, sideband settings - * Note: In cw mode, doesnt key the radio, only puts it in tx mode - * CW offest is calculated as lower than the operating frequency when in LSB mode, and vice versa in USB mode - */ - -void startTx(TuningMode_e tx_mode){ - globalSettings.tuningMode = tx_mode; - - if (globalSettings.ritOn){ - //save the current as the rx frequency - uint32_t rit_tx_freq = globalSettings.ritFrequency; - globalSettings.ritFrequency = GetActiveVfoFreq(); - setFrequency(rit_tx_freq,true); - } - else{ - if(globalSettings.splitOn){ - if(Vfo_e::VFO_B == globalSettings.activeVfo){ - globalSettings.activeVfo = Vfo_e::VFO_A; - } - else{ - globalSettings.activeVfo = Vfo_e::VFO_B; - } - } - setFrequency(GetActiveVfoFreq(),true); - } - - digitalWrite(TX_RX, 1);//turn on the tx - globalSettings.txActive = true; - drawTx(); -} - -void stopTx(){ - digitalWrite(TX_RX, 0);//turn off the tx - globalSettings.txActive = false; - - if(globalSettings.ritOn){ - uint32_t rit_rx_freq = globalSettings.ritFrequency; - globalSettings.ritFrequency = GetActiveVfoFreq(); - setFrequency(rit_rx_freq); - } - else{ - if(globalSettings.splitOn){ - if(Vfo_e::VFO_B == globalSettings.activeVfo){ - globalSettings.activeVfo = Vfo_e::VFO_A; - } - else{ - globalSettings.activeVfo = Vfo_e::VFO_B; - } - } - setFrequency(GetActiveVfoFreq()); - } - drawTx(); -} - -/** - * ritEnable is called with a frequency parameter that determines - * what the tx frequency will be - */ -void ritEnable(unsigned long freq){ - globalSettings.ritOn = true; - //save the non-rit frequency back into the VFO memory - //as RIT is a temporary shift, this is not saved to EEPROM - globalSettings.ritFrequency = freq; -} - -// this is called by the RIT menu routine -void ritDisable(){ - if(globalSettings.ritOn){ - globalSettings.ritOn = false; - setFrequency(globalSettings.ritFrequency); - updateDisplay(); - } -} - /** * Basic User Interface Routines. These check the front panel for any activity */ @@ -286,12 +75,12 @@ void checkPTT(){ return; } - if(digitalRead(PTT) == 0 && !globalSettings.txActive){ + if(digitalRead(PIN_PTT) == 0 && !globalSettings.txActive){ startTx(TuningMode_e::TUNE_SSB); delay(50); //debounce the PTT } - if (digitalRead(PTT) == 1 && globalSettings.txActive) + if (digitalRead(PIN_PTT) == 1 && globalSettings.txActive) stopTx(); } @@ -319,87 +108,6 @@ ButtonPress_e checkButton(){ } } -void switchVFO(Vfo_e new_vfo){ - ritDisable();//If we are in RIT mode, we need to disable it before setting the active VFO so that the correct VFO gets it's frequency restored - - globalSettings.activeVfo = new_vfo; - setFrequency(GetActiveVfoFreq()); - redrawVFOs(); - saveVFOs(); -} - -/** - * The tuning jumps by 50 Hz on each step when you tune slowly - * As you spin the encoder faster, the jump size also increases - * This way, you can quickly move to another band by just spinning the - * tuning knob - */ - -void doTuning(){ - static unsigned long prev_freq; - static unsigned long nextFrequencyUpdate = 0; - - unsigned long now = millis(); - - if (now >= nextFrequencyUpdate && prev_freq != GetActiveVfoFreq()){ - updateDisplay(); - nextFrequencyUpdate = now + 100; - prev_freq = GetActiveVfoFreq(); - } - - int s = enc_read(); - if (!s) - return; - - //Serial.println(s); - - doingCAT = 0; // go back to manual mode if you were doing CAT - prev_freq = GetActiveVfoFreq(); - uint32_t new_freq = prev_freq; - - if (s > 10 || s < -10){ - new_freq += 200L * s; - } - else if (s > 5 || s < -5){ - new_freq += 100L * s; - } - else{ - new_freq += 50L * s; - } - - //Transition from below to above the traditional threshold for USB - if(prev_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); - } - - //Transition from aboveo to below the traditional threshold for USB - if(prev_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - } - - setFrequency(new_freq); -} - - -/** - * RIT only steps back and forth by 100 hz at a time - */ -void doRIT(){ - int knob = enc_read(); - uint32_t old_freq = GetActiveVfoFreq(); - uint32_t new_freq = old_freq; - - if (knob < 0) - new_freq -= 100l; - else if (knob > 0) - new_freq += 100; - - if (old_freq != new_freq){ - setFrequency(new_freq); - updateDisplay(); - } -} - /** * The settings are read from EEPROM. The first time around, the values may not be * present or out of range, in this case, some intelligent defaults are copied into the @@ -415,33 +123,33 @@ void initPorts(){ analogReference(DEFAULT); //?? - pinMode(ENC_A, INPUT_PULLUP); - pinMode(ENC_B, INPUT_PULLUP); - pinMode(FBUTTON, INPUT_PULLUP); + pinMode(PIN_ENC_A, INPUT_PULLUP); + pinMode(PIN_ENC_B, INPUT_PULLUP); + pinMode(PIN_ENC_PUSH_BUTTON, INPUT_PULLUP); enc_setup(); //configure the function button to use the external pull-up -// pinMode(FBUTTON, INPUT); -// digitalWrite(FBUTTON, HIGH); +// pinMode(PIN_ENC_PUSH_BUTTON, INPUT); +// digitalWrite(PIN_ENC_PUSH_BUTTON, HIGH); - pinMode(PTT, INPUT_PULLUP); -// pinMode(ANALOG_KEYER, INPUT_PULLUP); + pinMode(PIN_PTT, INPUT_PULLUP); +// pinMode(PIN_ANALOG_KEYER, INPUT_PULLUP); - pinMode(CW_TONE, OUTPUT); - digitalWrite(CW_TONE, 0); + pinMode(PIN_CW_TONE, OUTPUT); + digitalWrite(PIN_CW_TONE, 0); - pinMode(TX_RX,OUTPUT); - digitalWrite(TX_RX, 0); - - pinMode(TX_LPF_A, OUTPUT); - pinMode(TX_LPF_B, OUTPUT); - pinMode(TX_LPF_C, OUTPUT); - digitalWrite(TX_LPF_A, 0); - digitalWrite(TX_LPF_B, 0); - digitalWrite(TX_LPF_C, 0); - - pinMode(CW_KEY, OUTPUT); - digitalWrite(CW_KEY, 0); + pinMode(PIN_TX_RXn,OUTPUT); + digitalWrite(PIN_TX_RXn, 0); + + pinMode(PIN_TX_LPF_A, OUTPUT); + pinMode(PIN_TX_LPF_B, OUTPUT); + pinMode(PIN_TX_LPF_C, OUTPUT); + digitalWrite(PIN_TX_LPF_A, 0); + digitalWrite(PIN_TX_LPF_B, 0); + digitalWrite(PIN_TX_LPF_C, 0); + + pinMode(PIN_CW_KEY, OUTPUT); + digitalWrite(PIN_CW_KEY, 0); } void setup() From 17663864117a180b54b9fb465b203bfc49e2b472 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:16:30 -0700 Subject: [PATCH 237/324] Update pin names --- pin_definitions.h | 112 +++++++--------------------------------------- 1 file changed, 17 insertions(+), 95 deletions(-) diff --git a/pin_definitions.h b/pin_definitions.h index 37b2c51..96356d4 100644 --- a/pin_definitions.h +++ b/pin_definitions.h @@ -1,25 +1,23 @@ #pragma once -#include "settings.h" - /* The ubitx is powered by an arduino nano. The pin assignment is as folows * */ -#define ENC_A (A0) // Tuning encoder interface -#define ENC_B (A1) // Tuning encoder interface -#define FBUTTON (A2) // Tuning encoder interface -#define PTT (A3) // Sense it for ssb and as a straight key for cw operation -#define ANALOG_KEYER (A6) // This is used as keyer. The analog port has 4.7K pull up resistor. Details are in the circuit description on www.hfsignals.com -#define ANALOG_SPARE (A7) // Not used yet - -#define TX_RX (7) // Pin from the Nano to the radio to switch to TX (HIGH) and RX(LOW) -#define CW_TONE (6) // Generates a square wave sidetone while sending the CW. -#define TX_LPF_A (5) // The 30 MHz LPF is permanently connected in the output of the PA... -#define TX_LPF_B (4) // ...Alternatively, either 3.5 MHz, 7 MHz or 14 Mhz LPFs are... -#define TX_LPF_C (3) // ...switched inline depending upon the TX frequency -#define CW_KEY (2) // Pin goes high during CW keydown to transmit the carrier. - // ... The CW_KEY is needed in addition to the TX/RX key as the... +static const uint8_t PIN_ENC_A = A0; // Tuning encoder interface +static const uint8_t PIN_ENC_B = A1; // Tuning encoder interface +static const uint8_t PIN_ENC_PUSH_BUTTON = A2; // Tuning encoder interface +static const uint8_t PIN_PTT = A3; // Sense it for ssb and as a straight key for cw operation +static const uint8_t PIN_ANALOG_KEYER = A6; // This is used as keyer. The analog port has 4.7K pull up resistor. Details are in the circuit description on www.hfsignals.com +static const uint8_t PIN_ANALOG_SPARE = A7; // Not used yet + +static const uint8_t PIN_TX_RXn = 7; // Pin from the Nano to the radio to switch to TX (HIGH) and RX(LOW) +static const uint8_t PIN_CW_TONE = 6; // Generates a square wave sidetone while sending the CW. +static const uint8_t PIN_TX_LPF_A = 5; // The 30 MHz LPF is permanently connected in the output of the PA... +static const uint8_t PIN_TX_LPF_B = 4; // ...Alternatively, either 3.5 MHz, 7 MHz or 14 Mhz LPFs are... +static const uint8_t PIN_TX_LPF_C = 3; // ...switched inline depending upon the TX frequency +static const uint8_t PIN_CW_KEY = 2; // Pin goes high during CW keydown to transmit the carrier. + // ... The PIN_CW_KEY is needed in addition to the TX/RX key as the... // ...key can be up within a tx period @@ -43,88 +41,12 @@ The model is called tjctm24028-spi it uses an ILI9341 display controller and an XPT2046 touch controller. */ -#define TFT_DC 9 -#define TFT_CS 10 -#define CS_PIN 8 //this is the pin to select the touch controller on spi interface - -/** - * The Arduino, unlike C/C++ on a regular computer with gigabytes of RAM, has very little memory. - * We have to be very careful with variables that are declared inside the functions as they are - * created in a memory region called the stack. The stack has just a few bytes of space on the Arduino - * if you declare large strings inside functions, they can easily exceed the capacity of the stack - * and mess up your programs. - * We circumvent this by declaring a few global buffers as kitchen counters where we can - * slice and dice our strings. These strings are mostly used to control the display or handle - * the input and output from the USB port. We must keep a count of the bytes used while reading - * the serial port as we can easily run out of buffer space. This is done in the serial_in_count variable. - */ -extern char c[30], b[128]; - -/** - * The second set of 16 pins on the Raduino's bottom connector are have the three clock outputs and the digital lines to control the rig. - * This assignment is as follows : - * Pin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - * GND +5V CLK0 GND GND CLK1 GND GND CLK2 GND D2 D3 D4 D5 D6 D7 - * These too are flexible with what you may do with them, for the Raduino, we use them to : - * - TX_RX line : Switches between Transmit and Receive after sensing the PTT or the morse keyer - * - CW_KEY line : turns on the carrier for CW - */ - - -/** - * The uBITX is an upconnversion transceiver. The first IF is at 45 MHz. - * The first IF frequency is not exactly at 45 Mhz but about 5 khz lower, - * this shift is due to the loading on the 45 Mhz crystal filter by the matching - * L-network used on it's either sides. - * The first oscillator works between 48 Mhz and 75 MHz. The signal is subtracted - * from the first oscillator to arriive at 45 Mhz IF. Thus, it is inverted : LSB becomes USB - * and USB becomes LSB. - * The second IF of 11.059 Mhz has a ladder crystal filter. If a second oscillator is used at - * 56 Mhz (appox), the signal is subtracted FROM the oscillator, inverting a second time, and arrives - * at the 11.059 Mhz ladder filter thus doouble inversion, keeps the sidebands as they originally were. - * If the second oscillator is at 33 Mhz, the oscilaltor is subtracated from the signal, - * thus keeping the signal's sidebands inverted. The USB will become LSB. - * We use this technique to switch sidebands. This is to avoid placing the lsbCarrier close to - * 11 MHz where its fifth harmonic beats with the arduino's 16 Mhz oscillator's fourth harmonic - */ - -#define INIT_USB_FREQ (11059200l) -// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz -#define LOWEST_FREQ (100000l) -#define HIGHEST_FREQ (30000000l) -static const uint32_t THRESHOLD_USB_LSB = 10000000L; - -/* these are functions implemented in the main file named as ubitx_xxx.ino */ -void saveVFOs(); -void setFrequency(const unsigned long freq, const bool transmit = false); -void startTx(TuningMode_e tx_mode); -void stopTx(); -void ritEnable(unsigned long f); -void ritDisable(); -void checkCAT(); -void cwKeyer(void); -void switchVFO(Vfo_e vfoSelect); +static const uint8_t PIN_TFT_DC = 9; +static const uint8_t PIN_TFT_CS = 10; +static const uint8_t PIN_TOUCH_CS = 8; //this is the pin to select the touch controller on spi interface int enc_read(void); // returns the number of ticks in a short interval, +ve in clockwise, -ve in anti-clockwise void enc_setup(void); // Setups up initial values and interrupts. int btnDown(); //returns true if the encoder button is pressed -/* these functions are called universally to update the display */ -void updateDisplay(); //updates just the VFO frequency to show what is in 'frequency' variable -void redrawVFOs(); //redraws only the changed digits of the vfo -void guiUpdate(); //repaints the entire screen. Slow!! -void drawCommandbar(char *text); -void drawTx(); -//getValueByKnob() provides a reusable dialog box to get a value from the encoder, the prefix and postfix -//are useful to concatanate the values with text like "Set Freq to " x " KHz" -int getValueByKnob(int minimum, int maximum, int step_size, int initial, char* prefix, char *postfix); - -//main functions to check if any button is pressed and other user interface events -void doCommands(); //does the commands with encoder to jump from button to button - - -/* these are functiosn implemented in ubitx_si5351.cpp */ -void si5351bx_setfreq(uint8_t clknum, uint32_t fout); -void initOscillators(); -void si5351_set_calibration(int32_t cal); //calibration is a small value that is nudged to make up for the inaccuracies of the reference 25 MHz crystal frequency From cc013e5be468c1787cbf1a0cc428d44613899027 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:19:17 -0700 Subject: [PATCH 238/324] stub out some functions that still need to be removed or refactored --- nano_gui.h | 5 +++++ tmp.cpp | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 tmp.cpp diff --git a/nano_gui.h b/nano_gui.h index 71b2d51..e00d4c5 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -18,6 +18,11 @@ void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t bg); void displayText(const char *const text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification = TextJustification_e::Center); +/* these functions are called universally to update the display */ +void updateDisplay(); //updates just the VFO frequency to show what is in 'frequency' variable +void redrawVFOs(); //redraws only the changed digits of the vfo +void drawTx(); + #define TEXT_LINE_HEIGHT 18 #define TEXT_LINE_INDENT 5 diff --git a/tmp.cpp b/tmp.cpp new file mode 100644 index 0000000..2c0d556 --- /dev/null +++ b/tmp.cpp @@ -0,0 +1,12 @@ +#include +#include "pin_definitions.h" + +void updateDisplay() {} +void redrawVFOs(){} +void drawTx(){} +int btnDown() +{ + //Button has a pullup, so it reads high normally, + //and reads low when pressed down + return !digitalRead(PIN_ENC_PUSH_BUTTON); +} \ No newline at end of file From 1ee39ec535db45ec265750b820e50b1098c96b05 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:19:47 -0700 Subject: [PATCH 239/324] Update includes, and disable numpad for space reasons for now --- menu_main_buttons.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 534473d..ca161c2 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -11,9 +11,10 @@ #include "menu_numpad.h" #include "morse.h" #include "nano_gui.h" +#include "scratch_space.h" #include "settings.h" #include "setup.h" -#include "ubitx.h"//setFrequency, b +#include "tuner.h" #include "utils.h" static const unsigned int LAYOUT_VFO_LABEL_X = 0; @@ -587,5 +588,5 @@ void osMenu(){ } void osNumpad(){ - enterSubmenu(numpadMenu); + //enterSubmenu(numpadMenu); } From 40a13f1b5f49a8bcf84b8cd42df681c611cb39f7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:38:34 -0700 Subject: [PATCH 240/324] Re-enable frequency entering --- menu_main_buttons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index ca161c2..590fcca 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -588,5 +588,5 @@ void osMenu(){ } void osNumpad(){ - //enterSubmenu(numpadMenu); + enterSubmenu(numpadMenu); } From 98e62a6dcab76667e03ad3a438ebf5b8769bfbff Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:40:02 -0700 Subject: [PATCH 241/324] Switch to using a tiny but terrible looking font for size reasons --- PDQ_MinLib/Picopixel.h | 120 +++++++++++++++++++++++++++++++++++++++++ nano_font.cpp | 6 ++- nano_gui.cpp | 2 +- 3 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 PDQ_MinLib/Picopixel.h diff --git a/PDQ_MinLib/Picopixel.h b/PDQ_MinLib/Picopixel.h new file mode 100644 index 0000000..c1a0092 --- /dev/null +++ b/PDQ_MinLib/Picopixel.h @@ -0,0 +1,120 @@ +// Picopixel by Sebastian Weber. A tiny font +// with all characters within a 6 pixel height. + +const uint8_t PicopixelBitmaps[] PROGMEM = { + 0xE8, 0xB4, 0x57, 0xD5, 0xF5, 0x00, 0x4E, 0x3E, 0x80, 0xA5, 0x4A, 0x4A, + 0x5A, 0x50, 0xC0, 0x6A, 0x40, 0x95, 0x80, 0xAA, 0x80, 0x5D, 0x00, 0x60, + 0xE0, 0x80, 0x25, 0x48, 0x56, 0xD4, 0x75, 0x40, 0xC5, 0x4E, 0xC5, 0x1C, + 0x97, 0x92, 0xF3, 0x1C, 0x53, 0x54, 0xE5, 0x48, 0x55, 0x54, 0x55, 0x94, + 0xA0, 0x46, 0x64, 0xE3, 0x80, 0x98, 0xC5, 0x04, 0x56, 0xC6, 0x57, 0xDA, + 0xD7, 0x5C, 0x72, 0x46, 0xD6, 0xDC, 0xF3, 0xCE, 0xF3, 0x48, 0x72, 0xD4, + 0xB7, 0xDA, 0xF8, 0x24, 0xD4, 0xBB, 0x5A, 0x92, 0x4E, 0x8E, 0xEB, 0x58, + 0x80, 0x9D, 0xB9, 0x90, 0x56, 0xD4, 0xD7, 0x48, 0x56, 0xD4, 0x40, 0xD7, + 0x5A, 0x71, 0x1C, 0xE9, 0x24, 0xB6, 0xD4, 0xB6, 0xA4, 0x8C, 0x6B, 0x55, + 0x00, 0xB5, 0x5A, 0xB5, 0x24, 0xE5, 0x4E, 0xEA, 0xC0, 0x91, 0x12, 0xD5, + 0xC0, 0x54, 0xF0, 0x90, 0xC7, 0xF0, 0x93, 0x5E, 0x71, 0x80, 0x25, 0xDE, + 0x5E, 0x30, 0x6E, 0x80, 0x77, 0x9C, 0x93, 0x5A, 0xB8, 0x45, 0x60, 0x92, + 0xEA, 0xAA, 0x40, 0xD5, 0x6A, 0xD6, 0x80, 0x55, 0x00, 0xD7, 0x40, 0x75, + 0x90, 0xE8, 0x71, 0xE0, 0xBA, 0x40, 0xB5, 0x80, 0xB5, 0x00, 0x8D, 0x54, + 0xAA, 0x80, 0xAC, 0xE0, 0xE5, 0x70, 0x6A, 0x26, 0xFC, 0xC8, 0xAC, 0x5A}; + +const GFXglyph PicopixelGlyphs[] PROGMEM = {{0, 0, 0, 2, 0, 1}, // 0x20 ' ' + {0, 1, 5, 2, 0, -4}, // 0x21 '!' + {1, 3, 2, 4, 0, -4}, // 0x22 '"' + {2, 5, 5, 6, 0, -4}, // 0x23 '#' + {6, 3, 6, 4, 0, -4}, // 0x24 '$' + {9, 3, 5, 4, 0, -4}, // 0x25 '%' + {11, 4, 5, 5, 0, -4}, // 0x26 '&' + {14, 1, 2, 2, 0, -4}, // 0x27 ''' + {15, 2, 5, 3, 0, -4}, // 0x28 '(' + {17, 2, 5, 3, 0, -4}, // 0x29 ')' + {19, 3, 3, 4, 0, -3}, // 0x2A '*' + {21, 3, 3, 4, 0, -3}, // 0x2B '+' + {23, 2, 2, 3, 0, 0}, // 0x2C ',' + {24, 3, 1, 4, 0, -2}, // 0x2D '-' + {25, 1, 1, 2, 0, 0}, // 0x2E '.' + {26, 3, 5, 4, 0, -4}, // 0x2F '/' + {28, 3, 5, 4, 0, -4}, // 0x30 '0' + {30, 2, 5, 3, 0, -4}, // 0x31 '1' + {32, 3, 5, 4, 0, -4}, // 0x32 '2' + {34, 3, 5, 4, 0, -4}, // 0x33 '3' + {36, 3, 5, 4, 0, -4}, // 0x34 '4' + {38, 3, 5, 4, 0, -4}, // 0x35 '5' + {40, 3, 5, 4, 0, -4}, // 0x36 '6' + {42, 3, 5, 4, 0, -4}, // 0x37 '7' + {44, 3, 5, 4, 0, -4}, // 0x38 '8' + {46, 3, 5, 4, 0, -4}, // 0x39 '9' + {48, 1, 3, 2, 0, -3}, // 0x3A ':' + {49, 2, 4, 3, 0, -3}, // 0x3B ';' + {50, 2, 3, 3, 0, -3}, // 0x3C '<' + {51, 3, 3, 4, 0, -3}, // 0x3D '=' + {53, 2, 3, 3, 0, -3}, // 0x3E '>' + {54, 3, 5, 4, 0, -4}, // 0x3F '?' + {56, 3, 5, 4, 0, -4}, // 0x40 '@' + {58, 3, 5, 4, 0, -4}, // 0x41 'A' + {60, 3, 5, 4, 0, -4}, // 0x42 'B' + {62, 3, 5, 4, 0, -4}, // 0x43 'C' + {64, 3, 5, 4, 0, -4}, // 0x44 'D' + {66, 3, 5, 4, 0, -4}, // 0x45 'E' + {68, 3, 5, 4, 0, -4}, // 0x46 'F' + {70, 3, 5, 4, 0, -4}, // 0x47 'G' + {72, 3, 5, 4, 0, -4}, // 0x48 'H' + {74, 1, 5, 2, 0, -4}, // 0x49 'I' + {75, 3, 5, 4, 0, -4}, // 0x4A 'J' + {77, 3, 5, 4, 0, -4}, // 0x4B 'K' + {79, 3, 5, 4, 0, -4}, // 0x4C 'L' + {81, 5, 5, 6, 0, -4}, // 0x4D 'M' + {85, 4, 5, 5, 0, -4}, // 0x4E 'N' + {88, 3, 5, 4, 0, -4}, // 0x4F 'O' + {90, 3, 5, 4, 0, -4}, // 0x50 'P' + {92, 3, 6, 4, 0, -4}, // 0x51 'Q' + {95, 3, 5, 4, 0, -4}, // 0x52 'R' + {97, 3, 5, 4, 0, -4}, // 0x53 'S' + {99, 3, 5, 4, 0, -4}, // 0x54 'T' + {101, 3, 5, 4, 0, -4}, // 0x55 'U' + {103, 3, 5, 4, 0, -4}, // 0x56 'V' + {105, 5, 5, 6, 0, -4}, // 0x57 'W' + {109, 3, 5, 4, 0, -4}, // 0x58 'X' + {111, 3, 5, 4, 0, -4}, // 0x59 'Y' + {113, 3, 5, 4, 0, -4}, // 0x5A 'Z' + {115, 2, 5, 3, 0, -4}, // 0x5B '[' + {117, 3, 5, 4, 0, -4}, // 0x5C '\' + {119, 2, 5, 3, 0, -4}, // 0x5D ']' + {121, 3, 2, 4, 0, -4}, // 0x5E '^' + {122, 4, 1, 4, 0, 1}, // 0x5F '_' + {123, 2, 2, 3, 0, -4}, // 0x60 '`' + {124, 3, 4, 4, 0, -3}, // 0x61 'a' + {126, 3, 5, 4, 0, -4}, // 0x62 'b' + {128, 3, 3, 4, 0, -2}, // 0x63 'c' + {130, 3, 5, 4, 0, -4}, // 0x64 'd' + {132, 3, 4, 4, 0, -3}, // 0x65 'e' + {134, 2, 5, 3, 0, -4}, // 0x66 'f' + {136, 3, 5, 4, 0, -3}, // 0x67 'g' + {138, 3, 5, 4, 0, -4}, // 0x68 'h' + {140, 1, 5, 2, 0, -4}, // 0x69 'i' + {141, 2, 6, 3, 0, -4}, // 0x6A 'j' + {143, 3, 5, 4, 0, -4}, // 0x6B 'k' + {145, 2, 5, 3, 0, -4}, // 0x6C 'l' + {147, 5, 3, 6, 0, -2}, // 0x6D 'm' + {149, 3, 3, 4, 0, -2}, // 0x6E 'n' + {151, 3, 3, 4, 0, -2}, // 0x6F 'o' + {153, 3, 4, 4, 0, -2}, // 0x70 'p' + {155, 3, 4, 4, 0, -2}, // 0x71 'q' + {157, 2, 3, 3, 0, -2}, // 0x72 'r' + {158, 3, 4, 4, 0, -3}, // 0x73 's' + {160, 2, 5, 3, 0, -4}, // 0x74 't' + {162, 3, 3, 4, 0, -2}, // 0x75 'u' + {164, 3, 3, 4, 0, -2}, // 0x76 'v' + {166, 5, 3, 6, 0, -2}, // 0x77 'w' + {168, 3, 3, 4, 0, -2}, // 0x78 'x' + {170, 3, 4, 4, 0, -2}, // 0x79 'y' + {172, 3, 4, 4, 0, -3}, // 0x7A 'z' + {174, 3, 5, 4, 0, -4}, // 0x7B '{' + {176, 1, 6, 2, 0, -4}, // 0x7C '|' + {177, 3, 5, 4, 0, -4}, // 0x7D '}' + {179, 4, 2, 5, 0, -3}}; // 0x7E '~' + +const GFXfont Picopixel PROGMEM = {(uint8_t *)PicopixelBitmaps, + (GFXglyph *)PicopixelGlyphs, 0x20, 0x7E, 7}; + +// Approx. 852 bytes diff --git a/nano_font.cpp b/nano_font.cpp index 9a0265d..d4651aa 100644 --- a/nano_font.cpp +++ b/nano_font.cpp @@ -1,6 +1,8 @@ #include "nano_font.h" #include -#include "PDQ_MinLib/FreeSansBold9pt7b.h" +//#include "PDQ_MinLib/FreeSansBold9pt7b.h" +#include "PDQ_MinLib/Picopixel.h" -const GFXfont* ubitx_font = &FreeSansBold9pt7b; \ No newline at end of file +//const GFXfont* ubitx_font = &FreeSansBold9pt7b; +const GFXfont* ubitx_font = &Picopixel; \ No newline at end of file diff --git a/nano_gui.cpp b/nano_gui.cpp index b46b4cf..f8960c2 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -34,7 +34,7 @@ void displayInit(void){ tft.setFont(ubitx_font); tft.setTextWrap(true); tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK); - tft.setTextSize(1); + tft.setTextSize(4); tft.setRotation(1); } From 80494b62b9cf06c188358f7cedb50b7f852a6476 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 21 Apr 2020 21:56:51 -0700 Subject: [PATCH 242/324] Try a couple other fonts. None are great. --- PDQ_MinLib/TomThumb.h | 471 ++++++++++++++++++++++++++++++++++++++++++ PDQ_MinLib/org_01.h | 128 ++++++++++++ nano_font.cpp | 8 +- nano_gui.cpp | 2 +- 4 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 PDQ_MinLib/TomThumb.h create mode 100644 PDQ_MinLib/org_01.h diff --git a/PDQ_MinLib/TomThumb.h b/PDQ_MinLib/TomThumb.h new file mode 100644 index 0000000..8bc4339 --- /dev/null +++ b/PDQ_MinLib/TomThumb.h @@ -0,0 +1,471 @@ +/** +** The original 3x5 font is licensed under the 3-clause BSD license: +** +** Copyright 1999 Brian J. Swetland +** Copyright 1999 Vassilii Khachaturov +** Portions (of vt100.c/vt100.h) copyright Dan Marks +** +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions, and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions, and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the authors may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +** +** Modifications to Tom Thumb for improved readability are from Robey Pointer, +** see: +** http://robey.lag.net/2010/01/23/tiny-monospace-font.html +** +** The original author does not have any objection to relicensing of Robey +** Pointer's modifications (in this file) in a more permissive license. See +** the discussion at the above blog, and also here: +** http://opengameart.org/forumtopic/how-to-submit-art-using-the-3-clause-bsd-license +** +** Feb 21, 2016: Conversion from Linux BDF --> Adafruit GFX font, +** with the help of this Python script: +** https://gist.github.com/skelliam/322d421f028545f16f6d +** William Skellenger (williamj@skellenger.net) +** Twitter: @skelliam +** +*/ + +#define TOMTHUMB_USE_EXTENDED 0 + +const uint8_t TomThumbBitmaps[] PROGMEM = { + 0x00, /* 0x20 space */ + 0x80, 0x80, 0x80, 0x00, 0x80, /* 0x21 exclam */ + 0xA0, 0xA0, /* 0x22 quotedbl */ + 0xA0, 0xE0, 0xA0, 0xE0, 0xA0, /* 0x23 numbersign */ + 0x60, 0xC0, 0x60, 0xC0, 0x40, /* 0x24 dollar */ + 0x80, 0x20, 0x40, 0x80, 0x20, /* 0x25 percent */ + 0xC0, 0xC0, 0xE0, 0xA0, 0x60, /* 0x26 ampersand */ + 0x80, 0x80, /* 0x27 quotesingle */ + 0x40, 0x80, 0x80, 0x80, 0x40, /* 0x28 parenleft */ + 0x80, 0x40, 0x40, 0x40, 0x80, /* 0x29 parenright */ + 0xA0, 0x40, 0xA0, /* 0x2A asterisk */ + 0x40, 0xE0, 0x40, /* 0x2B plus */ + 0x40, 0x80, /* 0x2C comma */ + 0xE0, /* 0x2D hyphen */ + 0x80, /* 0x2E period */ + 0x20, 0x20, 0x40, 0x80, 0x80, /* 0x2F slash */ + 0x60, 0xA0, 0xA0, 0xA0, 0xC0, /* 0x30 zero */ + 0x40, 0xC0, 0x40, 0x40, 0x40, /* 0x31 one */ + 0xC0, 0x20, 0x40, 0x80, 0xE0, /* 0x32 two */ + 0xC0, 0x20, 0x40, 0x20, 0xC0, /* 0x33 three */ + 0xA0, 0xA0, 0xE0, 0x20, 0x20, /* 0x34 four */ + 0xE0, 0x80, 0xC0, 0x20, 0xC0, /* 0x35 five */ + 0x60, 0x80, 0xE0, 0xA0, 0xE0, /* 0x36 six */ + 0xE0, 0x20, 0x40, 0x80, 0x80, /* 0x37 seven */ + 0xE0, 0xA0, 0xE0, 0xA0, 0xE0, /* 0x38 eight */ + 0xE0, 0xA0, 0xE0, 0x20, 0xC0, /* 0x39 nine */ + 0x80, 0x00, 0x80, /* 0x3A colon */ + 0x40, 0x00, 0x40, 0x80, /* 0x3B semicolon */ + 0x20, 0x40, 0x80, 0x40, 0x20, /* 0x3C less */ + 0xE0, 0x00, 0xE0, /* 0x3D equal */ + 0x80, 0x40, 0x20, 0x40, 0x80, /* 0x3E greater */ + 0xE0, 0x20, 0x40, 0x00, 0x40, /* 0x3F question */ + 0x40, 0xA0, 0xE0, 0x80, 0x60, /* 0x40 at */ + 0x40, 0xA0, 0xE0, 0xA0, 0xA0, /* 0x41 A */ + 0xC0, 0xA0, 0xC0, 0xA0, 0xC0, /* 0x42 B */ + 0x60, 0x80, 0x80, 0x80, 0x60, /* 0x43 C */ + 0xC0, 0xA0, 0xA0, 0xA0, 0xC0, /* 0x44 D */ + 0xE0, 0x80, 0xE0, 0x80, 0xE0, /* 0x45 E */ + 0xE0, 0x80, 0xE0, 0x80, 0x80, /* 0x46 F */ + 0x60, 0x80, 0xE0, 0xA0, 0x60, /* 0x47 G */ + 0xA0, 0xA0, 0xE0, 0xA0, 0xA0, /* 0x48 H */ + 0xE0, 0x40, 0x40, 0x40, 0xE0, /* 0x49 I */ + 0x20, 0x20, 0x20, 0xA0, 0x40, /* 0x4A J */ + 0xA0, 0xA0, 0xC0, 0xA0, 0xA0, /* 0x4B K */ + 0x80, 0x80, 0x80, 0x80, 0xE0, /* 0x4C L */ + 0xA0, 0xE0, 0xE0, 0xA0, 0xA0, /* 0x4D M */ + 0xA0, 0xE0, 0xE0, 0xE0, 0xA0, /* 0x4E N */ + 0x40, 0xA0, 0xA0, 0xA0, 0x40, /* 0x4F O */ + 0xC0, 0xA0, 0xC0, 0x80, 0x80, /* 0x50 P */ + 0x40, 0xA0, 0xA0, 0xE0, 0x60, /* 0x51 Q */ + 0xC0, 0xA0, 0xE0, 0xC0, 0xA0, /* 0x52 R */ + 0x60, 0x80, 0x40, 0x20, 0xC0, /* 0x53 S */ + 0xE0, 0x40, 0x40, 0x40, 0x40, /* 0x54 T */ + 0xA0, 0xA0, 0xA0, 0xA0, 0x60, /* 0x55 U */ + 0xA0, 0xA0, 0xA0, 0x40, 0x40, /* 0x56 V */ + 0xA0, 0xA0, 0xE0, 0xE0, 0xA0, /* 0x57 W */ + 0xA0, 0xA0, 0x40, 0xA0, 0xA0, /* 0x58 X */ + 0xA0, 0xA0, 0x40, 0x40, 0x40, /* 0x59 Y */ + 0xE0, 0x20, 0x40, 0x80, 0xE0, /* 0x5A Z */ + 0xE0, 0x80, 0x80, 0x80, 0xE0, /* 0x5B bracketleft */ + 0x80, 0x40, 0x20, /* 0x5C backslash */ + 0xE0, 0x20, 0x20, 0x20, 0xE0, /* 0x5D bracketright */ + 0x40, 0xA0, /* 0x5E asciicircum */ + 0xE0, /* 0x5F underscore */ + 0x80, 0x40, /* 0x60 grave */ + 0xC0, 0x60, 0xA0, 0xE0, /* 0x61 a */ + 0x80, 0xC0, 0xA0, 0xA0, 0xC0, /* 0x62 b */ + 0x60, 0x80, 0x80, 0x60, /* 0x63 c */ + 0x20, 0x60, 0xA0, 0xA0, 0x60, /* 0x64 d */ + 0x60, 0xA0, 0xC0, 0x60, /* 0x65 e */ + 0x20, 0x40, 0xE0, 0x40, 0x40, /* 0x66 f */ + 0x60, 0xA0, 0xE0, 0x20, 0x40, /* 0x67 g */ + 0x80, 0xC0, 0xA0, 0xA0, 0xA0, /* 0x68 h */ + 0x80, 0x00, 0x80, 0x80, 0x80, /* 0x69 i */ + 0x20, 0x00, 0x20, 0x20, 0xA0, 0x40, /* 0x6A j */ + 0x80, 0xA0, 0xC0, 0xC0, 0xA0, /* 0x6B k */ + 0xC0, 0x40, 0x40, 0x40, 0xE0, /* 0x6C l */ + 0xE0, 0xE0, 0xE0, 0xA0, /* 0x6D m */ + 0xC0, 0xA0, 0xA0, 0xA0, /* 0x6E n */ + 0x40, 0xA0, 0xA0, 0x40, /* 0x6F o */ + 0xC0, 0xA0, 0xA0, 0xC0, 0x80, /* 0x70 p */ + 0x60, 0xA0, 0xA0, 0x60, 0x20, /* 0x71 q */ + 0x60, 0x80, 0x80, 0x80, /* 0x72 r */ + 0x60, 0xC0, 0x60, 0xC0, /* 0x73 s */ + 0x40, 0xE0, 0x40, 0x40, 0x60, /* 0x74 t */ + 0xA0, 0xA0, 0xA0, 0x60, /* 0x75 u */ + 0xA0, 0xA0, 0xE0, 0x40, /* 0x76 v */ + 0xA0, 0xE0, 0xE0, 0xE0, /* 0x77 w */ + 0xA0, 0x40, 0x40, 0xA0, /* 0x78 x */ + 0xA0, 0xA0, 0x60, 0x20, 0x40, /* 0x79 y */ + 0xE0, 0x60, 0xC0, 0xE0, /* 0x7A z */ + 0x60, 0x40, 0x80, 0x40, 0x60, /* 0x7B braceleft */ + 0x80, 0x80, 0x00, 0x80, 0x80, /* 0x7C bar */ + 0xC0, 0x40, 0x20, 0x40, 0xC0, /* 0x7D braceright */ + 0x60, 0xC0, /* 0x7E asciitilde */ +#if (TOMTHUMB_USE_EXTENDED) + 0x80, 0x00, 0x80, 0x80, 0x80, /* 0xA1 exclamdown */ + 0x40, 0xE0, 0x80, 0xE0, 0x40, /* 0xA2 cent */ + 0x60, 0x40, 0xE0, 0x40, 0xE0, /* 0xA3 sterling */ + 0xA0, 0x40, 0xE0, 0x40, 0xA0, /* 0xA4 currency */ + 0xA0, 0xA0, 0x40, 0xE0, 0x40, /* 0xA5 yen */ + 0x80, 0x80, 0x00, 0x80, 0x80, /* 0xA6 brokenbar */ + 0x60, 0x40, 0xA0, 0x40, 0xC0, /* 0xA7 section */ + 0xA0, /* 0xA8 dieresis */ + 0x60, 0x80, 0x60, /* 0xA9 copyright */ + 0x60, 0xA0, 0xE0, 0x00, 0xE0, /* 0xAA ordfeminine */ + 0x40, 0x80, 0x40, /* 0xAB guillemotleft */ + 0xE0, 0x20, /* 0xAC logicalnot */ + 0xC0, /* 0xAD softhyphen */ + 0xC0, 0xC0, 0xA0, /* 0xAE registered */ + 0xE0, /* 0xAF macron */ + 0x40, 0xA0, 0x40, /* 0xB0 degree */ + 0x40, 0xE0, 0x40, 0x00, 0xE0, /* 0xB1 plusminus */ + 0xC0, 0x40, 0x60, /* 0xB2 twosuperior */ + 0xE0, 0x60, 0xE0, /* 0xB3 threesuperior */ + 0x40, 0x80, /* 0xB4 acute */ + 0xA0, 0xA0, 0xA0, 0xC0, 0x80, /* 0xB5 mu */ + 0x60, 0xA0, 0x60, 0x60, 0x60, /* 0xB6 paragraph */ + 0xE0, 0xE0, 0xE0, /* 0xB7 periodcentered */ + 0x40, 0x20, 0xC0, /* 0xB8 cedilla */ + 0x80, 0x80, 0x80, /* 0xB9 onesuperior */ + 0x40, 0xA0, 0x40, 0x00, 0xE0, /* 0xBA ordmasculine */ + 0x80, 0x40, 0x80, /* 0xBB guillemotright */ + 0x80, 0x80, 0x00, 0x60, 0x20, /* 0xBC onequarter */ + 0x80, 0x80, 0x00, 0xC0, 0x60, /* 0xBD onehalf */ + 0xC0, 0xC0, 0x00, 0x60, 0x20, /* 0xBE threequarters */ + 0x40, 0x00, 0x40, 0x80, 0xE0, /* 0xBF questiondown */ + 0x40, 0x20, 0x40, 0xE0, 0xA0, /* 0xC0 Agrave */ + 0x40, 0x80, 0x40, 0xE0, 0xA0, /* 0xC1 Aacute */ + 0xE0, 0x00, 0x40, 0xE0, 0xA0, /* 0xC2 Acircumflex */ + 0x60, 0xC0, 0x40, 0xE0, 0xA0, /* 0xC3 Atilde */ + 0xA0, 0x40, 0xA0, 0xE0, 0xA0, /* 0xC4 Adieresis */ + 0xC0, 0xC0, 0xA0, 0xE0, 0xA0, /* 0xC5 Aring */ + 0x60, 0xC0, 0xE0, 0xC0, 0xE0, /* 0xC6 AE */ + 0x60, 0x80, 0x80, 0x60, 0x20, 0x40, /* 0xC7 Ccedilla */ + 0x40, 0x20, 0xE0, 0xC0, 0xE0, /* 0xC8 Egrave */ + 0x40, 0x80, 0xE0, 0xC0, 0xE0, /* 0xC9 Eacute */ + 0xE0, 0x00, 0xE0, 0xC0, 0xE0, /* 0xCA Ecircumflex */ + 0xA0, 0x00, 0xE0, 0xC0, 0xE0, /* 0xCB Edieresis */ + 0x40, 0x20, 0xE0, 0x40, 0xE0, /* 0xCC Igrave */ + 0x40, 0x80, 0xE0, 0x40, 0xE0, /* 0xCD Iacute */ + 0xE0, 0x00, 0xE0, 0x40, 0xE0, /* 0xCE Icircumflex */ + 0xA0, 0x00, 0xE0, 0x40, 0xE0, /* 0xCF Idieresis */ + 0xC0, 0xA0, 0xE0, 0xA0, 0xC0, /* 0xD0 Eth */ + 0xC0, 0x60, 0xA0, 0xE0, 0xA0, /* 0xD1 Ntilde */ + 0x40, 0x20, 0xE0, 0xA0, 0xE0, /* 0xD2 Ograve */ + 0x40, 0x80, 0xE0, 0xA0, 0xE0, /* 0xD3 Oacute */ + 0xE0, 0x00, 0xE0, 0xA0, 0xE0, /* 0xD4 Ocircumflex */ + 0xC0, 0x60, 0xE0, 0xA0, 0xE0, /* 0xD5 Otilde */ + 0xA0, 0x00, 0xE0, 0xA0, 0xE0, /* 0xD6 Odieresis */ + 0xA0, 0x40, 0xA0, /* 0xD7 multiply */ + 0x60, 0xA0, 0xE0, 0xA0, 0xC0, /* 0xD8 Oslash */ + 0x80, 0x40, 0xA0, 0xA0, 0xE0, /* 0xD9 Ugrave */ + 0x20, 0x40, 0xA0, 0xA0, 0xE0, /* 0xDA Uacute */ + 0xE0, 0x00, 0xA0, 0xA0, 0xE0, /* 0xDB Ucircumflex */ + 0xA0, 0x00, 0xA0, 0xA0, 0xE0, /* 0xDC Udieresis */ + 0x20, 0x40, 0xA0, 0xE0, 0x40, /* 0xDD Yacute */ + 0x80, 0xE0, 0xA0, 0xE0, 0x80, /* 0xDE Thorn */ + 0x60, 0xA0, 0xC0, 0xA0, 0xC0, 0x80, /* 0xDF germandbls */ + 0x40, 0x20, 0x60, 0xA0, 0xE0, /* 0xE0 agrave */ + 0x40, 0x80, 0x60, 0xA0, 0xE0, /* 0xE1 aacute */ + 0xE0, 0x00, 0x60, 0xA0, 0xE0, /* 0xE2 acircumflex */ + 0x60, 0xC0, 0x60, 0xA0, 0xE0, /* 0xE3 atilde */ + 0xA0, 0x00, 0x60, 0xA0, 0xE0, /* 0xE4 adieresis */ + 0x60, 0x60, 0x60, 0xA0, 0xE0, /* 0xE5 aring */ + 0x60, 0xE0, 0xE0, 0xC0, /* 0xE6 ae */ + 0x60, 0x80, 0x60, 0x20, 0x40, /* 0xE7 ccedilla */ + 0x40, 0x20, 0x60, 0xE0, 0x60, /* 0xE8 egrave */ + 0x40, 0x80, 0x60, 0xE0, 0x60, /* 0xE9 eacute */ + 0xE0, 0x00, 0x60, 0xE0, 0x60, /* 0xEA ecircumflex */ + 0xA0, 0x00, 0x60, 0xE0, 0x60, /* 0xEB edieresis */ + 0x80, 0x40, 0x80, 0x80, 0x80, /* 0xEC igrave */ + 0x40, 0x80, 0x40, 0x40, 0x40, /* 0xED iacute */ + 0xE0, 0x00, 0x40, 0x40, 0x40, /* 0xEE icircumflex */ + 0xA0, 0x00, 0x40, 0x40, 0x40, /* 0xEF idieresis */ + 0x60, 0xC0, 0x60, 0xA0, 0x60, /* 0xF0 eth */ + 0xC0, 0x60, 0xC0, 0xA0, 0xA0, /* 0xF1 ntilde */ + 0x40, 0x20, 0x40, 0xA0, 0x40, /* 0xF2 ograve */ + 0x40, 0x80, 0x40, 0xA0, 0x40, /* 0xF3 oacute */ + 0xE0, 0x00, 0x40, 0xA0, 0x40, /* 0xF4 ocircumflex */ + 0xC0, 0x60, 0x40, 0xA0, 0x40, /* 0xF5 otilde */ + 0xA0, 0x00, 0x40, 0xA0, 0x40, /* 0xF6 odieresis */ + 0x40, 0x00, 0xE0, 0x00, 0x40, /* 0xF7 divide */ + 0x60, 0xE0, 0xA0, 0xC0, /* 0xF8 oslash */ + 0x80, 0x40, 0xA0, 0xA0, 0x60, /* 0xF9 ugrave */ + 0x20, 0x40, 0xA0, 0xA0, 0x60, /* 0xFA uacute */ + 0xE0, 0x00, 0xA0, 0xA0, 0x60, /* 0xFB ucircumflex */ + 0xA0, 0x00, 0xA0, 0xA0, 0x60, /* 0xFC udieresis */ + 0x20, 0x40, 0xA0, 0x60, 0x20, 0x40, /* 0xFD yacute */ + 0x80, 0xC0, 0xA0, 0xC0, 0x80, /* 0xFE thorn */ + 0xA0, 0x00, 0xA0, 0x60, 0x20, 0x40, /* 0xFF ydieresis */ + 0x00, /* 0x11D gcircumflex */ + 0x60, 0xC0, 0xE0, 0xC0, 0x60, /* 0x152 OE */ + 0x60, 0xE0, 0xC0, 0xE0, /* 0x153 oe */ + 0xA0, 0x60, 0xC0, 0x60, 0xC0, /* 0x160 Scaron */ + 0xA0, 0x60, 0xC0, 0x60, 0xC0, /* 0x161 scaron */ + 0xA0, 0x00, 0xA0, 0x40, 0x40, /* 0x178 Ydieresis */ + 0xA0, 0xE0, 0x60, 0xC0, 0xE0, /* 0x17D Zcaron */ + 0xA0, 0xE0, 0x60, 0xC0, 0xE0, /* 0x17E zcaron */ + 0x00, /* 0xEA4 uni0EA4 */ + 0x00, /* 0x13A0 uni13A0 */ + 0x80, /* 0x2022 bullet */ + 0xA0, /* 0x2026 ellipsis */ + 0x60, 0xE0, 0xE0, 0xC0, 0x60, /* 0x20AC Euro */ + 0xE0, 0xA0, 0xA0, 0xA0, 0xE0, /* 0xFFFD uniFFFD */ +#endif /* (TOMTHUMB_USE_EXTENDED) */ +}; + +/* {offset, width, height, advance cursor, x offset, y offset} */ +const GFXglyph TomThumbGlyphs[] PROGMEM = { + {0, 8, 1, 2, 0, -5}, /* 0x20 space */ + {1, 8, 5, 2, 0, -5}, /* 0x21 exclam */ + {6, 8, 2, 4, 0, -5}, /* 0x22 quotedbl */ + {8, 8, 5, 4, 0, -5}, /* 0x23 numbersign */ + {13, 8, 5, 4, 0, -5}, /* 0x24 dollar */ + {18, 8, 5, 4, 0, -5}, /* 0x25 percent */ + {23, 8, 5, 4, 0, -5}, /* 0x26 ampersand */ + {28, 8, 2, 2, 0, -5}, /* 0x27 quotesingle */ + {30, 8, 5, 3, 0, -5}, /* 0x28 parenleft */ + {35, 8, 5, 3, 0, -5}, /* 0x29 parenright */ + {40, 8, 3, 4, 0, -5}, /* 0x2A asterisk */ + {43, 8, 3, 4, 0, -4}, /* 0x2B plus */ + {46, 8, 2, 3, 0, -2}, /* 0x2C comma */ + {48, 8, 1, 4, 0, -3}, /* 0x2D hyphen */ + {49, 8, 1, 2, 0, -1}, /* 0x2E period */ + {50, 8, 5, 4, 0, -5}, /* 0x2F slash */ + {55, 8, 5, 4, 0, -5}, /* 0x30 zero */ + {60, 8, 5, 3, 0, -5}, /* 0x31 one */ + {65, 8, 5, 4, 0, -5}, /* 0x32 two */ + {70, 8, 5, 4, 0, -5}, /* 0x33 three */ + {75, 8, 5, 4, 0, -5}, /* 0x34 four */ + {80, 8, 5, 4, 0, -5}, /* 0x35 five */ + {85, 8, 5, 4, 0, -5}, /* 0x36 six */ + {90, 8, 5, 4, 0, -5}, /* 0x37 seven */ + {95, 8, 5, 4, 0, -5}, /* 0x38 eight */ + {100, 8, 5, 4, 0, -5}, /* 0x39 nine */ + {105, 8, 3, 2, 0, -4}, /* 0x3A colon */ + {108, 8, 4, 3, 0, -4}, /* 0x3B semicolon */ + {112, 8, 5, 4, 0, -5}, /* 0x3C less */ + {117, 8, 3, 4, 0, -4}, /* 0x3D equal */ + {120, 8, 5, 4, 0, -5}, /* 0x3E greater */ + {125, 8, 5, 4, 0, -5}, /* 0x3F question */ + {130, 8, 5, 4, 0, -5}, /* 0x40 at */ + {135, 8, 5, 4, 0, -5}, /* 0x41 A */ + {140, 8, 5, 4, 0, -5}, /* 0x42 B */ + {145, 8, 5, 4, 0, -5}, /* 0x43 C */ + {150, 8, 5, 4, 0, -5}, /* 0x44 D */ + {155, 8, 5, 4, 0, -5}, /* 0x45 E */ + {160, 8, 5, 4, 0, -5}, /* 0x46 F */ + {165, 8, 5, 4, 0, -5}, /* 0x47 G */ + {170, 8, 5, 4, 0, -5}, /* 0x48 H */ + {175, 8, 5, 4, 0, -5}, /* 0x49 I */ + {180, 8, 5, 4, 0, -5}, /* 0x4A J */ + {185, 8, 5, 4, 0, -5}, /* 0x4B K */ + {190, 8, 5, 4, 0, -5}, /* 0x4C L */ + {195, 8, 5, 4, 0, -5}, /* 0x4D M */ + {200, 8, 5, 4, 0, -5}, /* 0x4E N */ + {205, 8, 5, 4, 0, -5}, /* 0x4F O */ + {210, 8, 5, 4, 0, -5}, /* 0x50 P */ + {215, 8, 5, 4, 0, -5}, /* 0x51 Q */ + {220, 8, 5, 4, 0, -5}, /* 0x52 R */ + {225, 8, 5, 4, 0, -5}, /* 0x53 S */ + {230, 8, 5, 4, 0, -5}, /* 0x54 T */ + {235, 8, 5, 4, 0, -5}, /* 0x55 U */ + {240, 8, 5, 4, 0, -5}, /* 0x56 V */ + {245, 8, 5, 4, 0, -5}, /* 0x57 W */ + {250, 8, 5, 4, 0, -5}, /* 0x58 X */ + {255, 8, 5, 4, 0, -5}, /* 0x59 Y */ + {260, 8, 5, 4, 0, -5}, /* 0x5A Z */ + {265, 8, 5, 4, 0, -5}, /* 0x5B bracketleft */ + {270, 8, 3, 4, 0, -4}, /* 0x5C backslash */ + {273, 8, 5, 4, 0, -5}, /* 0x5D bracketright */ + {278, 8, 2, 4, 0, -5}, /* 0x5E asciicircum */ + {280, 8, 1, 4, 0, -1}, /* 0x5F underscore */ + {281, 8, 2, 3, 0, -5}, /* 0x60 grave */ + {283, 8, 4, 4, 0, -4}, /* 0x61 a */ + {287, 8, 5, 4, 0, -5}, /* 0x62 b */ + {292, 8, 4, 4, 0, -4}, /* 0x63 c */ + {296, 8, 5, 4, 0, -5}, /* 0x64 d */ + {301, 8, 4, 4, 0, -4}, /* 0x65 e */ + {305, 8, 5, 4, 0, -5}, /* 0x66 f */ + {310, 8, 5, 4, 0, -4}, /* 0x67 g */ + {315, 8, 5, 4, 0, -5}, /* 0x68 h */ + {320, 8, 5, 2, 0, -5}, /* 0x69 i */ + {325, 8, 6, 4, 0, -5}, /* 0x6A j */ + {331, 8, 5, 4, 0, -5}, /* 0x6B k */ + {336, 8, 5, 4, 0, -5}, /* 0x6C l */ + {341, 8, 4, 4, 0, -4}, /* 0x6D m */ + {345, 8, 4, 4, 0, -4}, /* 0x6E n */ + {349, 8, 4, 4, 0, -4}, /* 0x6F o */ + {353, 8, 5, 4, 0, -4}, /* 0x70 p */ + {358, 8, 5, 4, 0, -4}, /* 0x71 q */ + {363, 8, 4, 4, 0, -4}, /* 0x72 r */ + {367, 8, 4, 4, 0, -4}, /* 0x73 s */ + {371, 8, 5, 4, 0, -5}, /* 0x74 t */ + {376, 8, 4, 4, 0, -4}, /* 0x75 u */ + {380, 8, 4, 4, 0, -4}, /* 0x76 v */ + {384, 8, 4, 4, 0, -4}, /* 0x77 w */ + {388, 8, 4, 4, 0, -4}, /* 0x78 x */ + {392, 8, 5, 4, 0, -4}, /* 0x79 y */ + {397, 8, 4, 4, 0, -4}, /* 0x7A z */ + {401, 8, 5, 4, 0, -5}, /* 0x7B braceleft */ + {406, 8, 5, 2, 0, -5}, /* 0x7C bar */ + {411, 8, 5, 4, 0, -5}, /* 0x7D braceright */ + {416, 8, 2, 4, 0, -5}, /* 0x7E asciitilde */ +#if (TOMTHUMB_USE_EXTENDED) + {418, 8, 5, 2, 0, -5}, /* 0xA1 exclamdown */ + {423, 8, 5, 4, 0, -5}, /* 0xA2 cent */ + {428, 8, 5, 4, 0, -5}, /* 0xA3 sterling */ + {433, 8, 5, 4, 0, -5}, /* 0xA4 currency */ + {438, 8, 5, 4, 0, -5}, /* 0xA5 yen */ + {443, 8, 5, 2, 0, -5}, /* 0xA6 brokenbar */ + {448, 8, 5, 4, 0, -5}, /* 0xA7 section */ + {453, 8, 1, 4, 0, -5}, /* 0xA8 dieresis */ + {454, 8, 3, 4, 0, -5}, /* 0xA9 copyright */ + {457, 8, 5, 4, 0, -5}, /* 0xAA ordfeminine */ + {462, 8, 3, 3, 0, -5}, /* 0xAB guillemotleft */ + {465, 8, 2, 4, 0, -4}, /* 0xAC logicalnot */ + {467, 8, 1, 3, 0, -3}, /* 0xAD softhyphen */ + {468, 8, 3, 4, 0, -5}, /* 0xAE registered */ + {471, 8, 1, 4, 0, -5}, /* 0xAF macron */ + {472, 8, 3, 4, 0, -5}, /* 0xB0 degree */ + {475, 8, 5, 4, 0, -5}, /* 0xB1 plusminus */ + {480, 8, 3, 4, 0, -5}, /* 0xB2 twosuperior */ + {483, 8, 3, 4, 0, -5}, /* 0xB3 threesuperior */ + {486, 8, 2, 3, 0, -5}, /* 0xB4 acute */ + {488, 8, 5, 4, 0, -5}, /* 0xB5 mu */ + {493, 8, 5, 4, 0, -5}, /* 0xB6 paragraph */ + {498, 8, 3, 4, 0, -4}, /* 0xB7 periodcentered */ + {501, 8, 3, 4, 0, -3}, /* 0xB8 cedilla */ + {504, 8, 3, 2, 0, -5}, /* 0xB9 onesuperior */ + {507, 8, 5, 4, 0, -5}, /* 0xBA ordmasculine */ + {512, 8, 3, 3, 0, -5}, /* 0xBB guillemotright */ + {515, 8, 5, 4, 0, -5}, /* 0xBC onequarter */ + {520, 8, 5, 4, 0, -5}, /* 0xBD onehalf */ + {525, 8, 5, 4, 0, -5}, /* 0xBE threequarters */ + {530, 8, 5, 4, 0, -5}, /* 0xBF questiondown */ + {535, 8, 5, 4, 0, -5}, /* 0xC0 Agrave */ + {540, 8, 5, 4, 0, -5}, /* 0xC1 Aacute */ + {545, 8, 5, 4, 0, -5}, /* 0xC2 Acircumflex */ + {550, 8, 5, 4, 0, -5}, /* 0xC3 Atilde */ + {555, 8, 5, 4, 0, -5}, /* 0xC4 Adieresis */ + {560, 8, 5, 4, 0, -5}, /* 0xC5 Aring */ + {565, 8, 5, 4, 0, -5}, /* 0xC6 AE */ + {570, 8, 6, 4, 0, -5}, /* 0xC7 Ccedilla */ + {576, 8, 5, 4, 0, -5}, /* 0xC8 Egrave */ + {581, 8, 5, 4, 0, -5}, /* 0xC9 Eacute */ + {586, 8, 5, 4, 0, -5}, /* 0xCA Ecircumflex */ + {591, 8, 5, 4, 0, -5}, /* 0xCB Edieresis */ + {596, 8, 5, 4, 0, -5}, /* 0xCC Igrave */ + {601, 8, 5, 4, 0, -5}, /* 0xCD Iacute */ + {606, 8, 5, 4, 0, -5}, /* 0xCE Icircumflex */ + {611, 8, 5, 4, 0, -5}, /* 0xCF Idieresis */ + {616, 8, 5, 4, 0, -5}, /* 0xD0 Eth */ + {621, 8, 5, 4, 0, -5}, /* 0xD1 Ntilde */ + {626, 8, 5, 4, 0, -5}, /* 0xD2 Ograve */ + {631, 8, 5, 4, 0, -5}, /* 0xD3 Oacute */ + {636, 8, 5, 4, 0, -5}, /* 0xD4 Ocircumflex */ + {641, 8, 5, 4, 0, -5}, /* 0xD5 Otilde */ + {646, 8, 5, 4, 0, -5}, /* 0xD6 Odieresis */ + {651, 8, 3, 4, 0, -4}, /* 0xD7 multiply */ + {654, 8, 5, 4, 0, -5}, /* 0xD8 Oslash */ + {659, 8, 5, 4, 0, -5}, /* 0xD9 Ugrave */ + {664, 8, 5, 4, 0, -5}, /* 0xDA Uacute */ + {669, 8, 5, 4, 0, -5}, /* 0xDB Ucircumflex */ + {674, 8, 5, 4, 0, -5}, /* 0xDC Udieresis */ + {679, 8, 5, 4, 0, -5}, /* 0xDD Yacute */ + {684, 8, 5, 4, 0, -5}, /* 0xDE Thorn */ + {689, 8, 6, 4, 0, -5}, /* 0xDF germandbls */ + {695, 8, 5, 4, 0, -5}, /* 0xE0 agrave */ + {700, 8, 5, 4, 0, -5}, /* 0xE1 aacute */ + {705, 8, 5, 4, 0, -5}, /* 0xE2 acircumflex */ + {710, 8, 5, 4, 0, -5}, /* 0xE3 atilde */ + {715, 8, 5, 4, 0, -5}, /* 0xE4 adieresis */ + {720, 8, 5, 4, 0, -5}, /* 0xE5 aring */ + {725, 8, 4, 4, 0, -4}, /* 0xE6 ae */ + {729, 8, 5, 4, 0, -4}, /* 0xE7 ccedilla */ + {734, 8, 5, 4, 0, -5}, /* 0xE8 egrave */ + {739, 8, 5, 4, 0, -5}, /* 0xE9 eacute */ + {744, 8, 5, 4, 0, -5}, /* 0xEA ecircumflex */ + {749, 8, 5, 4, 0, -5}, /* 0xEB edieresis */ + {754, 8, 5, 3, 0, -5}, /* 0xEC igrave */ + {759, 8, 5, 3, 0, -5}, /* 0xED iacute */ + {764, 8, 5, 4, 0, -5}, /* 0xEE icircumflex */ + {769, 8, 5, 4, 0, -5}, /* 0xEF idieresis */ + {774, 8, 5, 4, 0, -5}, /* 0xF0 eth */ + {779, 8, 5, 4, 0, -5}, /* 0xF1 ntilde */ + {784, 8, 5, 4, 0, -5}, /* 0xF2 ograve */ + {789, 8, 5, 4, 0, -5}, /* 0xF3 oacute */ + {794, 8, 5, 4, 0, -5}, /* 0xF4 ocircumflex */ + {799, 8, 5, 4, 0, -5}, /* 0xF5 otilde */ + {804, 8, 5, 4, 0, -5}, /* 0xF6 odieresis */ + {809, 8, 5, 4, 0, -5}, /* 0xF7 divide */ + {814, 8, 4, 4, 0, -4}, /* 0xF8 oslash */ + {818, 8, 5, 4, 0, -5}, /* 0xF9 ugrave */ + {823, 8, 5, 4, 0, -5}, /* 0xFA uacute */ + {828, 8, 5, 4, 0, -5}, /* 0xFB ucircumflex */ + {833, 8, 5, 4, 0, -5}, /* 0xFC udieresis */ + {838, 8, 6, 4, 0, -5}, /* 0xFD yacute */ + {844, 8, 5, 4, 0, -4}, /* 0xFE thorn */ + {849, 8, 6, 4, 0, -5}, /* 0xFF ydieresis */ + {855, 8, 1, 2, 0, -1}, /* 0x11D gcircumflex */ + {856, 8, 5, 4, 0, -5}, /* 0x152 OE */ + {861, 8, 4, 4, 0, -4}, /* 0x153 oe */ + {865, 8, 5, 4, 0, -5}, /* 0x160 Scaron */ + {870, 8, 5, 4, 0, -5}, /* 0x161 scaron */ + {875, 8, 5, 4, 0, -5}, /* 0x178 Ydieresis */ + {880, 8, 5, 4, 0, -5}, /* 0x17D Zcaron */ + {885, 8, 5, 4, 0, -5}, /* 0x17E zcaron */ + {890, 8, 1, 2, 0, -1}, /* 0xEA4 uni0EA4 */ + {891, 8, 1, 2, 0, -1}, /* 0x13A0 uni13A0 */ + {892, 8, 1, 2, 0, -3}, /* 0x2022 bullet */ + {893, 8, 1, 4, 0, -1}, /* 0x2026 ellipsis */ + {894, 8, 5, 4, 0, -5}, /* 0x20AC Euro */ + {899, 8, 5, 4, 0, -5}, /* 0xFFFD uniFFFD */ +#endif /* (TOMTHUMB_USE_EXTENDED) */ +}; + +const GFXfont TomThumb PROGMEM = {(uint8_t *)TomThumbBitmaps, + (GFXglyph *)TomThumbGlyphs, 0x20, 0x7E, 6}; diff --git a/PDQ_MinLib/org_01.h b/PDQ_MinLib/org_01.h new file mode 100644 index 0000000..eabbd92 --- /dev/null +++ b/PDQ_MinLib/org_01.h @@ -0,0 +1,128 @@ +// Org_v01 by Orgdot (www.orgdot.com/aliasfonts). A tiny, +// stylized font with all characters within a 6 pixel height. + +const uint8_t Org_01Bitmaps[] PROGMEM = { + 0xE8, 0xA0, 0x57, 0xD5, 0xF5, 0x00, 0xFD, 0x3E, 0x5F, 0x80, 0x88, 0x88, + 0x88, 0x80, 0xF4, 0xBF, 0x2E, 0x80, 0x80, 0x6A, 0x40, 0x95, 0x80, 0xAA, + 0x80, 0x5D, 0x00, 0xC0, 0xF0, 0x80, 0x08, 0x88, 0x88, 0x00, 0xFC, 0x63, + 0x1F, 0x80, 0xF8, 0xF8, 0x7F, 0x0F, 0x80, 0xF8, 0x7E, 0x1F, 0x80, 0x8C, + 0x7E, 0x10, 0x80, 0xFC, 0x3E, 0x1F, 0x80, 0xFC, 0x3F, 0x1F, 0x80, 0xF8, + 0x42, 0x10, 0x80, 0xFC, 0x7F, 0x1F, 0x80, 0xFC, 0x7E, 0x1F, 0x80, 0x90, + 0xB0, 0x2A, 0x22, 0xF0, 0xF0, 0x88, 0xA8, 0xF8, 0x4E, 0x02, 0x00, 0xFD, + 0x6F, 0x0F, 0x80, 0xFC, 0x7F, 0x18, 0x80, 0xF4, 0x7D, 0x1F, 0x00, 0xFC, + 0x21, 0x0F, 0x80, 0xF4, 0x63, 0x1F, 0x00, 0xFC, 0x3F, 0x0F, 0x80, 0xFC, + 0x3F, 0x08, 0x00, 0xFC, 0x2F, 0x1F, 0x80, 0x8C, 0x7F, 0x18, 0x80, 0xF9, + 0x08, 0x4F, 0x80, 0x78, 0x85, 0x2F, 0x80, 0x8D, 0xB1, 0x68, 0x80, 0x84, + 0x21, 0x0F, 0x80, 0xFD, 0x6B, 0x5A, 0x80, 0xFC, 0x63, 0x18, 0x80, 0xFC, + 0x63, 0x1F, 0x80, 0xFC, 0x7F, 0x08, 0x00, 0xFC, 0x63, 0x3F, 0x80, 0xFC, + 0x7F, 0x29, 0x00, 0xFC, 0x3E, 0x1F, 0x80, 0xF9, 0x08, 0x42, 0x00, 0x8C, + 0x63, 0x1F, 0x80, 0x8C, 0x62, 0xA2, 0x00, 0xAD, 0x6B, 0x5F, 0x80, 0x8A, + 0x88, 0xA8, 0x80, 0x8C, 0x54, 0x42, 0x00, 0xF8, 0x7F, 0x0F, 0x80, 0xEA, + 0xC0, 0x82, 0x08, 0x20, 0x80, 0xD5, 0xC0, 0x54, 0xF8, 0x80, 0xF1, 0xFF, + 0x8F, 0x99, 0xF0, 0xF8, 0x8F, 0x1F, 0x99, 0xF0, 0xFF, 0x8F, 0x6B, 0xA4, + 0xF9, 0x9F, 0x10, 0x8F, 0x99, 0x90, 0xF0, 0x55, 0xC0, 0x8A, 0xF9, 0x90, + 0xF8, 0xFD, 0x63, 0x10, 0xF9, 0x99, 0xF9, 0x9F, 0xF9, 0x9F, 0x80, 0xF9, + 0x9F, 0x20, 0xF8, 0x88, 0x47, 0x1F, 0x27, 0xC8, 0x42, 0x00, 0x99, 0x9F, + 0x99, 0x97, 0x8C, 0x6B, 0xF0, 0x96, 0x69, 0x99, 0x9F, 0x10, 0x2E, 0x8F, + 0x2B, 0x22, 0xF8, 0x89, 0xA8, 0x0F, 0xE0}; + +const GFXglyph Org_01Glyphs[] PROGMEM = {{0, 0, 0, 6, 0, 1}, // 0x20 ' ' + {0, 1, 5, 2, 0, -4}, // 0x21 '!' + {1, 3, 1, 4, 0, -4}, // 0x22 '"' + {2, 5, 5, 6, 0, -4}, // 0x23 '#' + {6, 5, 5, 6, 0, -4}, // 0x24 '$' + {10, 5, 5, 6, 0, -4}, // 0x25 '%' + {14, 5, 5, 6, 0, -4}, // 0x26 '&' + {18, 1, 1, 2, 0, -4}, // 0x27 ''' + {19, 2, 5, 3, 0, -4}, // 0x28 '(' + {21, 2, 5, 3, 0, -4}, // 0x29 ')' + {23, 3, 3, 4, 0, -3}, // 0x2A '*' + {25, 3, 3, 4, 0, -3}, // 0x2B '+' + {27, 1, 2, 2, 0, 0}, // 0x2C ',' + {28, 4, 1, 5, 0, -2}, // 0x2D '-' + {29, 1, 1, 2, 0, 0}, // 0x2E '.' + {30, 5, 5, 6, 0, -4}, // 0x2F '/' + {34, 5, 5, 6, 0, -4}, // 0x30 '0' + {38, 1, 5, 2, 0, -4}, // 0x31 '1' + {39, 5, 5, 6, 0, -4}, // 0x32 '2' + {43, 5, 5, 6, 0, -4}, // 0x33 '3' + {47, 5, 5, 6, 0, -4}, // 0x34 '4' + {51, 5, 5, 6, 0, -4}, // 0x35 '5' + {55, 5, 5, 6, 0, -4}, // 0x36 '6' + {59, 5, 5, 6, 0, -4}, // 0x37 '7' + {63, 5, 5, 6, 0, -4}, // 0x38 '8' + {67, 5, 5, 6, 0, -4}, // 0x39 '9' + {71, 1, 4, 2, 0, -3}, // 0x3A ':' + {72, 1, 4, 2, 0, -3}, // 0x3B ';' + {73, 3, 5, 4, 0, -4}, // 0x3C '<' + {75, 4, 3, 5, 0, -3}, // 0x3D '=' + {77, 3, 5, 4, 0, -4}, // 0x3E '>' + {79, 5, 5, 6, 0, -4}, // 0x3F '?' + {83, 5, 5, 6, 0, -4}, // 0x40 '@' + {87, 5, 5, 6, 0, -4}, // 0x41 'A' + {91, 5, 5, 6, 0, -4}, // 0x42 'B' + {95, 5, 5, 6, 0, -4}, // 0x43 'C' + {99, 5, 5, 6, 0, -4}, // 0x44 'D' + {103, 5, 5, 6, 0, -4}, // 0x45 'E' + {107, 5, 5, 6, 0, -4}, // 0x46 'F' + {111, 5, 5, 6, 0, -4}, // 0x47 'G' + {115, 5, 5, 6, 0, -4}, // 0x48 'H' + {119, 5, 5, 6, 0, -4}, // 0x49 'I' + {123, 5, 5, 6, 0, -4}, // 0x4A 'J' + {127, 5, 5, 6, 0, -4}, // 0x4B 'K' + {131, 5, 5, 6, 0, -4}, // 0x4C 'L' + {135, 5, 5, 6, 0, -4}, // 0x4D 'M' + {139, 5, 5, 6, 0, -4}, // 0x4E 'N' + {143, 5, 5, 6, 0, -4}, // 0x4F 'O' + {147, 5, 5, 6, 0, -4}, // 0x50 'P' + {151, 5, 5, 6, 0, -4}, // 0x51 'Q' + {155, 5, 5, 6, 0, -4}, // 0x52 'R' + {159, 5, 5, 6, 0, -4}, // 0x53 'S' + {163, 5, 5, 6, 0, -4}, // 0x54 'T' + {167, 5, 5, 6, 0, -4}, // 0x55 'U' + {171, 5, 5, 6, 0, -4}, // 0x56 'V' + {175, 5, 5, 6, 0, -4}, // 0x57 'W' + {179, 5, 5, 6, 0, -4}, // 0x58 'X' + {183, 5, 5, 6, 0, -4}, // 0x59 'Y' + {187, 5, 5, 6, 0, -4}, // 0x5A 'Z' + {191, 2, 5, 3, 0, -4}, // 0x5B '[' + {193, 5, 5, 6, 0, -4}, // 0x5C '\' + {197, 2, 5, 3, 0, -4}, // 0x5D ']' + {199, 3, 2, 4, 0, -4}, // 0x5E '^' + {200, 5, 1, 6, 0, 1}, // 0x5F '_' + {201, 1, 1, 2, 0, -4}, // 0x60 '`' + {202, 4, 4, 5, 0, -3}, // 0x61 'a' + {204, 4, 5, 5, 0, -4}, // 0x62 'b' + {207, 4, 4, 5, 0, -3}, // 0x63 'c' + {209, 4, 5, 5, 0, -4}, // 0x64 'd' + {212, 4, 4, 5, 0, -3}, // 0x65 'e' + {214, 3, 5, 4, 0, -4}, // 0x66 'f' + {216, 4, 5, 5, 0, -3}, // 0x67 'g' + {219, 4, 5, 5, 0, -4}, // 0x68 'h' + {222, 1, 4, 2, 0, -3}, // 0x69 'i' + {223, 2, 5, 3, 0, -3}, // 0x6A 'j' + {225, 4, 5, 5, 0, -4}, // 0x6B 'k' + {228, 1, 5, 2, 0, -4}, // 0x6C 'l' + {229, 5, 4, 6, 0, -3}, // 0x6D 'm' + {232, 4, 4, 5, 0, -3}, // 0x6E 'n' + {234, 4, 4, 5, 0, -3}, // 0x6F 'o' + {236, 4, 5, 5, 0, -3}, // 0x70 'p' + {239, 4, 5, 5, 0, -3}, // 0x71 'q' + {242, 4, 4, 5, 0, -3}, // 0x72 'r' + {244, 4, 4, 5, 0, -3}, // 0x73 's' + {246, 5, 5, 6, 0, -4}, // 0x74 't' + {250, 4, 4, 5, 0, -3}, // 0x75 'u' + {252, 4, 4, 5, 0, -3}, // 0x76 'v' + {254, 5, 4, 6, 0, -3}, // 0x77 'w' + {257, 4, 4, 5, 0, -3}, // 0x78 'x' + {259, 4, 5, 5, 0, -3}, // 0x79 'y' + {262, 4, 4, 5, 0, -3}, // 0x7A 'z' + {264, 3, 5, 4, 0, -4}, // 0x7B '{' + {266, 1, 5, 2, 0, -4}, // 0x7C '|' + {267, 3, 5, 4, 0, -4}, // 0x7D '}' + {269, 5, 3, 6, 0, -3}}; // 0x7E '~' + +const GFXfont Org_01 PROGMEM = {(uint8_t *)Org_01Bitmaps, + (GFXglyph *)Org_01Glyphs, 0x20, 0x7E, 7}; + +// Approx. 943 bytes diff --git a/nano_font.cpp b/nano_font.cpp index d4651aa..67fe89b 100644 --- a/nano_font.cpp +++ b/nano_font.cpp @@ -2,7 +2,11 @@ #include //#include "PDQ_MinLib/FreeSansBold9pt7b.h" -#include "PDQ_MinLib/Picopixel.h" +//#include "PDQ_MinLib/Picopixel.h" +//#include "PDQ_MinLib/org_01.h" +#include "PDQ_MinLib/TomThumb.h" //const GFXfont* ubitx_font = &FreeSansBold9pt7b; -const GFXfont* ubitx_font = &Picopixel; \ No newline at end of file +//const GFXfont* ubitx_font = &Picopixel; +//const GFXfont* ubitx_font = &Org_01; +const GFXfont* ubitx_font = &TomThumb; diff --git a/nano_gui.cpp b/nano_gui.cpp index f8960c2..ebd15da 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -34,7 +34,7 @@ void displayInit(void){ tft.setFont(ubitx_font); tft.setTextWrap(true); tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK); - tft.setTextSize(4); + tft.setTextSize(3); tft.setRotation(1); } From 91776fdcc7ee0d939c57e880a82742a192ac6eca Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 11:33:17 -0700 Subject: [PATCH 243/324] Clean up pin descriptions a bit --- pin_definitions.h | 67 ++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 35 deletions(-) diff --git a/pin_definitions.h b/pin_definitions.h index 96356d4..18e7dce 100644 --- a/pin_definitions.h +++ b/pin_definitions.h @@ -1,52 +1,49 @@ #pragma once -/* The ubitx is powered by an arduino nano. The pin assignment is as folows - * +/* + * Pin configurations for uBiTXv6 + * + * Attached devices are: + * * A rotory encoder for tuning, which has a built-in push button for selection + * * A Push-to-talk button input + * * A morse keyer input, using analog voltage divider for paddle support + * * A SI5351A 3-output frequency generator + * * A model tjctm24028-spi touch screen LCD, which has: + * * An ILI9341 display controller + * * A XPT2046 touch controller + * * A TX/RX output control pin + * * A tone output pin to provide audio feedback to the operator when sending CW + * * Three filter selection output control pins + * * A CW keydown output + * * Optionally, a serial CAT interface */ static const uint8_t PIN_ENC_A = A0; // Tuning encoder interface static const uint8_t PIN_ENC_B = A1; // Tuning encoder interface static const uint8_t PIN_ENC_PUSH_BUTTON = A2; // Tuning encoder interface static const uint8_t PIN_PTT = A3; // Sense it for ssb and as a straight key for cw operation +//A4 is I2C SDA +//A5 is I2C SCK static const uint8_t PIN_ANALOG_KEYER = A6; // This is used as keyer. The analog port has 4.7K pull up resistor. Details are in the circuit description on www.hfsignals.com static const uint8_t PIN_ANALOG_SPARE = A7; // Not used yet -static const uint8_t PIN_TX_RXn = 7; // Pin from the Nano to the radio to switch to TX (HIGH) and RX(LOW) -static const uint8_t PIN_CW_TONE = 6; // Generates a square wave sidetone while sending the CW. -static const uint8_t PIN_TX_LPF_A = 5; // The 30 MHz LPF is permanently connected in the output of the PA... +//13 is SPI CLK +//12 is SPI MISO +//11 is SPI MOSI +static const uint8_t PIN_TFT_CS = 10; // Selects the LCD controller on SPI interface (active low) +static const uint8_t PIN_TFT_DC = 9; // Tells the LCD controller if it's getting data (D, high) or commands (C, low) +static const uint8_t PIN_TOUCH_CS = 8; // Selects the touch controller on SPI interface (active low) +static const uint8_t PIN_TX_RXn = 7; // Pin from the Nano to the radio to switch to TX (HIGH) and RX(LOW) +static const uint8_t PIN_CW_TONE = 6; // Generates a square wave sidetone while sending the CW +static const uint8_t PIN_TX_LPF_A = 5; // The 30 MHz LPF is permanently connected in the output of the PA... static const uint8_t PIN_TX_LPF_B = 4; // ...Alternatively, either 3.5 MHz, 7 MHz or 14 Mhz LPFs are... static const uint8_t PIN_TX_LPF_C = 3; // ...switched inline depending upon the TX frequency -static const uint8_t PIN_CW_KEY = 2; // Pin goes high during CW keydown to transmit the carrier. - // ... The PIN_CW_KEY is needed in addition to the TX/RX key as the... - // ...key can be up within a tx period - - -/** pin assignments -14 T_IRQ 2 std changed -13 T_DOUT (parallel to SOD/MOSI, pin 9 of display) -12 T_DIN (parallel to SDI/MISO, pin 6 of display) -11 T_CS 9 (we need to specify this) -10 T_CLK (parallel to SCK, pin 7 of display) -9 SDO(MSIO) 12 12 (spi) -8 LED A0 8 (not needed, permanently on +3.3v) (resistor from 5v, -7 SCK 13 13 (spi) -6 SDI 11 11 (spi) -5 D/C A3 7 (changable) -4 RESET A4 9 (not needed, permanently +5v) -3 CS A5 10 (changable) -2 GND GND -1 VCC VCC - -The model is called tjctm24028-spi -it uses an ILI9341 display controller and an XPT2046 touch controller. -*/ - -static const uint8_t PIN_TFT_DC = 9; -static const uint8_t PIN_TFT_CS = 10; -static const uint8_t PIN_TOUCH_CS = 8; //this is the pin to select the touch controller on spi interface +static const uint8_t PIN_CW_KEY = 2; // Pin goes high during CW keydown to transmit the carrier. + // ... The PIN_CW_KEY is needed in addition to the TX/RX key as the... + // ...key can be up within a tx period +//1 is UART RX +//0 is UART TX int enc_read(void); // returns the number of ticks in a short interval, +ve in clockwise, -ve in anti-clockwise void enc_setup(void); // Setups up initial values and interrupts. int btnDown(); //returns true if the encoder button is pressed - - From 5596c0c8abb9abf4a8f0f3b0aeaa3f30a411cdb7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 11:47:11 -0700 Subject: [PATCH 244/324] Remove function declarations from pin definition file --- morse.cpp | 1 + pin_definitions.h | 4 ---- push_button.cpp | 10 ++++++++++ push_button.h | 3 +++ setup.cpp | 1 + tmp.cpp | 9 --------- ubitxv6.ino | 10 ++++++---- 7 files changed, 21 insertions(+), 17 deletions(-) create mode 100644 push_button.cpp create mode 100644 push_button.h diff --git a/morse.cpp b/morse.cpp index b1d5586..b8c2b20 100644 --- a/morse.cpp +++ b/morse.cpp @@ -1,5 +1,6 @@ #include //tone +#include "encoder.h" #include "morse.h" #include "pin_definitions.h" #include "settings.h" diff --git a/pin_definitions.h b/pin_definitions.h index 18e7dce..a1521ad 100644 --- a/pin_definitions.h +++ b/pin_definitions.h @@ -43,7 +43,3 @@ static const uint8_t PIN_CW_KEY = 2; // Pin goes high during CW keydow // ...key can be up within a tx period //1 is UART RX //0 is UART TX - -int enc_read(void); // returns the number of ticks in a short interval, +ve in clockwise, -ve in anti-clockwise -void enc_setup(void); // Setups up initial values and interrupts. -int btnDown(); //returns true if the encoder button is pressed diff --git a/push_button.cpp b/push_button.cpp new file mode 100644 index 0000000..41f8457 --- /dev/null +++ b/push_button.cpp @@ -0,0 +1,10 @@ +#include +#include "pin_definitions.h" +#include "push_button.h" + +bool IsButtonPressed() +{ + //Button has a pullup, so it reads high normally, + //and reads low when pressed down + return !digitalRead(PIN_ENC_PUSH_BUTTON); +} diff --git a/push_button.h b/push_button.h new file mode 100644 index 0000000..27ff54f --- /dev/null +++ b/push_button.h @@ -0,0 +1,3 @@ +#pragma once + +bool IsButtonPressed(); //returns true if the encoder button is pressed diff --git a/setup.cpp b/setup.cpp index 679f127..6c7a0f4 100644 --- a/setup.cpp +++ b/setup.cpp @@ -1,5 +1,6 @@ #include #include "colors.h" +#include "encoder.h" #include "menu.h" #include "morse.h" #include "nano_gui.h" diff --git a/tmp.cpp b/tmp.cpp index 2c0d556..1adaa49 100644 --- a/tmp.cpp +++ b/tmp.cpp @@ -1,12 +1,3 @@ -#include -#include "pin_definitions.h" - void updateDisplay() {} void redrawVFOs(){} void drawTx(){} -int btnDown() -{ - //Button has a pullup, so it reads high normally, - //and reads low when pressed down - return !digitalRead(PIN_ENC_PUSH_BUTTON); -} \ No newline at end of file diff --git a/ubitxv6.ino b/ubitxv6.ino index 075ef9d..a152ad3 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -31,10 +31,12 @@ */ #include #include "button_timing.h" +#include "encoder.h" #include "menu.h" #include "menu_main.h" #include "morse.h" #include "pin_definitions.h" +#include "push_button.h" #include "nano_gui.h" #include "settings.h" #include "setup.h" @@ -86,16 +88,16 @@ void checkPTT(){ //check if the encoder button was pressed ButtonPress_e checkButton(){ - if (!btnDown()){ + if (!IsButtonPressed()){ return ButtonPress_e::NotPressed; } delay(DEBOUNCE_DELAY_MS); - if (!btnDown()){//debounce + if (!IsButtonPressed()){//debounce return ButtonPress_e::NotPressed; } uint16_t down_time = 0; - while(btnDown() && (down_time < LONG_PRESS_TIME_MS)){ + while(IsButtonPressed() && (down_time < LONG_PRESS_TIME_MS)){ delay(LONG_PRESS_POLL_TIME_MS); down_time += LONG_PRESS_POLL_TIME_MS; } @@ -165,7 +167,7 @@ void setup() setFrequency(globalSettings.vfoA.frequency); //Run initial calibration routine if button is pressed during power up - if(btnDown()){ + if(IsButtonPressed()){ LoadDefaultSettings(); setupTouch(); SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); From 8af59b0a851a9102e764eded4964a0fbc2099d60 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 12:00:19 -0700 Subject: [PATCH 245/324] Move button pressing logic to it's own file --- button_press_e.h | 7 +++++++ menu.h | 7 +------ push_button.cpp | 24 ++++++++++++++++++++++++ push_button.h | 4 +++- ubitxv6.ino | 29 ++--------------------------- 5 files changed, 37 insertions(+), 34 deletions(-) create mode 100644 button_press_e.h diff --git a/button_press_e.h b/button_press_e.h new file mode 100644 index 0000000..9147d4b --- /dev/null +++ b/button_press_e.h @@ -0,0 +1,7 @@ +#pragma once + +enum ButtonPress_e : uint8_t { + NotPressed, + ShortPress, + LongPress +}; diff --git a/menu.h b/menu.h index 82a755e..ef46054 100644 --- a/menu.h +++ b/menu.h @@ -1,6 +1,7 @@ #pragma once #include +#include "button_press_e.h" #include "point.h" enum MenuReturn_e : uint8_t { @@ -9,12 +10,6 @@ enum MenuReturn_e : uint8_t { ExitedNoRedraw }; -enum ButtonPress_e : uint8_t { - NotPressed, - ShortPress, - LongPress -}; - struct Menu_t { void (*const initMenu)();//Any initial draw routines or state initialization MenuReturn_e (*const runMenu)(const ButtonPress_e tuner_button, diff --git a/push_button.cpp b/push_button.cpp index 41f8457..fb34813 100644 --- a/push_button.cpp +++ b/push_button.cpp @@ -1,4 +1,5 @@ #include +#include "button_timing.h" #include "pin_definitions.h" #include "push_button.h" @@ -8,3 +9,26 @@ bool IsButtonPressed() //and reads low when pressed down return !digitalRead(PIN_ENC_PUSH_BUTTON); } + +ButtonPress_e CheckTunerButton(){ + if (!IsButtonPressed()){ + return ButtonPress_e::NotPressed; + } + delay(DEBOUNCE_DELAY_MS); + if (!IsButtonPressed()){//debounce + return ButtonPress_e::NotPressed; + } + + uint16_t down_time = 0; + while(IsButtonPressed() && (down_time < LONG_PRESS_TIME_MS)){ + delay(LONG_PRESS_POLL_TIME_MS); + down_time += LONG_PRESS_POLL_TIME_MS; + } + + if(down_time < LONG_PRESS_TIME_MS){ + return ButtonPress_e::ShortPress; + } + else{ + return ButtonPress_e::LongPress; + } +} diff --git a/push_button.h b/push_button.h index 27ff54f..c83a173 100644 --- a/push_button.h +++ b/push_button.h @@ -1,3 +1,5 @@ #pragma once -bool IsButtonPressed(); //returns true if the encoder button is pressed +#include "button_press_e.h" + +ButtonPress_e CheckTunerButton(); diff --git a/ubitxv6.ino b/ubitxv6.ino index a152ad3..f3d1594 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -30,7 +30,6 @@ * Si5351 object to control the clocks. */ #include -#include "button_timing.h" #include "encoder.h" #include "menu.h" #include "menu_main.h" @@ -86,30 +85,6 @@ void checkPTT(){ stopTx(); } -//check if the encoder button was pressed -ButtonPress_e checkButton(){ - if (!IsButtonPressed()){ - return ButtonPress_e::NotPressed; - } - delay(DEBOUNCE_DELAY_MS); - if (!IsButtonPressed()){//debounce - return ButtonPress_e::NotPressed; - } - - uint16_t down_time = 0; - while(IsButtonPressed() && (down_time < LONG_PRESS_TIME_MS)){ - delay(LONG_PRESS_POLL_TIME_MS); - down_time += LONG_PRESS_POLL_TIME_MS; - } - - if(down_time < LONG_PRESS_TIME_MS){ - return ButtonPress_e::ShortPress; - } - else{ - return ButtonPress_e::LongPress; - } -} - /** * The settings are read from EEPROM. The first time around, the values may not be * present or out of range, in this case, some intelligent defaults are copied into the @@ -167,7 +142,7 @@ void setup() setFrequency(globalSettings.vfoA.frequency); //Run initial calibration routine if button is pressed during power up - if(IsButtonPressed()){ + if(ButtonPress_e::NotPressed != CheckTunerButton()){ LoadDefaultSettings(); setupTouch(); SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); @@ -201,7 +176,7 @@ void loop(){ return; } - ButtonPress_e tuner_button = checkButton(); + ButtonPress_e tuner_button = CheckTunerButton(); Point touch_point; ButtonPress_e touch_button = checkTouch(&touch_point); int16_t knob = enc_read(); From f66a173dbebfc7aef5e6a566299cbb9fa8413ca4 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 12:10:25 -0700 Subject: [PATCH 246/324] Get LSB and USB buttons to update properly --- menu_main.cpp | 2 ++ menu_main_buttons.cpp | 5 +++++ menu_main_buttons.h | 1 + 3 files changed, 8 insertions(+) diff --git a/menu_main.cpp b/menu_main.cpp index 0c15cd0..7860050 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -59,11 +59,13 @@ void mainMenuTune(int16_t knob) //Transition from below to above the traditional threshold for USB if(current_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + updateSidebandButtons(); } //Transition from above to below the traditional threshold for USB if(current_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + updateSidebandButtons(); } setFrequency(new_freq); diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 590fcca..0ea15a6 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -451,6 +451,11 @@ void osSidebandMode(VfoMode_e mode){ drawButton(&button); } +void updateSidebandButtons() +{ + osSidebandMode(GetActiveVfoMode()); +} + ButtonStatus_e bsUsb(){ return (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 91df8fa..0e7febd 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -10,3 +10,4 @@ extern const uint8_t MAIN_MENU_NUM_BUTTONS; extern const Button bVfoA; extern const Button bVfoB; void updateBandButtons(const uint32_t old_freq); +void updateSidebandButtons(); From 0f45a2fc43ad1ab9617356b8e7089925e0c8bc46 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 12:17:15 -0700 Subject: [PATCH 247/324] Fix out-of-band midpoint selection --- bands.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bands.cpp b/bands.cpp index 353e7a5..c9f04ad 100644 --- a/bands.cpp +++ b/bands.cpp @@ -94,7 +94,7 @@ uint32_t getFreqInBand(const uint32_t frequency, //We're not in a known band - just go to the center of the target band Band_t band; memcpy_P(&band,&bands[target_band_index],sizeof(band)); - return ((band.max - band.min)/2/100)*100;//truncated 100Hz + return band.min + ((band.max - band.min)/2/100)*100;//midpoint truncated to 100Hz resolution } else{ //We're in a known band. Match the relative position in the target band. From fdd2afce982557f4d0f2eb85276e2b49f5fc9367 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 12:35:59 -0700 Subject: [PATCH 248/324] Fix auto-selection of sideband mode when tuning --- menu_main.cpp | 13 +++---------- menu_main_buttons.cpp | 3 +++ tuner.cpp | 27 ++++++++++++++++++++++----- tuner.h | 3 +-- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 7860050..8eb010b 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -56,19 +56,12 @@ void mainMenuTune(int16_t knob) current_freq = GetActiveVfoFreq(); const uint32_t new_freq = current_freq + (50 * knob); - //Transition from below to above the traditional threshold for USB - if(current_freq < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); - updateSidebandButtons(); - } - - //Transition from above to below the traditional threshold for USB - if(current_freq >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + setFrequency(new_freq); + + if(autoSelectSidebandChanged(current_freq)){ updateSidebandButtons(); } - setFrequency(new_freq); const uint32_t old_freq = current_freq; current_freq = new_freq; diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 0ea15a6..75fcd89 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -514,6 +514,9 @@ ButtonStatus_e bsBand(const uint8_t band){ void osBand(const uint8_t band){ const uint32_t old_freq = GetActiveVfoFreq(); SetActiveVfoFreq(getFreqInBand(old_freq,band)); + if(autoSelectSidebandChanged(old_freq)){ + updateSidebandButtons(); + } Button button; if(Vfo_e::VFO_A == globalSettings.activeVfo){ diff --git a/tuner.cpp b/tuner.cpp index 0bebb98..c9e7a11 100644 --- a/tuner.cpp +++ b/tuner.cpp @@ -5,10 +5,7 @@ #include "nano_gui.h" #include "pin_definitions.h" -/** - * Below are the basic functions that control the uBitx. Understanding the functions before - * you start hacking around - */ +static const uint32_t THRESHOLD_USB_LSB = 10000000L; void saveVFOs() { @@ -198,4 +195,24 @@ void ritDisable(){ setFrequency(globalSettings.ritFrequency); updateDisplay(); } -} \ No newline at end of file +} + +bool autoSelectSidebandChanged(const uint32_t old_frequency) +{ + const uint32_t new_freq = GetActiveVfoFreq(); + //Transition from below to above the traditional threshold for USB + if(old_frequency < THRESHOLD_USB_LSB && new_freq >= THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + setFrequency(new_freq);//Refresh tuning to activate the new sideband mode + return true; + } + + //Transition from above to below the traditional threshold for USB + if(old_frequency >= THRESHOLD_USB_LSB && new_freq < THRESHOLD_USB_LSB){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + setFrequency(new_freq);//Refresh tuning to activate the new sideband mode + return true; + } + + return false; +} diff --git a/tuner.h b/tuner.h index dc4cf27..2414aaf 100644 --- a/tuner.h +++ b/tuner.h @@ -18,5 +18,4 @@ void si5351bx_setfreq(uint8_t clknum, uint32_t fout); void initOscillators(); void si5351_set_calibration(int32_t cal); //calibration is a small value that is nudged to make up for the inaccuracies of the reference 25 MHz crystal frequency -// limits the tuning and working range of the ubitx between 3 MHz and 30 MHz -static const uint32_t THRESHOLD_USB_LSB = 10000000L; +bool autoSelectSidebandChanged(const uint32_t old_frequency); //if the current frequency defaults to a different sideband mode, updates to that sideband mode and returns true. Else, returns false From 2db9899d4d4b856f75ae7eadc580f05d35eb1c02 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 14:31:59 -0700 Subject: [PATCH 249/324] Move SI5351 driver stuff into it's own header --- setup.cpp | 1 + ubitx_si5351.cpp => si5351.cpp | 0 si5351.h | 5 +++++ tuner.cpp | 1 + tuner.h | 6 ------ ubitxv6.ino | 1 + 6 files changed, 8 insertions(+), 6 deletions(-) rename ubitx_si5351.cpp => si5351.cpp (100%) create mode 100644 si5351.h diff --git a/setup.cpp b/setup.cpp index 6c7a0f4..938453a 100644 --- a/setup.cpp +++ b/setup.cpp @@ -8,6 +8,7 @@ #include "scratch_space.h" #include "setup.h" #include "settings.h" +#include "si5351.h" #include "tuner.h" #include "utils.h" diff --git a/ubitx_si5351.cpp b/si5351.cpp similarity index 100% rename from ubitx_si5351.cpp rename to si5351.cpp diff --git a/si5351.h b/si5351.h new file mode 100644 index 0000000..2a9d38e --- /dev/null +++ b/si5351.h @@ -0,0 +1,5 @@ +#pragma once + +void initOscillators(); +void si5351bx_setfreq(uint8_t clknum, uint32_t fout); +void si5351_set_calibration(int32_t cal); //calibration is a small value that is nudged to make up for the inaccuracies of the reference 25 MHz crystal frequency diff --git a/tuner.cpp b/tuner.cpp index c9e7a11..1eb3724 100644 --- a/tuner.cpp +++ b/tuner.cpp @@ -4,6 +4,7 @@ #include "nano_gui.h" #include "pin_definitions.h" +#include "si5351.h" static const uint32_t THRESHOLD_USB_LSB = 10000000L; diff --git a/tuner.h b/tuner.h index 2414aaf..cce5e97 100644 --- a/tuner.h +++ b/tuner.h @@ -2,7 +2,6 @@ #include "settings.h" -/* these are functions implemented in the main file named as ubitx_xxx.ino */ void saveVFOs(); void setFrequency(const unsigned long freq, const bool transmit = false); void startTx(TuningMode_e tx_mode); @@ -13,9 +12,4 @@ void checkCAT(); void cwKeyer(void); void switchVFO(Vfo_e vfoSelect); -/* these are functiosn implemented in ubitx_si5351.cpp */ -void si5351bx_setfreq(uint8_t clknum, uint32_t fout); -void initOscillators(); -void si5351_set_calibration(int32_t cal); //calibration is a small value that is nudged to make up for the inaccuracies of the reference 25 MHz crystal frequency - bool autoSelectSidebandChanged(const uint32_t old_frequency); //if the current frequency defaults to a different sideband mode, updates to that sideband mode and returns true. Else, returns false diff --git a/ubitxv6.ino b/ubitxv6.ino index f3d1594..38f4da4 100644 --- a/ubitxv6.ino +++ b/ubitxv6.ino @@ -39,6 +39,7 @@ #include "nano_gui.h" #include "settings.h" #include "setup.h" +#include "si5351.h" #include "touch.h" #include "tuner.h" #include "ui_touch.h" From 1f97be3263bf766f52292287939c6b1a3bfc6b6d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 19:46:36 -0700 Subject: [PATCH 250/324] Rough pass at button grids --- button.cpp | 44 ------------ button.h | 20 ------ button_grid.cpp | 90 ++++++++++++++++++++++++ button_grid.h | 33 +++++++++ menu_main.cpp | 32 ++++----- menu_main_buttons.cpp | 149 ++++++++++++--------------------------- menu_main_buttons.h | 8 +-- menu_numpad.cpp | 31 ++++----- menu_numpad_buttons.cpp | 60 +++++++--------- menu_numpad_buttons.h | 5 +- menu_utils.cpp | 151 +++++++++++++++++++++++++++++----------- menu_utils.h | 18 +++-- 12 files changed, 345 insertions(+), 296 deletions(-) delete mode 100644 button.cpp delete mode 100644 button.h create mode 100644 button_grid.cpp create mode 100644 button_grid.h diff --git a/button.cpp b/button.cpp deleted file mode 100644 index ac221ac..0000000 --- a/button.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include "button.h" - -#include - -#include "color_theme.h" -#include "nano_gui.h" -#include "scratch_space.h" - -void drawButton(Button* button) -{ - uint16_t tc = COLOR_INACTIVE_TEXT; - uint16_t bgc = COLOR_INACTIVE_BACKGROUND; - const uint16_t bdc = COLOR_INACTIVE_BORDER; - switch(button->status()) - { - case ButtonStatus_e::Stateless://Fallthrough intended - case ButtonStatus_e::Inactive://Fallthrough intended - default: - { - //Colors are initialized for this, so we're done - break; - } - case ButtonStatus_e::Active: - { - tc = COLOR_ACTIVE_TEXT; - bgc = COLOR_ACTIVE_BACKGROUND; - break; - } - } - - - if(nullptr != button->text){ - strncpy_P(b,button->text,sizeof(b)); - } - else if(nullptr != button->text_override){ - button->text_override(b,sizeof(b)); - } - else{ - //Something's messed up - //Serial.println(F("No text for button!")); - return; - } - displayText(b, button->x, button->y, button->w, button->h, tc, bgc, bdc); -} diff --git a/button.h b/button.h deleted file mode 100644 index 6aba532..0000000 --- a/button.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include - -enum ButtonStatus_e : uint8_t { - Stateless, - Inactive, - Active -}; - -struct Button { - int16_t x, y, w, h; - const char* text;//nullptr if text_override should be used - void (*text_override)(char* text_out, const uint16_t max_text_size);//nullptr if text should be used - ButtonStatus_e (*status)();//Used for coloring and morse menu - void (*on_select)();//Action to take when selected - char morse; -}; - -void drawButton(Button* button); diff --git a/button_grid.cpp b/button_grid.cpp new file mode 100644 index 0000000..337621c --- /dev/null +++ b/button_grid.cpp @@ -0,0 +1,90 @@ +#include "button_grid.h" + +#include +#include + +#include "color_theme.h" +#include "nano_gui.h" +#include "scratch_space.h" + +void drawButton(const ButtonGrid_t *const button_grid_P, + const Button *const button_P) +{ + uint16_t tc = COLOR_INACTIVE_TEXT; + uint16_t bgc = COLOR_INACTIVE_BACKGROUND; + const uint16_t bdc = COLOR_INACTIVE_BORDER; + + Button button; + memcpy_P(&button,button_P,sizeof(button)); + switch(button.status()) + { + case ButtonStatus_e::Stateless://Fallthrough intended + case ButtonStatus_e::Inactive://Fallthrough intended + default: + { + //Colors are initialized for this, so we're done + break; + } + case ButtonStatus_e::Active: + { + tc = COLOR_ACTIVE_TEXT; + bgc = COLOR_ACTIVE_BACKGROUND; + break; + } + } + + if(nullptr != button.text){ + strncpy_P(b,button.text,sizeof(b)); + } + else if(nullptr != button.text_override){ + button.text_override(b,sizeof(b)); + } + else{ + //Something's messed up + //Serial.println(F("No text for button!")); + return; + } + + ButtonGrid_t button_grid; + memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); + + uint8_t button_col = 0; + uint8_t button_row = 0; + bool found_it = false; + for(button_col = 0; button_col < button_grid.num_button_cols && !found_it; ++button_col){ + for(button_row = 0; button_row < button_grid.num_button_rows && !found_it; ++button_row){ + Button* bp; + memcpy_P(&bp,&(button_grid.buttons_P[button_row*button_grid.num_button_cols + button_col]),sizeof(bp)); + if(bp == button_P){ + found_it = true; + break; + } + } + if(found_it){ + break; + } + } + + Serial.print(button_col);Serial.print(",");Serial.print(button_row);Serial.print(" ");Serial.println(b); + displayText(b, + button_col * button_grid.button_pitch_x + button_grid.top_left_x, + button_row * button_grid.button_pitch_y + button_grid.top_left_y, + button_grid.button_width, + button_grid.button_height, + tc, bgc, bdc); +} + +void drawButtonGrid(const ButtonGrid_t *const button_grid_P) +{ + ButtonGrid_t button_grid; + memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); + + Button* bp; + for(uint8_t i = 0; i < button_grid.num_button_rows * button_grid.num_button_cols; ++i){ + memcpy_P(&bp, &(button_grid.buttons_P[i]), sizeof(bp)); + if(nullptr == bp){ + continue; + } + drawButton(button_grid_P,bp); + } +} diff --git a/button_grid.h b/button_grid.h new file mode 100644 index 0000000..7b27e3e --- /dev/null +++ b/button_grid.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +enum ButtonStatus_e : uint8_t { + Stateless, + Inactive, + Active +}; + +struct Button { + const char* text;//nullptr if text_override should be used + void (*text_override)(char* text_out, const uint16_t max_text_size);//nullptr if text should be used + ButtonStatus_e (*status)();//Used for coloring and morse menu + void (*on_select)();//Action to take when selected + char morse; +}; + +struct ButtonGrid_t { + int16_t top_left_x; + int16_t top_left_y; + uint16_t button_width; + uint16_t button_height; + uint16_t button_pitch_x; + uint16_t button_pitch_y; + uint8_t num_button_rows; + uint8_t num_button_cols; + const Button* const* buttons_P;//Expected to be in progmem +}; + +void drawButton(const ButtonGrid_t *const button_grid_P, + const Button *const button_P); +void drawButtonGrid(const ButtonGrid_t *const button_grid_P); diff --git a/menu_main.cpp b/menu_main.cpp index 8eb010b..34b68ca 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -4,7 +4,7 @@ #include #include -#include "button.h" +#include "button_grid.h" #include "color_theme.h" #include "menu_utils.h" #include "morse.h" @@ -33,13 +33,9 @@ int16_t mainMenuSelectedItemRaw = 0;//Allow negative only for easier checks on w void drawMainMenu(void) { displayClear(COLOR_BACKGROUND); - Button button; - Button* bp; - for(uint8_t i = 0; i < MAIN_MENU_NUM_BUTTONS; ++i){ - memcpy_P(&bp, &(mainMenuButtons[i]), sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - drawButton(&button); - } + + drawButtonGrid(&mainMenuGrid); + ltoa(GetActiveVfoFreq(),b,10); morseText(b); } @@ -65,14 +61,13 @@ void mainMenuTune(int16_t knob) const uint32_t old_freq = current_freq; current_freq = new_freq; - Button button; if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&mainMenuVfoGrid,&bVfoA); } else{ - memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&mainMenuVfoGrid,&bVfoB); } - drawButton(&button); + updateBandButtons(old_freq); } @@ -94,17 +89,17 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, { if(mainMenuSelecting){ uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + endSelector(mainMenuSelectedItemRaw,&mainMenuGrid); + Button button; Button* bp; - memcpy_P(&bp,&(mainMenuButtons[menu_index]),sizeof(bp)); + memcpy_P(&bp,&(mainMenuGrid.buttons_P[menu_index]),sizeof(bp)); memcpy_P(&button,bp,sizeof(button)); - endSelector(&button); button.on_select(); } else{ initSelector(&mainMenuSelectedItemRaw, - mainMenuButtons, - MAIN_MENU_NUM_BUTTONS, + &mainMenuGrid, MorsePlaybackType_e::PlayChar); } mainMenuSelecting = !mainMenuSelecting; @@ -134,7 +129,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, else if(ButtonPress_e::NotPressed != touch_button){ //We treat long and short presses the same, so no need to have a switch Button button; - if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&button,touch_point)){ + if(findPressedButton(&mainMenuGrid,&button,touch_point)){ button.on_select(); } else{ @@ -146,8 +141,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, if(mainMenuSelecting){ adjustSelector(&mainMenuSelectedItemRaw, knob, - mainMenuButtons, - MAIN_MENU_NUM_BUTTONS, + &mainMenuGrid, MorsePlaybackType_e::PlayChar); } else{ diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 75fcd89..a8e396d 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -5,7 +5,7 @@ #include //F() #include "bands.h" -#include "button.h" +#include "button_grid.h" #include "color_theme.h" #include "menu_main.h" #include "menu_numpad.h" @@ -54,10 +54,6 @@ void toVfoA(char* text_out, const uint16_t max_text_size); ButtonStatus_e bsVfoA(); void osVfoA(); constexpr Button bVfoA PROGMEM = { - LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, - LAYOUT_VFO_LABEL_Y, - LAYOUT_VFO_LABEL_WIDTH, - LAYOUT_VFO_LABEL_HEIGHT, nullptr, toVfoA, bsVfoA, @@ -69,10 +65,6 @@ void toVfoB(char* text_out, const uint16_t max_text_size); ButtonStatus_e bsVfoB(); void osVfoB(); constexpr Button bVfoB PROGMEM = { - LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, - LAYOUT_VFO_LABEL_Y, - LAYOUT_VFO_LABEL_WIDTH, - LAYOUT_VFO_LABEL_HEIGHT, nullptr, toVfoB, bsVfoB, @@ -84,10 +76,6 @@ constexpr char txtRit [] PROGMEM = "RIT"; ButtonStatus_e bsRit(); void osRit(); constexpr Button bRit PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtRit, nullptr, bsRit, @@ -99,10 +87,6 @@ constexpr char txtUsb [] PROGMEM = "USB"; ButtonStatus_e bsUsb(); void osUsb(); constexpr Button bUsb PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtUsb, nullptr, bsUsb, @@ -114,10 +98,6 @@ constexpr char txtLsb [] PROGMEM = "LSB"; ButtonStatus_e bsLsb(); void osLsb(); constexpr Button bLsb PROGMEM = { - LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtLsb, nullptr, bsLsb, @@ -129,10 +109,6 @@ constexpr char txtCw [] PROGMEM = "CW"; ButtonStatus_e bsCw(); void osCw(); constexpr Button bCw PROGMEM = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtCw, nullptr, bsCw, @@ -144,10 +120,6 @@ constexpr char txtSpl [] PROGMEM = "SPL"; ButtonStatus_e bsSpl(); void osSpl(); constexpr Button bSpl PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtSpl, nullptr, bsSpl, @@ -159,10 +131,6 @@ constexpr char txt80 [] PROGMEM = "80"; ButtonStatus_e bs80(); void os80(); constexpr Button b80 PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txt80, nullptr, bs80, @@ -174,10 +142,6 @@ constexpr char txt40 [] PROGMEM = "40"; ButtonStatus_e bs40(); void os40(); constexpr Button b40 PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txt40, nullptr, bs40, @@ -189,10 +153,6 @@ constexpr char txt30 [] PROGMEM = "30"; ButtonStatus_e bs30(); void os30(); constexpr Button b30 PROGMEM = { - LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txt30, nullptr, bs30, @@ -204,10 +164,6 @@ constexpr char txt20 [] PROGMEM = "20"; ButtonStatus_e bs20(); void os20(); constexpr Button b20 PROGMEM = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txt20, nullptr, bs20, @@ -219,10 +175,6 @@ constexpr char txt17 [] PROGMEM = "17"; ButtonStatus_e bs17(); void os17(); constexpr Button b17 PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txt17, nullptr, bs17, @@ -234,10 +186,6 @@ constexpr char txt15 [] PROGMEM = "15"; ButtonStatus_e bs15(); void os15(); constexpr Button b15 PROGMEM = { - LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txt15, nullptr, bs15, @@ -249,10 +197,6 @@ constexpr char txt10 [] PROGMEM = "10"; ButtonStatus_e bs10(); void os10(); constexpr Button b10 PROGMEM = { - LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txt10, nullptr, bs10, @@ -264,10 +208,6 @@ constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon ButtonStatus_e bsIgnore(); void osMenu(); constexpr Button bMenu PROGMEM = { - LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtMenu, nullptr, bsIgnore, @@ -279,10 +219,6 @@ constexpr char txtNumpad [] PROGMEM = "FRQ"; ButtonStatus_e bsIgnore(); void osNumpad(); constexpr Button bNumpad PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtNumpad, nullptr, bsIgnore, @@ -290,15 +226,39 @@ constexpr Button bNumpad PROGMEM = { 'F' }; -const Button* const mainMenuButtons [] PROGMEM = { - &bVfoA, &bVfoB, +const Button* const mainMenuVfoButtons [] PROGMEM = { + &bVfoA, &bVfoB +}; - &bRit, &bUsb, &bLsb, &bCw, &bSpl, - &b80, &b40, &b30, &b20, &b17, - &b15, &b10, &bMenu, &bNumpad +const ButtonGrid_t mainMenuVfoGrid PROGMEM = { + LAYOUT_VFO_LABEL_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, + LAYOUT_VFO_LABEL_PITCH_X, + 0,//not used, since it's just one row + 1,//rows + 2,//cols + mainMenuVfoButtons }; -const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); +const Button* const mainMenuButtons [] PROGMEM = { + &bRit, &bUsb, &bLsb, &bCw, &bSpl, + &b80, &b40, &b30, &b20, &b17, + &b15, &b10, nullptr, &bMenu, &bNumpad +}; + +const ButtonGrid_t mainMenuGrid PROGMEM = { + LAYOUT_BUTTON_X, + LAYOUT_BUTTON_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_PITCH_Y, + 3,//rows + 5,//cols + mainMenuButtons +}; void updateBandButtons(const uint32_t old_freq) { @@ -310,7 +270,7 @@ void updateBandButtons(const uint32_t old_freq) for(uint8_t i = 0; i < sizeof(bands)/sizeof(bands[0]); ++i){ if(isFreqInBand(old_freq,bands[i]) != isFreqInBand(curr_freq,bands[i])){ memcpy_P(&button,band_buttons[i],sizeof(button)); - drawButton(&button); + drawButton(&mainMenuGrid,band_buttons[i]); morseBool(ButtonStatus_e::Active == button.status()); } } @@ -374,11 +334,8 @@ void osVfo(const Vfo_e vfo){ ltoa(GetActiveVfoFreq(),b,10); morseText(b); - Button button; - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuGrid,&bVfoA); + drawButton(&mainMenuGrid,&bVfoB); updateBandButtons(old_freq); } @@ -406,7 +363,6 @@ ButtonStatus_e bsRit(){ return globalSettings.ritOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } void osRit(){ - Button button; if(!globalSettings.ritOn){ globalSettings.ritOn = true; globalSettings.ritFrequency = GetActiveVfoFreq(); @@ -426,17 +382,14 @@ void osRit(){ displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuVfoGrid,&bVfoA); } else{ - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuVfoGrid,&bVfoB); } } - memcpy_P(&button,&bRit,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuGrid,&bRit); } void osSidebandMode(VfoMode_e mode){ @@ -444,11 +397,8 @@ void osSidebandMode(VfoMode_e mode){ setFrequency(GetActiveVfoFreq()); SaveSettingsToEeprom(); - Button button; - memcpy_P(&button,&bUsb,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bLsb,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuGrid,&bUsb); + drawButton(&mainMenuGrid,&bLsb); } void updateSidebandButtons() @@ -486,9 +436,7 @@ void osCw(){ setFrequency(GetActiveVfoFreq()); - Button button; - memcpy_P(&button,&bCw,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuGrid,&bCw); } ButtonStatus_e bsSpl(){ @@ -498,13 +446,9 @@ ButtonStatus_e bsSpl(){ void osSpl(){ globalSettings.splitOn = !globalSettings.splitOn; - Button button; - memcpy_P(&button,&bSpl,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuGrid,&bSpl); + drawButton(&mainMenuVfoGrid,&bVfoA); + drawButton(&mainMenuVfoGrid,&bVfoB); } ButtonStatus_e bsBand(const uint8_t band){ @@ -518,14 +462,11 @@ void osBand(const uint8_t band){ updateSidebandButtons(); } - Button button; if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuVfoGrid,&bVfoA); } else if(Vfo_e::VFO_B == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + drawButton(&mainMenuVfoGrid,&bVfoB); } updateBandButtons(old_freq); diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 0e7febd..631e411 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -2,12 +2,12 @@ #include -#include "button.h" - -extern const Button* const mainMenuButtons[]; -extern const uint8_t MAIN_MENU_NUM_BUTTONS; +#include "button_grid.h" +extern const ButtonGrid_t mainMenuVfoGrid; +extern const ButtonGrid_t mainMenuGrid; extern const Button bVfoA; extern const Button bVfoB; + void updateBandButtons(const uint32_t old_freq); void updateSidebandButtons(); diff --git a/menu_numpad.cpp b/menu_numpad.cpp index 847fb2e..08e602f 100644 --- a/menu_numpad.cpp +++ b/menu_numpad.cpp @@ -25,13 +25,7 @@ int16_t numpadMenuSelectedItemRaw = 0;//Allow negative only for easier checks on void drawNumpad(void) { displayFillrect(0,47,320,200,COLOR_BACKGROUND); - Button button; - Button* bp; - for(uint8_t i = 0; i < NUMPAD_MENU_NUM_BUTTONS; ++i){ - memcpy_P(&bp, &(numpadMenuButtons[i]), sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - drawButton(&button); - } + drawButtonGrid(&numpadMenuGrid); } void initNumpad(void) @@ -39,8 +33,7 @@ void initNumpad(void) numpadMenuFrequency = 0; drawNumpad(); initSelector(&numpadMenuSelectedItemRaw, - numpadMenuButtons, - NUMPAD_MENU_NUM_BUTTONS, + &numpadMenuGrid, MorsePlaybackType_e::PlayChar); } @@ -51,18 +44,25 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button, { if(ButtonPress_e::NotPressed != tuner_button){ //We treat long and short presses the same, so no need to have a switch + + ButtonGrid_t button_grid; + memcpy_P(&button_grid,&numpadMenuGrid,sizeof(button_grid)); + uint8_t menu_index = numpadMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; - Button button; Button* bp; - memcpy_P(&bp,&(numpadMenuButtons[menu_index]),sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - button.on_select(); + memcpy_P(&bp,&(button_grid.buttons_P[menu_index]),sizeof(bp)); + + if(nullptr != bp){ + Button button; + memcpy_P(&button,bp,sizeof(button)); + button.on_select(); + } }//tuner_button else if(ButtonPress_e::NotPressed != touch_button){ //We treat long and short presses the same, so no need to have a switch Button button; - if(findPressedButton(numpadMenuButtons,NUMPAD_MENU_NUM_BUTTONS,&button,touch_point)){ + if(findPressedButton(&numpadMenuGrid,&button,touch_point)){ button.on_select(); } else{ @@ -73,8 +73,7 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button, else{//Neither button input type found, so handle the knob adjustSelector(&numpadMenuSelectedItemRaw, knob, - numpadMenuButtons, - NUMPAD_MENU_NUM_BUTTONS, + &numpadMenuGrid, MorsePlaybackType_e::PlayChar); } diff --git a/menu_numpad_buttons.cpp b/menu_numpad_buttons.cpp index 252eaa6..2946fdd 100644 --- a/menu_numpad_buttons.cpp +++ b/menu_numpad_buttons.cpp @@ -27,15 +27,11 @@ uint32_t numpadMenuFrequency; #define D_STRINGIFY(x) #x #define D_STRING(x) D_STRINGIFY(x) -#define NUMBER_BUTTON_GENERATE(number,x,y) \ +#define NUMBER_BUTTON_GENERATE(number) \ constexpr char txt##number [] PROGMEM = "" D_STRING(number);\ ButtonStatus_e bs##number();\ void os##number();\ constexpr Button b##number PROGMEM = {\ - LAYOUT_BUTTON_X + x*LAYOUT_BUTTON_PITCH_X,\ - LAYOUT_BUTTON_Y + y*LAYOUT_BUTTON_PITCH_Y,\ - LAYOUT_BUTTON_WIDTH,\ - LAYOUT_BUTTON_HEIGHT,\ txt##number,\ nullptr,\ bsNumpad,\ @@ -47,28 +43,20 @@ ButtonStatus_e bsNumpad(void){ return ButtonStatus_e::Stateless; } - -// 1 2 3 Ok -// 4 5 6 0 <- -// 7 8 9 Can -NUMBER_BUTTON_GENERATE(1,0,0); -NUMBER_BUTTON_GENERATE(2,1,0); -NUMBER_BUTTON_GENERATE(3,2,0); -NUMBER_BUTTON_GENERATE(4,0,1); -NUMBER_BUTTON_GENERATE(5,1,1); -NUMBER_BUTTON_GENERATE(6,2,1); -NUMBER_BUTTON_GENERATE(7,0,2); -NUMBER_BUTTON_GENERATE(8,1,2); -NUMBER_BUTTON_GENERATE(9,2,2); -NUMBER_BUTTON_GENERATE(0,3,1); +NUMBER_BUTTON_GENERATE(1); +NUMBER_BUTTON_GENERATE(2); +NUMBER_BUTTON_GENERATE(3); +NUMBER_BUTTON_GENERATE(4); +NUMBER_BUTTON_GENERATE(5); +NUMBER_BUTTON_GENERATE(6); +NUMBER_BUTTON_GENERATE(7); +NUMBER_BUTTON_GENERATE(8); +NUMBER_BUTTON_GENERATE(9); +NUMBER_BUTTON_GENERATE(0); constexpr char txtOk [] PROGMEM = "OK"; void osOk(); constexpr Button bOk PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtOk, nullptr, bsNumpad, @@ -79,10 +67,6 @@ constexpr Button bOk PROGMEM = { constexpr char txtBackspace [] PROGMEM = "<-"; void osBackspace(); constexpr Button bBackspace PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtBackspace, nullptr, bsNumpad, @@ -93,10 +77,6 @@ constexpr Button bBackspace PROGMEM = { constexpr char txtCancel [] PROGMEM = "Can"; void osCancel(); constexpr Button bCancel PROGMEM = { - LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, txtCancel, nullptr, bsNumpad, @@ -106,10 +86,22 @@ constexpr Button bCancel PROGMEM = { //Declare in menu select order, not graphical order const Button* const numpadMenuButtons [] PROGMEM = { - &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &b9, &b0, - &bOk, &bBackspace, &bCancel + &b1, &b2, &b3, nullptr, &bOk, + &b4, &b5, &b6, &b0, &bBackspace, + &b7, &b8, &b9, nullptr, &bCancel +}; + +const ButtonGrid_t numpadMenuGrid PROGMEM = { + LAYOUT_BUTTON_X, + LAYOUT_BUTTON_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_PITCH_Y, + 3,//rows + 5,//cols + numpadMenuButtons }; -const uint8_t NUMPAD_MENU_NUM_BUTTONS = sizeof(numpadMenuButtons)/sizeof(numpadMenuButtons[0]); void updateCurrentEnteredFrequency(void) { diff --git a/menu_numpad_buttons.h b/menu_numpad_buttons.h index a7d555e..c813437 100644 --- a/menu_numpad_buttons.h +++ b/menu_numpad_buttons.h @@ -2,10 +2,9 @@ #include -#include "button.h" +#include "button_grid.h" -extern const Button* const numpadMenuButtons[]; -extern const uint8_t NUMPAD_MENU_NUM_BUTTONS; +extern const ButtonGrid_t numpadMenuGrid; extern const uint32_t NUMPAD_MENU_EXIT_FREQ; extern uint32_t numpadMenuFrequency; diff --git a/menu_utils.cpp b/menu_utils.cpp index d5fcf6e..dfda9e2 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -2,40 +2,80 @@ #include -#include "button.h" +#include "button_grid.h" #include "color_theme.h" #include "morse.h" #include "nano_gui.h" #include "utils.h" -bool findPressedButton(const Button* const* buttons, - const uint8_t num_buttons, +bool findPressedButton(const ButtonGrid_t *const button_grid_P, Button *const button_out, const Point touch_point) { + ButtonGrid_t button_grid; + memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); + + if((touch_point.x < button_grid.top_left_x) + ||(touch_point.y < button_grid.top_left_y) + ||(touch_point.x > (int16_t)button_grid.button_pitch_x * button_grid.num_button_cols) + ||(touch_point.y > (int16_t)button_grid.button_pitch_y * button_grid.num_button_rows)){ + //touch point was outside the button grid + return false; + } + + uint8_t row = (touch_point.x - button_grid.top_left_x) / button_grid.button_pitch_x; + uint8_t col = (touch_point.y - button_grid.top_left_y) / button_grid.button_pitch_y; + int16_t x_max = (col * button_grid.button_pitch_x) + button_grid.button_width; + int16_t y_max = (row * button_grid.button_pitch_y) + button_grid.button_height; + if((touch_point.x > x_max) + ||(touch_point.y > y_max)){ + //touch point was outside of the button + return false; + } + Button* bp; - for(uint16_t i = 0; i < num_buttons; ++i){ - memcpy_P(&bp,&(buttons[i]),sizeof(bp)); - memcpy_P(button_out,bp,sizeof(*button_out)); - if((button_out->x <= touch_point.x) - &&(touch_point.x <= button_out->x + button_out->w) - &&(button_out->y <= touch_point.y) - &&(touch_point.y <= button_out->y + button_out->h)){ - return true; - } + memcpy_P(&bp,&(button_grid.buttons_P[row * button_grid.num_button_cols + col]),sizeof(bp)); + if(nullptr == bp){ + //no button there + return false; } - return false; + memcpy_P(button_out,bp,sizeof(*button_out)); + return true; } -void movePuck(const Button *const b_old, - const Button *const b_new) +void indexToRowCol(const ButtonGrid_t *const button_grid, + const int8_t index, + uint8_t *const row_out, + uint8_t *const col_out) { - if(nullptr != b_old){ - displayRect(b_old->x,b_old->y,b_old->w,b_old->h,COLOR_INACTIVE_BORDER); + *row_out = index / button_grid->num_button_cols; + *col_out = index % button_grid->num_button_cols; +} + +void movePuck(const ButtonGrid_t *const button_grid, + const int8_t old_index, + const int8_t new_index) +{ + if(-1 != old_index){ + uint8_t row; + uint8_t col; + indexToRowCol(button_grid,old_index,&row,&col); + displayRect(button_grid->top_left_x + button_grid->button_pitch_x * col, + button_grid->top_left_y + button_grid->button_pitch_y * row, + button_grid->button_width, + button_grid->button_height, + COLOR_INACTIVE_BORDER); } - if(nullptr != b_new){ - displayRect(b_new->x,b_new->y,b_new->w,b_new->h,COLOR_ACTIVE_BORDER); + if(-1 != new_index){ + uint8_t row; + uint8_t col; + indexToRowCol(button_grid,new_index,&row,&col); + displayRect(button_grid->top_left_x + button_grid->button_pitch_x * col, + button_grid->top_left_y + button_grid->button_pitch_y * row, + button_grid->button_width, + button_grid->button_height, + COLOR_ACTIVE_BORDER); } } @@ -59,45 +99,72 @@ void playButtonMorse(const Button *const button, } void initSelector(int16_t *const raw_select_val_in_out, - const Button* const* buttons, - const uint8_t num_buttons, + const ButtonGrid_t *const button_grid_P, const MorsePlaybackType_e play_type) { + ButtonGrid_t button_grid; + memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); + *raw_select_val_in_out = 0; - if(0 < num_buttons){ + + if(0 < button_grid.num_button_rows * button_grid.num_button_cols){ Button button; Button* bp; - memcpy_P(&bp,&(buttons[0]),sizeof(bp)); + memcpy_P(&bp,&(button_grid.buttons_P[0]),sizeof(bp)); memcpy_P(&button,bp,sizeof(button)); - movePuck(nullptr,&button); + movePuck(&button_grid,-1,0); playButtonMorse(&button,play_type); } } void adjustSelector(int16_t *const raw_select_val_in_out, - const int16_t knob, - const Button* const* buttons, - const uint8_t num_buttons, + int16_t knob, + const ButtonGrid_t *const button_grid_P, const MorsePlaybackType_e play_type) { + ButtonGrid_t button_grid; + memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); + + const uint8_t num_buttons = button_grid.num_button_rows * button_grid.num_button_cols; const uint8_t prev_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; - *raw_select_val_in_out = LIMIT((*raw_select_val_in_out)+knob,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1); - const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; - if(prev_select != new_select){ - Button prev_button; - Button* bp; - memcpy_P(&bp,&(buttons[prev_select]),sizeof(bp)); - memcpy_P(&prev_button,bp,sizeof(prev_button)); - Button new_button; - memcpy_P(&bp,&(buttons[new_select]),sizeof(bp)); - memcpy_P(&new_button,bp,sizeof(new_button)); - - movePuck(&prev_button,&new_button); - playButtonMorse(&new_button,play_type); + *raw_select_val_in_out += knob; + bool keep_trying = true; + while(keep_trying){ + *raw_select_val_in_out = LIMIT(*raw_select_val_in_out,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1); + const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; + if(prev_select != new_select){ + Button* bp; + memcpy_P(&bp,&(button_grid.buttons_P[new_select]),sizeof(bp)); + if(nullptr == bp){ + if(new_select > prev_select){ + *raw_select_val_in_out += MENU_KNOB_COUNTS_PER_ITEM; + } + else{ + *raw_select_val_in_out -= MENU_KNOB_COUNTS_PER_ITEM; + } + if((*raw_select_val_in_out <= 0) + ||(*raw_select_val_in_out >= num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1)){ + keep_trying = false; + } + continue; + } + + Button new_button; + memcpy_P(&new_button,bp,sizeof(new_button)); + + movePuck(&button_grid,prev_select,new_select); + playButtonMorse(&new_button,play_type); + } } } -void endSelector(const Button *const button) +void endSelector(const int16_t raw_select, + const ButtonGrid_t *const button_grid_P) { - movePuck(button,nullptr); + ButtonGrid_t button_grid; + memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); + + uint8_t index = raw_select/MENU_KNOB_COUNTS_PER_ITEM; + + movePuck(&button_grid,index,-1); } diff --git a/menu_utils.h b/menu_utils.h index d84be30..0a6f55c 100644 --- a/menu_utils.h +++ b/menu_utils.h @@ -1,11 +1,10 @@ #pragma once -#include "button.h" +#include "button_grid.h" #include "menu.h" //Returns true if button was found, false otherwise -bool findPressedButton(const Button* const* buttons, - const uint8_t num_buttons, +bool findPressedButton(const ButtonGrid_t *const button_grid_P, Button *const button_out, const Point touch_point); @@ -14,14 +13,13 @@ enum MorsePlaybackType_e : uint8_t { PlayText }; void initSelector(int16_t *const raw_select_val_in_out, - const Button* const* buttons, - const uint8_t num_buttons, - const MorsePlaybackType_e); + const ButtonGrid_t *const button_grid_P, + const MorsePlaybackType_e play_type); void adjustSelector(int16_t *const raw_select_val_in_out, int16_t knob, - const Button* const* buttons, - const uint8_t num_buttons, - const MorsePlaybackType_e); + const ButtonGrid_t *const button_grid_P, + const MorsePlaybackType_e play_type); -void endSelector(const Button *const button); +void endSelector(const int16_t raw_select, + const ButtonGrid_t *const button_grid_P); From 9b9a1610c2ad109e411761a9921a1c75a46c6194 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 19:47:02 -0700 Subject: [PATCH 251/324] Revert "Rough pass at button grids" This reverts commit 1f97be3263bf766f52292287939c6b1a3bfc6b6d. --- button.cpp | 44 ++++++++++++ button.h | 20 ++++++ button_grid.cpp | 90 ------------------------ button_grid.h | 33 --------- menu_main.cpp | 32 +++++---- menu_main_buttons.cpp | 149 +++++++++++++++++++++++++++------------ menu_main_buttons.h | 8 +-- menu_numpad.cpp | 31 +++++---- menu_numpad_buttons.cpp | 60 +++++++++------- menu_numpad_buttons.h | 5 +- menu_utils.cpp | 151 +++++++++++----------------------------- menu_utils.h | 18 ++--- 12 files changed, 296 insertions(+), 345 deletions(-) create mode 100644 button.cpp create mode 100644 button.h delete mode 100644 button_grid.cpp delete mode 100644 button_grid.h diff --git a/button.cpp b/button.cpp new file mode 100644 index 0000000..ac221ac --- /dev/null +++ b/button.cpp @@ -0,0 +1,44 @@ +#include "button.h" + +#include + +#include "color_theme.h" +#include "nano_gui.h" +#include "scratch_space.h" + +void drawButton(Button* button) +{ + uint16_t tc = COLOR_INACTIVE_TEXT; + uint16_t bgc = COLOR_INACTIVE_BACKGROUND; + const uint16_t bdc = COLOR_INACTIVE_BORDER; + switch(button->status()) + { + case ButtonStatus_e::Stateless://Fallthrough intended + case ButtonStatus_e::Inactive://Fallthrough intended + default: + { + //Colors are initialized for this, so we're done + break; + } + case ButtonStatus_e::Active: + { + tc = COLOR_ACTIVE_TEXT; + bgc = COLOR_ACTIVE_BACKGROUND; + break; + } + } + + + if(nullptr != button->text){ + strncpy_P(b,button->text,sizeof(b)); + } + else if(nullptr != button->text_override){ + button->text_override(b,sizeof(b)); + } + else{ + //Something's messed up + //Serial.println(F("No text for button!")); + return; + } + displayText(b, button->x, button->y, button->w, button->h, tc, bgc, bdc); +} diff --git a/button.h b/button.h new file mode 100644 index 0000000..6aba532 --- /dev/null +++ b/button.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +enum ButtonStatus_e : uint8_t { + Stateless, + Inactive, + Active +}; + +struct Button { + int16_t x, y, w, h; + const char* text;//nullptr if text_override should be used + void (*text_override)(char* text_out, const uint16_t max_text_size);//nullptr if text should be used + ButtonStatus_e (*status)();//Used for coloring and morse menu + void (*on_select)();//Action to take when selected + char morse; +}; + +void drawButton(Button* button); diff --git a/button_grid.cpp b/button_grid.cpp deleted file mode 100644 index 337621c..0000000 --- a/button_grid.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include "button_grid.h" - -#include -#include - -#include "color_theme.h" -#include "nano_gui.h" -#include "scratch_space.h" - -void drawButton(const ButtonGrid_t *const button_grid_P, - const Button *const button_P) -{ - uint16_t tc = COLOR_INACTIVE_TEXT; - uint16_t bgc = COLOR_INACTIVE_BACKGROUND; - const uint16_t bdc = COLOR_INACTIVE_BORDER; - - Button button; - memcpy_P(&button,button_P,sizeof(button)); - switch(button.status()) - { - case ButtonStatus_e::Stateless://Fallthrough intended - case ButtonStatus_e::Inactive://Fallthrough intended - default: - { - //Colors are initialized for this, so we're done - break; - } - case ButtonStatus_e::Active: - { - tc = COLOR_ACTIVE_TEXT; - bgc = COLOR_ACTIVE_BACKGROUND; - break; - } - } - - if(nullptr != button.text){ - strncpy_P(b,button.text,sizeof(b)); - } - else if(nullptr != button.text_override){ - button.text_override(b,sizeof(b)); - } - else{ - //Something's messed up - //Serial.println(F("No text for button!")); - return; - } - - ButtonGrid_t button_grid; - memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); - - uint8_t button_col = 0; - uint8_t button_row = 0; - bool found_it = false; - for(button_col = 0; button_col < button_grid.num_button_cols && !found_it; ++button_col){ - for(button_row = 0; button_row < button_grid.num_button_rows && !found_it; ++button_row){ - Button* bp; - memcpy_P(&bp,&(button_grid.buttons_P[button_row*button_grid.num_button_cols + button_col]),sizeof(bp)); - if(bp == button_P){ - found_it = true; - break; - } - } - if(found_it){ - break; - } - } - - Serial.print(button_col);Serial.print(",");Serial.print(button_row);Serial.print(" ");Serial.println(b); - displayText(b, - button_col * button_grid.button_pitch_x + button_grid.top_left_x, - button_row * button_grid.button_pitch_y + button_grid.top_left_y, - button_grid.button_width, - button_grid.button_height, - tc, bgc, bdc); -} - -void drawButtonGrid(const ButtonGrid_t *const button_grid_P) -{ - ButtonGrid_t button_grid; - memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); - - Button* bp; - for(uint8_t i = 0; i < button_grid.num_button_rows * button_grid.num_button_cols; ++i){ - memcpy_P(&bp, &(button_grid.buttons_P[i]), sizeof(bp)); - if(nullptr == bp){ - continue; - } - drawButton(button_grid_P,bp); - } -} diff --git a/button_grid.h b/button_grid.h deleted file mode 100644 index 7b27e3e..0000000 --- a/button_grid.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -enum ButtonStatus_e : uint8_t { - Stateless, - Inactive, - Active -}; - -struct Button { - const char* text;//nullptr if text_override should be used - void (*text_override)(char* text_out, const uint16_t max_text_size);//nullptr if text should be used - ButtonStatus_e (*status)();//Used for coloring and morse menu - void (*on_select)();//Action to take when selected - char morse; -}; - -struct ButtonGrid_t { - int16_t top_left_x; - int16_t top_left_y; - uint16_t button_width; - uint16_t button_height; - uint16_t button_pitch_x; - uint16_t button_pitch_y; - uint8_t num_button_rows; - uint8_t num_button_cols; - const Button* const* buttons_P;//Expected to be in progmem -}; - -void drawButton(const ButtonGrid_t *const button_grid_P, - const Button *const button_P); -void drawButtonGrid(const ButtonGrid_t *const button_grid_P); diff --git a/menu_main.cpp b/menu_main.cpp index 34b68ca..8eb010b 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -4,7 +4,7 @@ #include #include -#include "button_grid.h" +#include "button.h" #include "color_theme.h" #include "menu_utils.h" #include "morse.h" @@ -33,9 +33,13 @@ int16_t mainMenuSelectedItemRaw = 0;//Allow negative only for easier checks on w void drawMainMenu(void) { displayClear(COLOR_BACKGROUND); - - drawButtonGrid(&mainMenuGrid); - + Button button; + Button* bp; + for(uint8_t i = 0; i < MAIN_MENU_NUM_BUTTONS; ++i){ + memcpy_P(&bp, &(mainMenuButtons[i]), sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + drawButton(&button); + } ltoa(GetActiveVfoFreq(),b,10); morseText(b); } @@ -61,13 +65,14 @@ void mainMenuTune(int16_t knob) const uint32_t old_freq = current_freq; current_freq = new_freq; + Button button; if(Vfo_e::VFO_A == globalSettings.activeVfo){ - drawButton(&mainMenuVfoGrid,&bVfoA); + memcpy_P(&button,&bVfoA,sizeof(button)); } else{ - drawButton(&mainMenuVfoGrid,&bVfoB); + memcpy_P(&button,&bVfoB,sizeof(button)); } - + drawButton(&button); updateBandButtons(old_freq); } @@ -89,17 +94,17 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, { if(mainMenuSelecting){ uint8_t menu_index = mainMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; - endSelector(mainMenuSelectedItemRaw,&mainMenuGrid); - Button button; Button* bp; - memcpy_P(&bp,&(mainMenuGrid.buttons_P[menu_index]),sizeof(bp)); + memcpy_P(&bp,&(mainMenuButtons[menu_index]),sizeof(bp)); memcpy_P(&button,bp,sizeof(button)); + endSelector(&button); button.on_select(); } else{ initSelector(&mainMenuSelectedItemRaw, - &mainMenuGrid, + mainMenuButtons, + MAIN_MENU_NUM_BUTTONS, MorsePlaybackType_e::PlayChar); } mainMenuSelecting = !mainMenuSelecting; @@ -129,7 +134,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, else if(ButtonPress_e::NotPressed != touch_button){ //We treat long and short presses the same, so no need to have a switch Button button; - if(findPressedButton(&mainMenuGrid,&button,touch_point)){ + if(findPressedButton(mainMenuButtons,MAIN_MENU_NUM_BUTTONS,&button,touch_point)){ button.on_select(); } else{ @@ -141,7 +146,8 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, if(mainMenuSelecting){ adjustSelector(&mainMenuSelectedItemRaw, knob, - &mainMenuGrid, + mainMenuButtons, + MAIN_MENU_NUM_BUTTONS, MorsePlaybackType_e::PlayChar); } else{ diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index a8e396d..75fcd89 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -5,7 +5,7 @@ #include //F() #include "bands.h" -#include "button_grid.h" +#include "button.h" #include "color_theme.h" #include "menu_main.h" #include "menu_numpad.h" @@ -54,6 +54,10 @@ void toVfoA(char* text_out, const uint16_t max_text_size); ButtonStatus_e bsVfoA(); void osVfoA(); constexpr Button bVfoA PROGMEM = { + LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, nullptr, toVfoA, bsVfoA, @@ -65,6 +69,10 @@ void toVfoB(char* text_out, const uint16_t max_text_size); ButtonStatus_e bsVfoB(); void osVfoB(); constexpr Button bVfoB PROGMEM = { + LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, + LAYOUT_VFO_LABEL_Y, + LAYOUT_VFO_LABEL_WIDTH, + LAYOUT_VFO_LABEL_HEIGHT, nullptr, toVfoB, bsVfoB, @@ -76,6 +84,10 @@ constexpr char txtRit [] PROGMEM = "RIT"; ButtonStatus_e bsRit(); void osRit(); constexpr Button bRit PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtRit, nullptr, bsRit, @@ -87,6 +99,10 @@ constexpr char txtUsb [] PROGMEM = "USB"; ButtonStatus_e bsUsb(); void osUsb(); constexpr Button bUsb PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtUsb, nullptr, bsUsb, @@ -98,6 +114,10 @@ constexpr char txtLsb [] PROGMEM = "LSB"; ButtonStatus_e bsLsb(); void osLsb(); constexpr Button bLsb PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtLsb, nullptr, bsLsb, @@ -109,6 +129,10 @@ constexpr char txtCw [] PROGMEM = "CW"; ButtonStatus_e bsCw(); void osCw(); constexpr Button bCw PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtCw, nullptr, bsCw, @@ -120,6 +144,10 @@ constexpr char txtSpl [] PROGMEM = "SPL"; ButtonStatus_e bsSpl(); void osSpl(); constexpr Button bSpl PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtSpl, nullptr, bsSpl, @@ -131,6 +159,10 @@ constexpr char txt80 [] PROGMEM = "80"; ButtonStatus_e bs80(); void os80(); constexpr Button b80 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txt80, nullptr, bs80, @@ -142,6 +174,10 @@ constexpr char txt40 [] PROGMEM = "40"; ButtonStatus_e bs40(); void os40(); constexpr Button b40 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txt40, nullptr, bs40, @@ -153,6 +189,10 @@ constexpr char txt30 [] PROGMEM = "30"; ButtonStatus_e bs30(); void os30(); constexpr Button b30 PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txt30, nullptr, bs30, @@ -164,6 +204,10 @@ constexpr char txt20 [] PROGMEM = "20"; ButtonStatus_e bs20(); void os20(); constexpr Button b20 PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txt20, nullptr, bs20, @@ -175,6 +219,10 @@ constexpr char txt17 [] PROGMEM = "17"; ButtonStatus_e bs17(); void os17(); constexpr Button b17 PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txt17, nullptr, bs17, @@ -186,6 +234,10 @@ constexpr char txt15 [] PROGMEM = "15"; ButtonStatus_e bs15(); void os15(); constexpr Button b15 PROGMEM = { + LAYOUT_BUTTON_X + 0*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txt15, nullptr, bs15, @@ -197,6 +249,10 @@ constexpr char txt10 [] PROGMEM = "10"; ButtonStatus_e bs10(); void os10(); constexpr Button b10 PROGMEM = { + LAYOUT_BUTTON_X + 1*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txt10, nullptr, bs10, @@ -208,6 +264,10 @@ constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon ButtonStatus_e bsIgnore(); void osMenu(); constexpr Button bMenu PROGMEM = { + LAYOUT_BUTTON_X + 3*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtMenu, nullptr, bsIgnore, @@ -219,6 +279,10 @@ constexpr char txtNumpad [] PROGMEM = "FRQ"; ButtonStatus_e bsIgnore(); void osNumpad(); constexpr Button bNumpad PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtNumpad, nullptr, bsIgnore, @@ -226,40 +290,16 @@ constexpr Button bNumpad PROGMEM = { 'F' }; -const Button* const mainMenuVfoButtons [] PROGMEM = { - &bVfoA, &bVfoB -}; - -const ButtonGrid_t mainMenuVfoGrid PROGMEM = { - LAYOUT_VFO_LABEL_X, - LAYOUT_VFO_LABEL_Y, - LAYOUT_VFO_LABEL_WIDTH, - LAYOUT_VFO_LABEL_HEIGHT, - LAYOUT_VFO_LABEL_PITCH_X, - 0,//not used, since it's just one row - 1,//rows - 2,//cols - mainMenuVfoButtons -}; - const Button* const mainMenuButtons [] PROGMEM = { - &bRit, &bUsb, &bLsb, &bCw, &bSpl, - &b80, &b40, &b30, &b20, &b17, - &b15, &b10, nullptr, &bMenu, &bNumpad -}; + &bVfoA, &bVfoB, -const ButtonGrid_t mainMenuGrid PROGMEM = { - LAYOUT_BUTTON_X, - LAYOUT_BUTTON_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_PITCH_Y, - 3,//rows - 5,//cols - mainMenuButtons + &bRit, &bUsb, &bLsb, &bCw, &bSpl, + &b80, &b40, &b30, &b20, &b17, + &b15, &b10, &bMenu, &bNumpad }; +const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); + void updateBandButtons(const uint32_t old_freq) { const Button* band_buttons[] = {&b80,&b40,&b30,&b20,&b17,&b15,&b10}; @@ -270,7 +310,7 @@ void updateBandButtons(const uint32_t old_freq) for(uint8_t i = 0; i < sizeof(bands)/sizeof(bands[0]); ++i){ if(isFreqInBand(old_freq,bands[i]) != isFreqInBand(curr_freq,bands[i])){ memcpy_P(&button,band_buttons[i],sizeof(button)); - drawButton(&mainMenuGrid,band_buttons[i]); + drawButton(&button); morseBool(ButtonStatus_e::Active == button.status()); } } @@ -334,8 +374,11 @@ void osVfo(const Vfo_e vfo){ ltoa(GetActiveVfoFreq(),b,10); morseText(b); - drawButton(&mainMenuGrid,&bVfoA); - drawButton(&mainMenuGrid,&bVfoB); + Button button; + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); updateBandButtons(old_freq); } @@ -363,6 +406,7 @@ ButtonStatus_e bsRit(){ return globalSettings.ritOn ? ButtonStatus_e::Active : ButtonStatus_e::Inactive; } void osRit(){ + Button button; if(!globalSettings.ritOn){ globalSettings.ritOn = true; globalSettings.ritFrequency = GetActiveVfoFreq(); @@ -382,14 +426,17 @@ void osRit(){ displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); if(Vfo_e::VFO_A == globalSettings.activeVfo){ - drawButton(&mainMenuVfoGrid,&bVfoA); + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); } else{ - drawButton(&mainMenuVfoGrid,&bVfoB); + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); } } - drawButton(&mainMenuGrid,&bRit); + memcpy_P(&button,&bRit,sizeof(button)); + drawButton(&button); } void osSidebandMode(VfoMode_e mode){ @@ -397,8 +444,11 @@ void osSidebandMode(VfoMode_e mode){ setFrequency(GetActiveVfoFreq()); SaveSettingsToEeprom(); - drawButton(&mainMenuGrid,&bUsb); - drawButton(&mainMenuGrid,&bLsb); + Button button; + memcpy_P(&button,&bUsb,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bLsb,sizeof(button)); + drawButton(&button); } void updateSidebandButtons() @@ -436,7 +486,9 @@ void osCw(){ setFrequency(GetActiveVfoFreq()); - drawButton(&mainMenuGrid,&bCw); + Button button; + memcpy_P(&button,&bCw,sizeof(button)); + drawButton(&button); } ButtonStatus_e bsSpl(){ @@ -446,9 +498,13 @@ ButtonStatus_e bsSpl(){ void osSpl(){ globalSettings.splitOn = !globalSettings.splitOn; - drawButton(&mainMenuGrid,&bSpl); - drawButton(&mainMenuVfoGrid,&bVfoA); - drawButton(&mainMenuVfoGrid,&bVfoB); + Button button; + memcpy_P(&button,&bSpl,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); } ButtonStatus_e bsBand(const uint8_t band){ @@ -462,11 +518,14 @@ void osBand(const uint8_t band){ updateSidebandButtons(); } + Button button; if(Vfo_e::VFO_A == globalSettings.activeVfo){ - drawButton(&mainMenuVfoGrid,&bVfoA); + memcpy_P(&button,&bVfoA,sizeof(button)); + drawButton(&button); } else if(Vfo_e::VFO_B == globalSettings.activeVfo){ - drawButton(&mainMenuVfoGrid,&bVfoB); + memcpy_P(&button,&bVfoB,sizeof(button)); + drawButton(&button); } updateBandButtons(old_freq); diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 631e411..0e7febd 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -2,12 +2,12 @@ #include -#include "button_grid.h" +#include "button.h" + +extern const Button* const mainMenuButtons[]; +extern const uint8_t MAIN_MENU_NUM_BUTTONS; -extern const ButtonGrid_t mainMenuVfoGrid; -extern const ButtonGrid_t mainMenuGrid; extern const Button bVfoA; extern const Button bVfoB; - void updateBandButtons(const uint32_t old_freq); void updateSidebandButtons(); diff --git a/menu_numpad.cpp b/menu_numpad.cpp index 08e602f..847fb2e 100644 --- a/menu_numpad.cpp +++ b/menu_numpad.cpp @@ -25,7 +25,13 @@ int16_t numpadMenuSelectedItemRaw = 0;//Allow negative only for easier checks on void drawNumpad(void) { displayFillrect(0,47,320,200,COLOR_BACKGROUND); - drawButtonGrid(&numpadMenuGrid); + Button button; + Button* bp; + for(uint8_t i = 0; i < NUMPAD_MENU_NUM_BUTTONS; ++i){ + memcpy_P(&bp, &(numpadMenuButtons[i]), sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + drawButton(&button); + } } void initNumpad(void) @@ -33,7 +39,8 @@ void initNumpad(void) numpadMenuFrequency = 0; drawNumpad(); initSelector(&numpadMenuSelectedItemRaw, - &numpadMenuGrid, + numpadMenuButtons, + NUMPAD_MENU_NUM_BUTTONS, MorsePlaybackType_e::PlayChar); } @@ -44,25 +51,18 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button, { if(ButtonPress_e::NotPressed != tuner_button){ //We treat long and short presses the same, so no need to have a switch - - ButtonGrid_t button_grid; - memcpy_P(&button_grid,&numpadMenuGrid,sizeof(button_grid)); - uint8_t menu_index = numpadMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + Button button; Button* bp; - memcpy_P(&bp,&(button_grid.buttons_P[menu_index]),sizeof(bp)); - - if(nullptr != bp){ - Button button; - memcpy_P(&button,bp,sizeof(button)); - button.on_select(); - } + memcpy_P(&bp,&(numpadMenuButtons[menu_index]),sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + button.on_select(); }//tuner_button else if(ButtonPress_e::NotPressed != touch_button){ //We treat long and short presses the same, so no need to have a switch Button button; - if(findPressedButton(&numpadMenuGrid,&button,touch_point)){ + if(findPressedButton(numpadMenuButtons,NUMPAD_MENU_NUM_BUTTONS,&button,touch_point)){ button.on_select(); } else{ @@ -73,7 +73,8 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button, else{//Neither button input type found, so handle the knob adjustSelector(&numpadMenuSelectedItemRaw, knob, - &numpadMenuGrid, + numpadMenuButtons, + NUMPAD_MENU_NUM_BUTTONS, MorsePlaybackType_e::PlayChar); } diff --git a/menu_numpad_buttons.cpp b/menu_numpad_buttons.cpp index 2946fdd..252eaa6 100644 --- a/menu_numpad_buttons.cpp +++ b/menu_numpad_buttons.cpp @@ -27,11 +27,15 @@ uint32_t numpadMenuFrequency; #define D_STRINGIFY(x) #x #define D_STRING(x) D_STRINGIFY(x) -#define NUMBER_BUTTON_GENERATE(number) \ +#define NUMBER_BUTTON_GENERATE(number,x,y) \ constexpr char txt##number [] PROGMEM = "" D_STRING(number);\ ButtonStatus_e bs##number();\ void os##number();\ constexpr Button b##number PROGMEM = {\ + LAYOUT_BUTTON_X + x*LAYOUT_BUTTON_PITCH_X,\ + LAYOUT_BUTTON_Y + y*LAYOUT_BUTTON_PITCH_Y,\ + LAYOUT_BUTTON_WIDTH,\ + LAYOUT_BUTTON_HEIGHT,\ txt##number,\ nullptr,\ bsNumpad,\ @@ -43,20 +47,28 @@ ButtonStatus_e bsNumpad(void){ return ButtonStatus_e::Stateless; } -NUMBER_BUTTON_GENERATE(1); -NUMBER_BUTTON_GENERATE(2); -NUMBER_BUTTON_GENERATE(3); -NUMBER_BUTTON_GENERATE(4); -NUMBER_BUTTON_GENERATE(5); -NUMBER_BUTTON_GENERATE(6); -NUMBER_BUTTON_GENERATE(7); -NUMBER_BUTTON_GENERATE(8); -NUMBER_BUTTON_GENERATE(9); -NUMBER_BUTTON_GENERATE(0); + +// 1 2 3 Ok +// 4 5 6 0 <- +// 7 8 9 Can +NUMBER_BUTTON_GENERATE(1,0,0); +NUMBER_BUTTON_GENERATE(2,1,0); +NUMBER_BUTTON_GENERATE(3,2,0); +NUMBER_BUTTON_GENERATE(4,0,1); +NUMBER_BUTTON_GENERATE(5,1,1); +NUMBER_BUTTON_GENERATE(6,2,1); +NUMBER_BUTTON_GENERATE(7,0,2); +NUMBER_BUTTON_GENERATE(8,1,2); +NUMBER_BUTTON_GENERATE(9,2,2); +NUMBER_BUTTON_GENERATE(0,3,1); constexpr char txtOk [] PROGMEM = "OK"; void osOk(); constexpr Button bOk PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 0*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtOk, nullptr, bsNumpad, @@ -67,6 +79,10 @@ constexpr Button bOk PROGMEM = { constexpr char txtBackspace [] PROGMEM = "<-"; void osBackspace(); constexpr Button bBackspace PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 1*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtBackspace, nullptr, bsNumpad, @@ -77,6 +93,10 @@ constexpr Button bBackspace PROGMEM = { constexpr char txtCancel [] PROGMEM = "Can"; void osCancel(); constexpr Button bCancel PROGMEM = { + LAYOUT_BUTTON_X + 4*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, txtCancel, nullptr, bsNumpad, @@ -86,22 +106,10 @@ constexpr Button bCancel PROGMEM = { //Declare in menu select order, not graphical order const Button* const numpadMenuButtons [] PROGMEM = { - &b1, &b2, &b3, nullptr, &bOk, - &b4, &b5, &b6, &b0, &bBackspace, - &b7, &b8, &b9, nullptr, &bCancel -}; - -const ButtonGrid_t numpadMenuGrid PROGMEM = { - LAYOUT_BUTTON_X, - LAYOUT_BUTTON_Y, - LAYOUT_BUTTON_WIDTH, - LAYOUT_BUTTON_HEIGHT, - LAYOUT_BUTTON_PITCH_X, - LAYOUT_BUTTON_PITCH_Y, - 3,//rows - 5,//cols - numpadMenuButtons + &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8, &b9, &b0, + &bOk, &bBackspace, &bCancel }; +const uint8_t NUMPAD_MENU_NUM_BUTTONS = sizeof(numpadMenuButtons)/sizeof(numpadMenuButtons[0]); void updateCurrentEnteredFrequency(void) { diff --git a/menu_numpad_buttons.h b/menu_numpad_buttons.h index c813437..a7d555e 100644 --- a/menu_numpad_buttons.h +++ b/menu_numpad_buttons.h @@ -2,9 +2,10 @@ #include -#include "button_grid.h" +#include "button.h" -extern const ButtonGrid_t numpadMenuGrid; +extern const Button* const numpadMenuButtons[]; +extern const uint8_t NUMPAD_MENU_NUM_BUTTONS; extern const uint32_t NUMPAD_MENU_EXIT_FREQ; extern uint32_t numpadMenuFrequency; diff --git a/menu_utils.cpp b/menu_utils.cpp index dfda9e2..d5fcf6e 100644 --- a/menu_utils.cpp +++ b/menu_utils.cpp @@ -2,80 +2,40 @@ #include -#include "button_grid.h" +#include "button.h" #include "color_theme.h" #include "morse.h" #include "nano_gui.h" #include "utils.h" -bool findPressedButton(const ButtonGrid_t *const button_grid_P, +bool findPressedButton(const Button* const* buttons, + const uint8_t num_buttons, Button *const button_out, const Point touch_point) { - ButtonGrid_t button_grid; - memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); - - if((touch_point.x < button_grid.top_left_x) - ||(touch_point.y < button_grid.top_left_y) - ||(touch_point.x > (int16_t)button_grid.button_pitch_x * button_grid.num_button_cols) - ||(touch_point.y > (int16_t)button_grid.button_pitch_y * button_grid.num_button_rows)){ - //touch point was outside the button grid - return false; - } - - uint8_t row = (touch_point.x - button_grid.top_left_x) / button_grid.button_pitch_x; - uint8_t col = (touch_point.y - button_grid.top_left_y) / button_grid.button_pitch_y; - int16_t x_max = (col * button_grid.button_pitch_x) + button_grid.button_width; - int16_t y_max = (row * button_grid.button_pitch_y) + button_grid.button_height; - if((touch_point.x > x_max) - ||(touch_point.y > y_max)){ - //touch point was outside of the button - return false; - } - Button* bp; - memcpy_P(&bp,&(button_grid.buttons_P[row * button_grid.num_button_cols + col]),sizeof(bp)); - if(nullptr == bp){ - //no button there - return false; + for(uint16_t i = 0; i < num_buttons; ++i){ + memcpy_P(&bp,&(buttons[i]),sizeof(bp)); + memcpy_P(button_out,bp,sizeof(*button_out)); + if((button_out->x <= touch_point.x) + &&(touch_point.x <= button_out->x + button_out->w) + &&(button_out->y <= touch_point.y) + &&(touch_point.y <= button_out->y + button_out->h)){ + return true; + } } - memcpy_P(button_out,bp,sizeof(*button_out)); - return true; + return false; } -void indexToRowCol(const ButtonGrid_t *const button_grid, - const int8_t index, - uint8_t *const row_out, - uint8_t *const col_out) +void movePuck(const Button *const b_old, + const Button *const b_new) { - *row_out = index / button_grid->num_button_cols; - *col_out = index % button_grid->num_button_cols; -} - -void movePuck(const ButtonGrid_t *const button_grid, - const int8_t old_index, - const int8_t new_index) -{ - if(-1 != old_index){ - uint8_t row; - uint8_t col; - indexToRowCol(button_grid,old_index,&row,&col); - displayRect(button_grid->top_left_x + button_grid->button_pitch_x * col, - button_grid->top_left_y + button_grid->button_pitch_y * row, - button_grid->button_width, - button_grid->button_height, - COLOR_INACTIVE_BORDER); + if(nullptr != b_old){ + displayRect(b_old->x,b_old->y,b_old->w,b_old->h,COLOR_INACTIVE_BORDER); } - if(-1 != new_index){ - uint8_t row; - uint8_t col; - indexToRowCol(button_grid,new_index,&row,&col); - displayRect(button_grid->top_left_x + button_grid->button_pitch_x * col, - button_grid->top_left_y + button_grid->button_pitch_y * row, - button_grid->button_width, - button_grid->button_height, - COLOR_ACTIVE_BORDER); + if(nullptr != b_new){ + displayRect(b_new->x,b_new->y,b_new->w,b_new->h,COLOR_ACTIVE_BORDER); } } @@ -99,72 +59,45 @@ void playButtonMorse(const Button *const button, } void initSelector(int16_t *const raw_select_val_in_out, - const ButtonGrid_t *const button_grid_P, + const Button* const* buttons, + const uint8_t num_buttons, const MorsePlaybackType_e play_type) { - ButtonGrid_t button_grid; - memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); - *raw_select_val_in_out = 0; - - if(0 < button_grid.num_button_rows * button_grid.num_button_cols){ + if(0 < num_buttons){ Button button; Button* bp; - memcpy_P(&bp,&(button_grid.buttons_P[0]),sizeof(bp)); + memcpy_P(&bp,&(buttons[0]),sizeof(bp)); memcpy_P(&button,bp,sizeof(button)); - movePuck(&button_grid,-1,0); + movePuck(nullptr,&button); playButtonMorse(&button,play_type); } } void adjustSelector(int16_t *const raw_select_val_in_out, - int16_t knob, - const ButtonGrid_t *const button_grid_P, + const int16_t knob, + const Button* const* buttons, + const uint8_t num_buttons, const MorsePlaybackType_e play_type) { - ButtonGrid_t button_grid; - memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); - - const uint8_t num_buttons = button_grid.num_button_rows * button_grid.num_button_cols; const uint8_t prev_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; - *raw_select_val_in_out += knob; - bool keep_trying = true; - while(keep_trying){ - *raw_select_val_in_out = LIMIT(*raw_select_val_in_out,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1); - const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; - if(prev_select != new_select){ - Button* bp; - memcpy_P(&bp,&(button_grid.buttons_P[new_select]),sizeof(bp)); - if(nullptr == bp){ - if(new_select > prev_select){ - *raw_select_val_in_out += MENU_KNOB_COUNTS_PER_ITEM; - } - else{ - *raw_select_val_in_out -= MENU_KNOB_COUNTS_PER_ITEM; - } - if((*raw_select_val_in_out <= 0) - ||(*raw_select_val_in_out >= num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1)){ - keep_trying = false; - } - continue; - } - - Button new_button; - memcpy_P(&new_button,bp,sizeof(new_button)); - - movePuck(&button_grid,prev_select,new_select); - playButtonMorse(&new_button,play_type); - } + *raw_select_val_in_out = LIMIT((*raw_select_val_in_out)+knob,0,num_buttons*MENU_KNOB_COUNTS_PER_ITEM - 1); + const uint8_t new_select = (*raw_select_val_in_out)/MENU_KNOB_COUNTS_PER_ITEM; + if(prev_select != new_select){ + Button prev_button; + Button* bp; + memcpy_P(&bp,&(buttons[prev_select]),sizeof(bp)); + memcpy_P(&prev_button,bp,sizeof(prev_button)); + Button new_button; + memcpy_P(&bp,&(buttons[new_select]),sizeof(bp)); + memcpy_P(&new_button,bp,sizeof(new_button)); + + movePuck(&prev_button,&new_button); + playButtonMorse(&new_button,play_type); } } -void endSelector(const int16_t raw_select, - const ButtonGrid_t *const button_grid_P) +void endSelector(const Button *const button) { - ButtonGrid_t button_grid; - memcpy_P(&button_grid,button_grid_P,sizeof(button_grid)); - - uint8_t index = raw_select/MENU_KNOB_COUNTS_PER_ITEM; - - movePuck(&button_grid,index,-1); + movePuck(button,nullptr); } diff --git a/menu_utils.h b/menu_utils.h index 0a6f55c..d84be30 100644 --- a/menu_utils.h +++ b/menu_utils.h @@ -1,10 +1,11 @@ #pragma once -#include "button_grid.h" +#include "button.h" #include "menu.h" //Returns true if button was found, false otherwise -bool findPressedButton(const ButtonGrid_t *const button_grid_P, +bool findPressedButton(const Button* const* buttons, + const uint8_t num_buttons, Button *const button_out, const Point touch_point); @@ -13,13 +14,14 @@ enum MorsePlaybackType_e : uint8_t { PlayText }; void initSelector(int16_t *const raw_select_val_in_out, - const ButtonGrid_t *const button_grid_P, - const MorsePlaybackType_e play_type); + const Button* const* buttons, + const uint8_t num_buttons, + const MorsePlaybackType_e); void adjustSelector(int16_t *const raw_select_val_in_out, int16_t knob, - const ButtonGrid_t *const button_grid_P, - const MorsePlaybackType_e play_type); + const Button* const* buttons, + const uint8_t num_buttons, + const MorsePlaybackType_e); -void endSelector(const int16_t raw_select, - const ButtonGrid_t *const button_grid_P); +void endSelector(const Button *const button); From 4e7d1717e042cfd56b1003572dd1b710604ade81 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 20:31:10 -0700 Subject: [PATCH 252/324] Re-add version to main display, add callsign display, and re-enable TX indicator --- callsign.cpp | 4 ++++ callsign.h | 9 +++++++++ menu_main.cpp | 3 +++ menu_main_buttons.cpp | 25 +++++++++++++++++++++++++ menu_main_buttons.h | 3 +++ tmp.cpp | 1 - 6 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 callsign.cpp create mode 100644 callsign.h diff --git a/callsign.cpp b/callsign.cpp new file mode 100644 index 0000000..d9d428d --- /dev/null +++ b/callsign.cpp @@ -0,0 +1,4 @@ +#include "callsign.h" + +const char CALLSIGN_STRING_PRIVATE [] PROGMEM = "[CALLSIGN]"; +const char* const CALLSIGN_STRING = CALLSIGN_STRING_PRIVATE; \ No newline at end of file diff --git a/callsign.h b/callsign.h new file mode 100644 index 0000000..481c143 --- /dev/null +++ b/callsign.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +/* + * VERSION_STRING is a PROGMEM string, so extract it before use, e.g. + * strncpy_P(char_buffer_out,VERSION_STRING,size_of_char_buffer_out); + */ +extern const char* const CALLSIGN_STRING; \ No newline at end of file diff --git a/menu_main.cpp b/menu_main.cpp index 8eb010b..102fa86 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -40,6 +40,9 @@ void drawMainMenu(void) memcpy_P(&button,bp,sizeof(button)); drawButton(&button); } + drawVersion(); + drawCallsign(); + ltoa(GetActiveVfoFreq(),b,10); morseText(b); } diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 75fcd89..995d28d 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -6,6 +6,7 @@ #include "bands.h" #include "button.h" +#include "callsign.h" #include "color_theme.h" #include "menu_main.h" #include "menu_numpad.h" @@ -16,6 +17,7 @@ #include "setup.h" #include "tuner.h" #include "utils.h" +#include "version.h" static const unsigned int LAYOUT_VFO_LABEL_X = 0; static const unsigned int LAYOUT_VFO_LABEL_Y = 10; @@ -50,6 +52,29 @@ static const unsigned int LAYOUT_TX_Y = LAYOUT_MODE_TEXT_Y; static const unsigned int LAYOUT_TX_WIDTH = 40; static const unsigned int LAYOUT_TX_HEIGHT = 36; +void drawTx() +{ + if(globalSettings.txActive){ + strncpy_P(b,(const char*)F("TX"),sizeof(b)); + displayText(b,LAYOUT_TX_X,LAYOUT_TX_Y,LAYOUT_TX_WIDTH,LAYOUT_TX_HEIGHT,COLOR_ACTIVE_TEXT,COLOR_ACTIVE_BACKGROUND,COLOR_BACKGROUND); + } + else{ + displayFillrect(LAYOUT_TX_X,LAYOUT_TX_Y,LAYOUT_TX_WIDTH,LAYOUT_TX_HEIGHT,COLOR_BACKGROUND); + } +} + +void drawVersion() +{ + strncpy_P(b,VERSION_STRING,sizeof(b)); + displayText(b,LAYOUT_VERSION_TEXT_X,LAYOUT_VERSION_TEXT_Y,LAYOUT_VERSION_TEXT_WIDTH,LAYOUT_VERSION_TEXT_HEIGHT,COLOR_VERSION_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); +} + +void drawCallsign() +{ + strcpy_P(b,CALLSIGN_STRING); + displayText(b,LAYOUT_CW_TEXT_X,LAYOUT_CW_TEXT_Y,LAYOUT_CW_TEXT_WIDTH,LAYOUT_CW_TEXT_HEIGHT,COLOR_ACTIVE_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); +} + void toVfoA(char* text_out, const uint16_t max_text_size); ButtonStatus_e bsVfoA(); void osVfoA(); diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 0e7febd..7795c82 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -11,3 +11,6 @@ extern const Button bVfoA; extern const Button bVfoB; void updateBandButtons(const uint32_t old_freq); void updateSidebandButtons(); +void drawTx(); +void drawVersion(); +void drawCallsign(); diff --git a/tmp.cpp b/tmp.cpp index 1adaa49..53c8aba 100644 --- a/tmp.cpp +++ b/tmp.cpp @@ -1,3 +1,2 @@ void updateDisplay() {} void redrawVFOs(){} -void drawTx(){} From 85ea71495502a2ea78364100536129a1ec1274b8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 20:31:35 -0700 Subject: [PATCH 253/324] Show current setting on setting screen --- setup.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/setup.cpp b/setup.cpp index 938453a..954b09d 100644 --- a/setup.cpp +++ b/setup.cpp @@ -53,8 +53,13 @@ static const unsigned int LAYOUT_ITEM_WIDTH = 260; static const unsigned int LAYOUT_ITEM_HEIGHT = 30; static const unsigned int LAYOUT_ITEM_PITCH_Y = LAYOUT_ITEM_HEIGHT + 1; +static const unsigned int LAYOUT_SETTING_REF_VALUE_X = LAYOUT_ITEM_X; +static const unsigned int LAYOUT_SETTING_REF_VALUE_Y = LAYOUT_ITEM_Y + 3*LAYOUT_ITEM_PITCH_Y; +static const unsigned int LAYOUT_SETTING_REF_VALUE_WIDTH = LAYOUT_ITEM_WIDTH; +static const unsigned int LAYOUT_SETTING_REF_VALUE_HEIGHT = LAYOUT_ITEM_HEIGHT; + static const unsigned int LAYOUT_SETTING_VALUE_X = LAYOUT_ITEM_X; -static const unsigned int LAYOUT_SETTING_VALUE_Y = LAYOUT_ITEM_Y + 3*LAYOUT_ITEM_PITCH_Y; +static const unsigned int LAYOUT_SETTING_VALUE_Y = LAYOUT_ITEM_Y + 4*LAYOUT_ITEM_PITCH_Y; static const unsigned int LAYOUT_SETTING_VALUE_WIDTH = LAYOUT_ITEM_WIDTH; static const unsigned int LAYOUT_SETTING_VALUE_HEIGHT = LAYOUT_ITEM_HEIGHT; @@ -127,6 +132,7 @@ void initSetting() screen.Initialize(&setupMenuLastValue); screen.OnValueChange(setupMenuLastValue,b,sizeof(b)); displayText(b, LAYOUT_SETTING_VALUE_X, LAYOUT_SETTING_VALUE_Y, LAYOUT_SETTING_VALUE_WIDTH, LAYOUT_SETTING_VALUE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_BACKGROUND); + displayText(b, LAYOUT_SETTING_REF_VALUE_X, LAYOUT_SETTING_REF_VALUE_Y, LAYOUT_SETTING_REF_VALUE_WIDTH, LAYOUT_SETTING_REF_VALUE_HEIGHT, COLOR_SETTING_BACKGROUND, COLOR_BACKGROUND, COLOR_BACKGROUND); setupMenuRawValue = setupMenuLastValue * (int32_t)screen.KnobDivider; } From 1f5f3a1f9fb1f7700ff5b2cfb038c97cbf197334 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 20:34:47 -0700 Subject: [PATCH 254/324] Use safer copy --- menu_main_buttons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 995d28d..9e9162b 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -71,7 +71,7 @@ void drawVersion() void drawCallsign() { - strcpy_P(b,CALLSIGN_STRING); + strncpy_P(b,CALLSIGN_STRING,sizeof(b)); displayText(b,LAYOUT_CW_TEXT_X,LAYOUT_CW_TEXT_Y,LAYOUT_CW_TEXT_WIDTH,LAYOUT_CW_TEXT_HEIGHT,COLOR_ACTIVE_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); } From 06fa0e9ad7f45b9fc12780a36a44bf7500bb7f0c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 21:08:43 -0700 Subject: [PATCH 255/324] Update README --- README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8b7e7e9..c013be8 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,18 @@ -# ubitxv6 -uBitx v6.3.1 Arduino sketch -IMPORTANT: It will compile only if you place this in the Arduino's own sketch directory! This is because of the restricted places that the Arduino searches for it's include files (the headers). +# uBiTXv6 -- This is refactored to remove dependencies on any library except the standard Arduino libraries of SPI, I2C, EEPROM, etc. -- This works with ILI9341 display controller. The pins used by the TFT display are the same as that of the 16x2 LCD display of the previous versions. -- As the files are now split into .cpp files, the nano gui, morse reader, etc. can be reused in other projects as well +This project is found at https://github.com/reedbn/ubitxv6/ -This is released under GPL v3 license. +It was forked from https://github.com/afarhan/ubitxv6/ + +The purpose of this project is to clean up (modularize) the source code, and add features that were not present +in Ashhar's original version of the project, without requiring any hardware modifications to a stock uBiTXv6. + +# Personalized Callsign + +To edit the callsign displayed, open the file `callsign.cpp` and change the string. Then re-compile and upload. + +# License + +The majority of this code is released under GPL v3 license, per Ashhar's original code. + +The files in the PDQ_MinLib subdirectory were copied from https://github.com/XarkLabs/PDQ_GFX_Libs, and have Adafruit's BSD License. From 2a8ff5e758e9fb73f3404b23921a32be9347a280 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 21:09:54 -0700 Subject: [PATCH 256/324] Replace fastest line routines with fillRect to save ~300 bytes --- nano_gui.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index ebd15da..defa833 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -39,15 +39,15 @@ void displayInit(void){ } void displayPixel(unsigned int x, unsigned int y, unsigned int c){ - tft.drawPixel(x,y,c); + tft.fillRect(x,y,1,1,c); } void displayHline(unsigned int x, unsigned int y, unsigned int w, unsigned int c){ - tft.drawFastHLine(x,y,w,c); + tft.fillRect(x,y,w,1,c); } void displayVline(unsigned int x, unsigned int y, unsigned int l, unsigned int c){ - tft.drawFastVLine(x,y,l,c); + tft.fillRect(x,y,1,l,c); } void displayClear(unsigned int color){ @@ -55,7 +55,10 @@ void displayClear(unsigned int color){ } void displayRect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c){ - tft.drawRect(x,y,w,h,c); + tft.fillRect(x,y,w,1,c); + tft.fillRect(x,y,1,h,c); + tft.fillRect(x,y+h-1,w,1,c); + tft.fillRect(x+w-1,y,1,h,c); } void displayFillrect(unsigned int x,unsigned int y,unsigned int w,unsigned int h,unsigned int c){ From 0fe54d054fecc43ee7d230aa56be4cc21177a0d3 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 22:32:17 -0700 Subject: [PATCH 257/324] Add toneAC2 library --- .../examples/toneAC2_demo/toneAC2_demo.pde | 27 +++++++ toneAC2/keywords.txt | 18 +++++ toneAC2/toneAC2.cpp | 64 ++++++++++++++++ toneAC2/toneAC2.h | 73 +++++++++++++++++++ 4 files changed, 182 insertions(+) create mode 100644 toneAC2/examples/toneAC2_demo/toneAC2_demo.pde create mode 100644 toneAC2/keywords.txt create mode 100644 toneAC2/toneAC2.cpp create mode 100644 toneAC2/toneAC2.h diff --git a/toneAC2/examples/toneAC2_demo/toneAC2_demo.pde b/toneAC2/examples/toneAC2_demo/toneAC2_demo.pde new file mode 100644 index 0000000..fa1b6e6 --- /dev/null +++ b/toneAC2/examples/toneAC2_demo/toneAC2_demo.pde @@ -0,0 +1,27 @@ +// --------------------------------------------------------------------------- +// Be sure to include an in-line 100 ohm resistor on one pin as you normally do when connecting a piezo or speaker. +// --------------------------------------------------------------------------- + +#include + +// Melody liberated from the toneMelody Arduino example sketch by Tom Igoe. +int melody[] = { 262, 196, 196, 220, 196, 0, 247, 262 }; +int noteDurations[] = { 4, 8, 8, 4, 4, 4, 4, 4 }; + +void setup() {} // Nothing to setup, just start playing! + +void loop() { + for (unsigned long freq = 125; freq <= 15000; freq += 10) { + toneAC2(2, 3, freq, 1); // Play the frequency (125 Hz to 15 kHz sweep in 10 Hz steps) for 1ms. + } + + delay(1000); // Wait a second. + + for (int thisNote = 0; thisNote < 8; thisNote++) { + int noteDuration = 1000/noteDurations[thisNote]; + toneAC2(2, 3, melody[thisNote], noteDuration, true); // Play thisNote at full volume for noteDuration in the background. + delay(noteDuration * 4 / 3); // Wait while the tone plays in the background, plus another 33% delay between notes. + } + + while(1); // Stop (so it doesn't repeat forever driving you crazy--you're welcome). +} diff --git a/toneAC2/keywords.txt b/toneAC2/keywords.txt new file mode 100644 index 0000000..9930b76 --- /dev/null +++ b/toneAC2/keywords.txt @@ -0,0 +1,18 @@ +################################### +# Syntax Coloring Map For toneAC2 +################################### + +################################### +# Datatypes (KEYWORD1) +################################### + +################################### +# Methods and Functions (KEYWORD2) +################################### + +toneAC2 KEYWORD2 +noToneAC2 KEYWORD2 + +################################### +# Constants (LITERAL1) +################################### diff --git a/toneAC2/toneAC2.cpp b/toneAC2/toneAC2.cpp new file mode 100644 index 0000000..7de7274 --- /dev/null +++ b/toneAC2/toneAC2.cpp @@ -0,0 +1,64 @@ +// --------------------------------------------------------------------------- +// Created by Tim Eckel - teckel@leethost.com +// Copyright 2015 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html +// +// See "toneAC2.h" for purpose, syntax, version history, links, and more. +// --------------------------------------------------------------------------- + +#include "toneAC2.h" + +unsigned long _tAC2_time; // Used to track end note with timer when playing note in the background. +volatile uint8_t *_pinMode1, *_pinMode2; // Pin modes. +uint8_t _pinMask1 = 0, _pinMask2 = 0; // Bitmask for pins. +volatile uint8_t *_pinOutput1, *_pinOutput2; // Output port registers for each pin. +int _tAC2_prescale[] = { 2, 16, 64, 128, 256, 512, 2048 }; // Prescaler. + +void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency, unsigned long length, uint8_t background) { + long top; + uint8_t prescaler; + + for (prescaler = 1; prescaler < 8; prescaler++) { // Find the appropriate prescaler + top = F_CPU / (long) frequency / (long) _tAC2_prescale[prescaler - 1] - 1; // Calculate the top. + if (top < 256) break; // Fits, break out of for loop. + } + if (top > 255) { noToneAC2(); return; } // Frequency is out of range, turn off sound and return. + + if (length > 0) _tAC2_time = millis() + length - 1; else _tAC2_time = 0xFFFFFFFF; // Set when the note should end, or play "forever". + + if (_pinMask1 == 0) { // This gets the port registers and bitmaps for the two pins and sets the pins to output mode. + _pinMask1 = digitalPinToBitMask(pin1); // Get the port register bitmask for pin 1. + _pinMask2 = digitalPinToBitMask(pin2); // Get the port register bitmask for pin 2. + _pinOutput1 = portOutputRegister(digitalPinToPort(pin1)); // Get the output port register for pin 1. + _pinOutput2 = portOutputRegister(digitalPinToPort(pin2)); // Get the output port register for pin 2. + _pinMode1 = (uint8_t *) portModeRegister(digitalPinToPort(pin1)); // Get the port mode register for pin 1. + _pinMode2 = (uint8_t *) portModeRegister(digitalPinToPort(pin2)); // Get the port mode register for pin 2. + *_pinMode1 |= _pinMask1; // Set pin 1 to Output mode. + *_pinMode2 |= _pinMask2; // Set pin 2 to Output mode. + } + + OCR2A = top; // Set the top. + if (TCNT2 > top) TCNT2 = top; // Counter over the top, put within range. + TCCR2B = _BV(WGM22) | prescaler; // Set Fast PWM and prescaler. + TCCR2A = _BV(WGM20) | _BV(WGM21); // Fast PWM and normal port operation, OC2A/OC2B disconnected. + TIMSK2 &= ~_BV(OCIE2A); // Stop timer 2 interrupt while we set the pin states. + if (*_pinOutput1 & _pinMask1) *_pinOutput2 &= ~_pinMask2; // Be sure pins are reversed. + else *_pinOutput2 |= _pinMask2; // Other half of making sure pins are reversed. + TIMSK2 |= _BV(OCIE2A); // Activate the timer interrupt. + + if (length > 0 && !background) { delay(length); noToneAC2(); } // Just a simple delay, doesn't return control till finished. +} + +void noToneAC2() { + TIMSK2 &= ~_BV(OCIE2A); // Remove the timer interrupt. + TCCR2B = _BV(CS22); // Default clock prescaler of 64. + TCCR2A = _BV(WGM20); // Set to defaults so PWM can work like normal (PWM, phase corrected, 8bit). + *_pinMode1 &= ~_pinMask1; // Set pin 1 to INPUT. + *_pinMode2 &= ~_pinMask2; // Set pin 2 to INPUT. + _pinMask1 = 0; // Flag so we know note is no longer playing. +} + +ISR(TIMER2_COMPA_vect) { // Timer interrupt vector. + if (millis() > _tAC2_time) noToneAC2(); // Check to see if it's time for the note to end. + *_pinOutput1 ^= _pinMask1; // Toggle the pin 1 state. + *_pinOutput2 ^= _pinMask2; // Toggle the pin 2 state. +} \ No newline at end of file diff --git a/toneAC2/toneAC2.h b/toneAC2/toneAC2.h new file mode 100644 index 0000000..1d244d6 --- /dev/null +++ b/toneAC2/toneAC2.h @@ -0,0 +1,73 @@ +// --------------------------------------------------------------------------- +// toneAC2 Library - v1.1 - 09/15/2015 +// +// AUTHOR/LICENSE: +// Created by Tim Eckel - teckel@leethost.com +// Copyright 2015 License: GNU GPL v3 http://www.gnu.org/licenses/gpl-3.0.html +// +// LINKS: +// Project home: https://bitbucket.org/teckel12/arduino-toneac/wiki/Home +// Blog: http://forum.arduino.cc/index.php?topic=142097.0 +// +// DISCLAIMER: +// This software is furnished "as is", without technical support, and with no +// warranty, express or implied, as to its usefulness for any purpose. +// +// PURPOSE: +// Replacement to the standard tone library with the advantage of nearly twice +// the volume, 800 bytes smaller compiled code size, and less stress on the +// speaker. This alternate version uses timer 2 and allows for flexible pin +// assignment. The primary version (toneAC) allows for higher frequencies, +// higher quality, and even smaller code size. However, toneAC is fixed to +// using the PWM timer 1 pins unlike toneAC2 which can use any two pins. Both +// exclusively use port registers for the fast and smallest code possible. +// +// USAGE: +// Connection is very similar to a piezo or standard speaker. Except, instead +// of connecting one speaker wire to ground you connect both speaker wires to +// Arduino pins. Unlike toneAC, with toneAC2 you can connect to any two pins. +// Just as usual when connecting a speaker, make sure you add an in-line 100 +// ohm resistor between one of the pins and the speaker wire. +// +// SYNTAX: +// toneAC2( pin1, pin2, frequency [, length [, background ]] ) - Play a note. +// Parameters: +// * pin1 - Pin to attach one of the speaker wires. +// * pin2 - Pin to attach the other speaker wire. +// * frequency - Play the specified frequency indefinitely, turn off with noToneAC2(). +// * length - [optional] Set the length to play in milliseconds. (default: 0 [forever], range: 0 to 2^32-1) +// * background - [optional] Play note in background or pause till finished? (default: false, values: true/false) +// noToneAC2() - Stop playing. +// +// HISTORY: +// 09/15/2015 v1.1 - Fix a potential race condition with _tAC2_time. Moved +// development to Bitbucket. +// +// 01/27/2013 v1.0 - Initial release. +// +// --------------------------------------------------------------------------- + +#ifndef toneAC2_h + #define toneAC2_h + + #if defined(ARDUINO) && ARDUINO >= 100 + #include + #else + #include + #endif + + // This doesn't currently work. Would require more work than simply doing this. + #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) + #define TCCR2A TCCR2 + #define TCCR2B TCCR2 + #define TIMSK2 TIMSK + #define COM2A1 COM21 + #define COM2A0 COM20 + #define OCIE2A OCIE2 + #define OCR2A OCR2 + #define TIMER2_COMPA_vect TIMER2_COMP_vect + #endif + + void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency = 0, unsigned long length = 0, uint8_t background = false); + void noToneAC2(); +#endif \ No newline at end of file From da456430355ab1c80d70efe4da8be4cb57d1a0b9 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 22:36:17 -0700 Subject: [PATCH 258/324] Remove secondary pin from library --- toneAC2/toneAC2.cpp | 16 ++++------------ toneAC2/toneAC2.h | 2 +- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/toneAC2/toneAC2.cpp b/toneAC2/toneAC2.cpp index 7de7274..39c5732 100644 --- a/toneAC2/toneAC2.cpp +++ b/toneAC2/toneAC2.cpp @@ -8,12 +8,12 @@ #include "toneAC2.h" unsigned long _tAC2_time; // Used to track end note with timer when playing note in the background. -volatile uint8_t *_pinMode1, *_pinMode2; // Pin modes. -uint8_t _pinMask1 = 0, _pinMask2 = 0; // Bitmask for pins. -volatile uint8_t *_pinOutput1, *_pinOutput2; // Output port registers for each pin. +volatile uint8_t *_pinMode1; // Pin modes. +uint8_t _pinMask1 = 0; // Bitmask for pins. +volatile uint8_t *_pinOutput1; // Output port registers for each pin. int _tAC2_prescale[] = { 2, 16, 64, 128, 256, 512, 2048 }; // Prescaler. -void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency, unsigned long length, uint8_t background) { +void toneAC2(uint8_t pin1, unsigned int frequency, unsigned long length, uint8_t background) { long top; uint8_t prescaler; @@ -27,13 +27,9 @@ void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency, unsigned long l if (_pinMask1 == 0) { // This gets the port registers and bitmaps for the two pins and sets the pins to output mode. _pinMask1 = digitalPinToBitMask(pin1); // Get the port register bitmask for pin 1. - _pinMask2 = digitalPinToBitMask(pin2); // Get the port register bitmask for pin 2. _pinOutput1 = portOutputRegister(digitalPinToPort(pin1)); // Get the output port register for pin 1. - _pinOutput2 = portOutputRegister(digitalPinToPort(pin2)); // Get the output port register for pin 2. _pinMode1 = (uint8_t *) portModeRegister(digitalPinToPort(pin1)); // Get the port mode register for pin 1. - _pinMode2 = (uint8_t *) portModeRegister(digitalPinToPort(pin2)); // Get the port mode register for pin 2. *_pinMode1 |= _pinMask1; // Set pin 1 to Output mode. - *_pinMode2 |= _pinMask2; // Set pin 2 to Output mode. } OCR2A = top; // Set the top. @@ -41,8 +37,6 @@ void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency, unsigned long l TCCR2B = _BV(WGM22) | prescaler; // Set Fast PWM and prescaler. TCCR2A = _BV(WGM20) | _BV(WGM21); // Fast PWM and normal port operation, OC2A/OC2B disconnected. TIMSK2 &= ~_BV(OCIE2A); // Stop timer 2 interrupt while we set the pin states. - if (*_pinOutput1 & _pinMask1) *_pinOutput2 &= ~_pinMask2; // Be sure pins are reversed. - else *_pinOutput2 |= _pinMask2; // Other half of making sure pins are reversed. TIMSK2 |= _BV(OCIE2A); // Activate the timer interrupt. if (length > 0 && !background) { delay(length); noToneAC2(); } // Just a simple delay, doesn't return control till finished. @@ -53,12 +47,10 @@ void noToneAC2() { TCCR2B = _BV(CS22); // Default clock prescaler of 64. TCCR2A = _BV(WGM20); // Set to defaults so PWM can work like normal (PWM, phase corrected, 8bit). *_pinMode1 &= ~_pinMask1; // Set pin 1 to INPUT. - *_pinMode2 &= ~_pinMask2; // Set pin 2 to INPUT. _pinMask1 = 0; // Flag so we know note is no longer playing. } ISR(TIMER2_COMPA_vect) { // Timer interrupt vector. if (millis() > _tAC2_time) noToneAC2(); // Check to see if it's time for the note to end. *_pinOutput1 ^= _pinMask1; // Toggle the pin 1 state. - *_pinOutput2 ^= _pinMask2; // Toggle the pin 2 state. } \ No newline at end of file diff --git a/toneAC2/toneAC2.h b/toneAC2/toneAC2.h index 1d244d6..f186d48 100644 --- a/toneAC2/toneAC2.h +++ b/toneAC2/toneAC2.h @@ -68,6 +68,6 @@ #define TIMER2_COMPA_vect TIMER2_COMP_vect #endif - void toneAC2(uint8_t pin1, uint8_t pin2, unsigned int frequency = 0, unsigned long length = 0, uint8_t background = false); + void toneAC2(uint8_t pin1, unsigned int frequency = 0, unsigned long length = 0, uint8_t background = false); void noToneAC2(); #endif \ No newline at end of file From 7a788b6297ed7ea46ed3c472d4bc43f1857d948f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 22:36:40 -0700 Subject: [PATCH 259/324] Proxy the tone library so that it builds --- toneAC2Proxy.cpp | 1 + 1 file changed, 1 insertion(+) create mode 100644 toneAC2Proxy.cpp diff --git a/toneAC2Proxy.cpp b/toneAC2Proxy.cpp new file mode 100644 index 0000000..5e118f1 --- /dev/null +++ b/toneAC2Proxy.cpp @@ -0,0 +1 @@ +#include "toneAC2/toneAC2.cpp" From 2c4448f6a0c4cf2e4af4e52b177eb0a31fca601a Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 22:44:26 -0700 Subject: [PATCH 260/324] Replace calls to the default Arduino Tone library to toneAC2, saving over 1024 bytes --- keyer.cpp | 6 +++--- morse.cpp | 10 +++++----- setup.cpp | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index d7d798f..45e5c22 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -1,4 +1,4 @@ -#include +#include "toneAC2/toneAC2.h" #include "pin_definitions.h" #include "settings.h" #include "tuner.h" @@ -45,7 +45,7 @@ static const unsigned int cwAdcDashTo = 800; * each time it is called, the cwTimeOut is pushed further into the future */ void cwKeydown(){ - tone(PIN_CW_TONE, globalSettings.cwSideToneFreq); + toneAC2(PIN_CW_TONE, globalSettings.cwSideToneFreq); digitalWrite(PIN_CW_KEY, 1); globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; @@ -56,7 +56,7 @@ void cwKeydown(){ * Pushes the cwTimeout further into the future */ void cwKeyUp(){ - noTone(PIN_CW_TONE); + noToneAC2(); digitalWrite(PIN_CW_KEY, 0); globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; diff --git a/morse.cpp b/morse.cpp index b8c2b20..eb7d9e6 100644 --- a/morse.cpp +++ b/morse.cpp @@ -1,4 +1,4 @@ -#include //tone +#include "toneAC2/toneAC2.h" #include "encoder.h" #include "morse.h" @@ -86,7 +86,7 @@ void morseLetter(char c, uint16_t dit_duration_ms){ //now we are at the first zero, skip and carry on mask = mask >> 1; while(mask){ - tone(PIN_CW_TONE, globalSettings.cwSideToneFreq,10000); + toneAC2(PIN_CW_TONE, globalSettings.cwSideToneFreq); if (mask & code){ delay(3 * dit_duration_ms); //Serial.print('-'); @@ -96,7 +96,7 @@ void morseLetter(char c, uint16_t dit_duration_ms){ //Serial.print('.'); } //Serial.print('#'); - noTone(PIN_CW_TONE); + noToneAC2(); delay(dit_duration_ms); // space between dots and dashes mask = mask >> 1; } @@ -122,8 +122,8 @@ void morseBool(bool val){ if(!globalSettings.morseMenuOn){ return; } - tone(PIN_CW_TONE, globalSettings.cwSideToneFreq + (val ? RELATIVE_OFFSET_HZ : -RELATIVE_OFFSET_HZ)); + toneAC2(PIN_CW_TONE, globalSettings.cwSideToneFreq + (val ? RELATIVE_OFFSET_HZ : -RELATIVE_OFFSET_HZ)); delay(3*globalSettings.cwDitDurationMs); - noTone(PIN_CW_TONE); + noToneAC2(); delay(3*globalSettings.cwDitDurationMs); } diff --git a/setup.cpp b/setup.cpp index 954b09d..c0b58de 100644 --- a/setup.cpp +++ b/setup.cpp @@ -1,4 +1,4 @@ -#include +#include "toneAC2/toneAC2.h" #include "colors.h" #include "encoder.h" #include "menu.h" @@ -279,13 +279,13 @@ void ssCwToneValidate(const long int candidate_value_in, long int* validated_val void ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_out_size) { globalSettings.cwSideToneFreq = new_value; - tone(PIN_CW_TONE, globalSettings.cwSideToneFreq); + toneAC2(PIN_CW_TONE, globalSettings.cwSideToneFreq); ltoa(globalSettings.cwSideToneFreq,buff_out,10); strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); } void ssCwToneFinalize(const long int final_value) { - noTone(PIN_CW_TONE); + noToneAC2(); globalSettings.cwSideToneFreq = final_value; SaveSettingsToEeprom(); } From c45a824276fa4e1ed474ecc5d8680fcca6f9007c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 22:52:39 -0700 Subject: [PATCH 261/324] Switch back to nicer font --- nano_font.cpp | 8 ++++---- nano_gui.cpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/nano_font.cpp b/nano_font.cpp index 67fe89b..b292824 100644 --- a/nano_font.cpp +++ b/nano_font.cpp @@ -1,12 +1,12 @@ #include "nano_font.h" #include -//#include "PDQ_MinLib/FreeSansBold9pt7b.h" +#include "PDQ_MinLib/FreeSansBold9pt7b.h" //#include "PDQ_MinLib/Picopixel.h" //#include "PDQ_MinLib/org_01.h" -#include "PDQ_MinLib/TomThumb.h" +//#include "PDQ_MinLib/TomThumb.h" -//const GFXfont* ubitx_font = &FreeSansBold9pt7b; +const GFXfont* ubitx_font = &FreeSansBold9pt7b; //const GFXfont* ubitx_font = &Picopixel; //const GFXfont* ubitx_font = &Org_01; -const GFXfont* ubitx_font = &TomThumb; +//const GFXfont* ubitx_font = &TomThumb; diff --git a/nano_gui.cpp b/nano_gui.cpp index defa833..64cba7b 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -34,7 +34,7 @@ void displayInit(void){ tft.setFont(ubitx_font); tft.setTextWrap(true); tft.setTextColor(DISPLAY_GREEN,DISPLAY_BLACK); - tft.setTextSize(3); + tft.setTextSize(1); tft.setRotation(1); } From bd1ff23d8f1e95d669b5cdc658a6fd40d7dad228 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 22:55:10 -0700 Subject: [PATCH 262/324] Add comment about toneAC2 library license --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c013be8..23ca865 100644 --- a/README.md +++ b/README.md @@ -16,3 +16,5 @@ To edit the callsign displayed, open the file `callsign.cpp` and change the stri The majority of this code is released under GPL v3 license, per Ashhar's original code. The files in the PDQ_MinLib subdirectory were copied from https://github.com/XarkLabs/PDQ_GFX_Libs, and have Adafruit's BSD License. + +The files in the toneAC2 were copied from https://bitbucket.org/teckel12/arduino-toneac2/wiki/Home, and are GPL v3 licensed. From e85db6781ad466cffec1facfae8c27fa5c9326cc Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 22:56:35 -0700 Subject: [PATCH 263/324] Use same color for version and callsign for better callsign visibility --- menu_main_buttons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 9e9162b..20b8b2b 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -72,7 +72,7 @@ void drawVersion() void drawCallsign() { strncpy_P(b,CALLSIGN_STRING,sizeof(b)); - displayText(b,LAYOUT_CW_TEXT_X,LAYOUT_CW_TEXT_Y,LAYOUT_CW_TEXT_WIDTH,LAYOUT_CW_TEXT_HEIGHT,COLOR_ACTIVE_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); + displayText(b,LAYOUT_CW_TEXT_X,LAYOUT_CW_TEXT_Y,LAYOUT_CW_TEXT_WIDTH,LAYOUT_CW_TEXT_HEIGHT,COLOR_VERSION_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); } void toVfoA(char* text_out, const uint16_t max_text_size); From 6cd72a5b8acc3c2ec73d257e964d5a3f6a9a6e54 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 25 Apr 2020 23:06:16 -0700 Subject: [PATCH 264/324] Update sideband selection graphic on band switch --- menu_main_buttons.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 20b8b2b..f28d59e 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -405,6 +405,7 @@ void osVfo(const Vfo_e vfo){ memcpy_P(&button,&bVfoB,sizeof(button)); drawButton(&button); updateBandButtons(old_freq); + updateSidebandButtons(); } void toVfoA(char* text_out, const uint16_t max_text_size){ From b1e4466b0e363253ae74e6db3cd3f2685e2c9fe6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 14:31:09 -0700 Subject: [PATCH 265/324] Remove ornamental borders on setup page --- setup.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/setup.cpp b/setup.cpp index c0b58de..024aff0 100644 --- a/setup.cpp +++ b/setup.cpp @@ -32,19 +32,9 @@ static const unsigned int COLOR_SETTING_BACKGROUND = DISPLAY_NAVY; static const unsigned int COLOR_ACTIVE_BORDER = DISPLAY_WHITE; static const unsigned int COLOR_INACTIVE_BORDER = COLOR_BACKGROUND; -static const unsigned int LAYOUT_OUTER_BORDER_X = 10; -static const unsigned int LAYOUT_OUTER_BORDER_Y = 10; -static const unsigned int LAYOUT_OUTER_BORDER_WIDTH = 300; -static const unsigned int LAYOUT_OUTER_BORDER_HEIGHT = 220; - -static const unsigned int LAYOUT_INNER_BORDER_X = 12; -static const unsigned int LAYOUT_INNER_BORDER_Y = 12; -static const unsigned int LAYOUT_INNER_BORDER_WIDTH = 296; -static const unsigned int LAYOUT_INNER_BORDER_HEIGHT = 216; - -static const unsigned int LAYOUT_TITLE_X = LAYOUT_INNER_BORDER_X; -static const unsigned int LAYOUT_TITLE_Y = LAYOUT_INNER_BORDER_Y; -static const unsigned int LAYOUT_TITLE_WIDTH = LAYOUT_INNER_BORDER_WIDTH; +static const unsigned int LAYOUT_TITLE_X = 12; +static const unsigned int LAYOUT_TITLE_Y = 12; +static const unsigned int LAYOUT_TITLE_WIDTH = 296; static const unsigned int LAYOUT_TITLE_HEIGHT = 35; static const unsigned int LAYOUT_ITEM_X = 30; @@ -66,7 +56,7 @@ static const unsigned int LAYOUT_SETTING_VALUE_HEIGHT = LAYOUT_ITEM_HEIGHT; static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_X = 20; static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_Y = LAYOUT_ITEM_Y; static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_WIDTH = LAYOUT_ITEM_WIDTH; -static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_HEIGHT = LAYOUT_SETTING_VALUE_Y - LAYOUT_ITEM_Y - 1; +static const unsigned int LAYOUT_INSTRUCTIONS_TEXT_HEIGHT = LAYOUT_SETTING_REF_VALUE_Y - LAYOUT_ITEM_Y - 1; static const unsigned int LAYOUT_CONFIRM_TEXT_X = 20; static const unsigned int LAYOUT_CONFIRM_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_ITEM_PITCH_Y; @@ -76,8 +66,6 @@ static const unsigned int LAYOUT_CONFIRM_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT; void displayDialog(const char* title, const char* instructions){ displayClear(COLOR_BACKGROUND); - displayRect(LAYOUT_OUTER_BORDER_X,LAYOUT_OUTER_BORDER_Y,LAYOUT_OUTER_BORDER_WIDTH,LAYOUT_OUTER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); - displayRect(LAYOUT_INNER_BORDER_X,LAYOUT_INNER_BORDER_Y,LAYOUT_INNER_BORDER_WIDTH,LAYOUT_INNER_BORDER_HEIGHT, COLOR_ACTIVE_BORDER); strncpy_P(b,title,sizeof(b)); displayText(b, LAYOUT_TITLE_X, LAYOUT_TITLE_Y, LAYOUT_TITLE_WIDTH, LAYOUT_TITLE_HEIGHT, COLOR_TEXT, COLOR_TITLE_BACKGROUND, COLOR_ACTIVE_BORDER); strncpy_P(b,instructions,sizeof(b)); From f9907cebdeef44aef2201a44c25bcf951eb34567 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 15:03:18 -0700 Subject: [PATCH 266/324] Add icons for numpad and star --- PDQ_MinLib/FreeSansBold9pt7b.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/PDQ_MinLib/FreeSansBold9pt7b.h b/PDQ_MinLib/FreeSansBold9pt7b.h index 8758ba8..4fda0a5 100644 --- a/PDQ_MinLib/FreeSansBold9pt7b.h +++ b/PDQ_MinLib/FreeSansBold9pt7b.h @@ -105,7 +105,12 @@ const uint8_t FreeSansBold9pt7bBitmaps[] PROGMEM = { 0x1C, 0xF3, 0x83, 0xFF, 0xFC, 0x7F, 0xFF, 0xE3, 0xF0, 0xFE, 0x1E, 0x07, 0xC1, 0xC0, 0x38, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0x1C, 0x03, 0x81, 0xE0, 0x78, 0x3F, 0x0F, 0xC7, 0xFF, 0xFE, 0x3F, - 0xFF, 0xC3, 0xCF, 0x38, 0x08, 0xF1, 0x00, 0x0F, 0x00 + 0xFF, 0xC3, 0xCF, 0x38, 0x08, 0xF1, 0x00, 0x0F, 0x00, 0x00, 0xEE, 0xFD, + 0xDF, 0xBB, 0x80, 0x0E, 0xEF, 0xDD, 0xFB, 0xB8, 0x00, 0xEE, 0xFD, 0xDF, + 0xBB, 0x80, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x00, 0x01, 0x00, 0x02, 0x00, + 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x1F, 0xFF, 0xDF, 0xFF, 0x0F, 0xF8, 0x0F, + 0xE0, 0x1F, 0xC0, 0x3F, 0x80, 0x7F, 0x01, 0xEF, 0x03, 0x06, 0x04, 0x04, + 0x00 }; const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { @@ -207,12 +212,14 @@ const GFXglyph FreeSansBold9pt7bGlyphs[] PROGMEM = { { 1231, 20, 20, 22, 1, -12 }, // 0x7F gear icon { 1231, 0, 0, 10, 0, 1 }, // 0x80 10px space to match numbers { 1231, 0, 0, 4, 0, 1 }, // 0x81 4px space to match period + { 1282, 11, 15, 13, 1, -10 }, // 0x82 numpad icon + { 1304, 15, 15, 17, 1, -10 }, // 0x83 star icon }; const GFXfont FreeSansBold9pt7b PROGMEM = { (uint8_t *)FreeSansBold9pt7bBitmaps, (GFXglyph *)FreeSansBold9pt7bGlyphs, 0x20, //first character - 0x81, //last character + 0x83, //last character 22 //yAdvance (newline) }; From 8cc272b0655aa5d96afeea0dcd6b19c09fa3b1b7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 15:03:32 -0700 Subject: [PATCH 267/324] Use numpad icon --- menu_main_buttons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index f28d59e..17cd3b6 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -300,7 +300,7 @@ constexpr Button bMenu PROGMEM = { 'M' }; -constexpr char txtNumpad [] PROGMEM = "FRQ"; +constexpr char txtNumpad [] PROGMEM = "\x82"; ButtonStatus_e bsIgnore(); void osNumpad(); constexpr Button bNumpad PROGMEM = { From 94be10fd87686dc64b9b15ac757d20cd95978e44 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 15:11:44 -0700 Subject: [PATCH 268/324] Justify RIT text left so that it doesn't interfere with the TX text --- menu_main_buttons.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 17cd3b6..0a389d6 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -440,10 +440,10 @@ void osRit(){ strncpy_P(b,(const char*)F("TX: "),sizeof(b)); formatFreq(globalSettings.ritFrequency, b + strlen(b), sizeof(b)-strlen(b)); if (VFO_A == globalSettings.activeVfo){ - displayText(b, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(b, LAYOUT_VFO_LABEL_X + 0*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND, TextJustification_e::Left); } else{ - displayText(b, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND); + displayText(b, LAYOUT_VFO_LABEL_X + 1*LAYOUT_VFO_LABEL_PITCH_X, LAYOUT_MODE_TEXT_Y, LAYOUT_VFO_LABEL_WIDTH, LAYOUT_MODE_TEXT_HEIGHT, COLOR_TEXT, COLOR_BACKGROUND, COLOR_BACKGROUND, TextJustification_e::Left); } } else{ From 0467223fe6e718a66fec452dd656b4c44602e469 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 15:17:18 -0700 Subject: [PATCH 269/324] If RIT is on, turn it off before switching VFO --- menu_main_buttons.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 0a389d6..7757356 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -393,6 +393,11 @@ ButtonStatus_e bsVfo(const Vfo_e vfo){ void osVfo(const Vfo_e vfo){ const uint32_t old_freq = GetActiveVfoFreq(); + + if(globalSettings.ritOn){ + osRit();//Turn off RIT + } + globalSettings.activeVfo = vfo; SaveSettingsToEeprom(); From e980cff9ff017dcdd8a45f44d0c6fa805946f221 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 23:35:54 -0700 Subject: [PATCH 270/324] Remove brackets from callsign --- callsign.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/callsign.cpp b/callsign.cpp index d9d428d..4c7203a 100644 --- a/callsign.cpp +++ b/callsign.cpp @@ -1,4 +1,4 @@ #include "callsign.h" -const char CALLSIGN_STRING_PRIVATE [] PROGMEM = "[CALLSIGN]"; +const char CALLSIGN_STRING_PRIVATE [] PROGMEM = "CALLSIGN"; const char* const CALLSIGN_STRING = CALLSIGN_STRING_PRIVATE; \ No newline at end of file From cd3364c835c0d52ecd720f97d0dd05fa750bc728 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 23:36:06 -0700 Subject: [PATCH 271/324] Update version --- version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cpp b/version.cpp index 59e9fe4..3534814 100644 --- a/version.cpp +++ b/version.cpp @@ -1,4 +1,4 @@ #include "version.h" -const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.1.2"; +const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.2.0"; const char* const VERSION_STRING = VERSION_STRING_PRIVATE; \ No newline at end of file From b49b61615b91ecada9965766b8741fdefb42fd18 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 17:19:35 -0700 Subject: [PATCH 272/324] Add quick list to EEPROM settings --- settings.cpp | 17 +++++++++++++++++ settings.h | 4 ++++ 2 files changed, 21 insertions(+) diff --git a/settings.cpp b/settings.cpp index 16fd2d1..4336e08 100644 --- a/settings.cpp +++ b/settings.cpp @@ -25,6 +25,8 @@ static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48;//uint16_t static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256;//uint8_t static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257;//uint8_t static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358;//uint8_t +static const uint16_t EEPROM_ADDR_QUICKLIST_FREQ = 630;//uint32_t array +static const uint16_t EEPROM_ADDR_QUICKLIST_MODE = 710;//uint8_t array template bool LoadSane(T& dest,uint16_t addr, T min, T max) @@ -62,6 +64,11 @@ void LoadDefaultSettings() globalSettings.vfoB.frequency = 14150000UL; globalSettings.vfoB.mode = VFO_MODE_USB; + for(uint8_t i = 0; i < NUM_QUICKLIST_SETTINGS; ++i){ + globalSettings.quickList[i].frequency = i*1000000; + globalSettings.quickList[i].mode = VfoMode_e::VFO_MODE_LSB; + } + globalSettings.keyerMode = KEYER_STRAIGHT; globalSettings.cwSideToneFreq = 800; globalSettings.cwDitDurationMs = 100; @@ -103,6 +110,11 @@ void LoadSettingsFromEeprom() LoadSane(morse_on,EEPROM_ADDR_MORSE_MENU,(uint8_t)0,(uint8_t)1); globalSettings.morseMenuOn = morse_on; + for(uint8_t i = 0; i < NUM_QUICKLIST_SETTINGS; ++i){ + LoadSane(globalSettings.quickList[i].frequency,EEPROM_ADDR_QUICKLIST_FREQ+(sizeof(uint32_t)*i),500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver + LoadSane(globalSettings.quickList[i].mode,EEPROM_ADDR_QUICKLIST_MODE+(sizeof(uint8_t)*i),VFO_MODE_LSB,VFO_MODE_USB); + } + //No sanity check on these - cal your heart out EEPROM.get(EEPROM_ADDR_MASTER_CAL,globalSettings.oscillatorCal); EEPROM.get(EEPROM_ADDR_TOUCH_SLOPE_X,globalSettings.touchSlopeX); @@ -129,6 +141,11 @@ void SaveSettingsToEeprom() EEPROM.put(EEPROM_ADDR_VFO_B_MODE,globalSettings.vfoB.mode); EEPROM.put(EEPROM_ADDR_CW_KEY_TYPE,globalSettings.keyerMode); EEPROM.put(EEPROM_ADDR_MORSE_MENU,(uint8_t)globalSettings.morseMenuOn); + + for(uint8_t i = 0; i < NUM_QUICKLIST_SETTINGS; ++i){ + EEPROM.put(EEPROM_ADDR_QUICKLIST_FREQ+(sizeof(uint32_t)*i),globalSettings.quickList[i].frequency); + EEPROM.put(EEPROM_ADDR_QUICKLIST_MODE+(sizeof(uint8_t)*i),globalSettings.quickList[i].mode); + } } uint32_t GetActiveVfoFreq() diff --git a/settings.h b/settings.h index 7c0caf1..19d4e28 100644 --- a/settings.h +++ b/settings.h @@ -14,6 +14,8 @@ #include //uint8_t etc. +static const uint8_t NUM_QUICKLIST_SETTINGS = 4; + /* * Loads default values for all settings */ @@ -79,6 +81,8 @@ struct SettingsRam VfoSettings_t vfoA; VfoSettings_t vfoB; + VfoSettings_t quickList[4]; + KeyerMode_e keyerMode; uint32_t cwSideToneFreq; uint16_t cwDitDurationMs; From fafc9acd0ed7fcdb98cb80cd007021f28d65b0a7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 17:30:19 -0700 Subject: [PATCH 273/324] Create quicklist menu --- menu_quicklist.cpp | 91 ++++++++++++++++++++++++ menu_quicklist.h | 2 + menu_quicklist_buttons.cpp | 137 +++++++++++++++++++++++++++++++++++++ menu_quicklist_buttons.h | 11 +++ 4 files changed, 241 insertions(+) create mode 100644 menu_quicklist.cpp create mode 100644 menu_quicklist.h create mode 100644 menu_quicklist_buttons.cpp create mode 100644 menu_quicklist_buttons.h diff --git a/menu_quicklist.cpp b/menu_quicklist.cpp new file mode 100644 index 0000000..8cc00a2 --- /dev/null +++ b/menu_quicklist.cpp @@ -0,0 +1,91 @@ +#include "menu_quicklist.h" +#include "menu_quicklist_buttons.h" + +#include +#include //F() + +#include "color_theme.h" +#include "menu_utils.h" +#include "nano_gui.h" +#include "scratch_space.h" + +void initQuickList(void); +MenuReturn_e runQuickList(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob); +Menu_t quickList_menu = { + initQuickList, + runQuickList, + nullptr +}; + +Menu_t *const quickListMenu = &quickList_menu; + +int16_t quickListMenuSelectedItemRaw = 0;//Allow negative only for easier checks on wrap around + +void drawQuickList(void) +{ + displayFillrect(0,47,320,200,COLOR_BACKGROUND); + Button button; + Button* bp; + for(uint8_t i = 0; i < QUICKLIST_MENU_NUM_BUTTONS; ++i){ + memcpy_P(&bp, &(quickListMenuButtons[i]), sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + drawButton(&button); + } + strncpy_P(b,(const char*)F("Short press = load\nLong press = save"),sizeof(b)); + displayText(b,10,47,170,200,COLOR_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); +} + +void initQuickList(void) +{ + quickListSelectionMode = ButtonPress_e::ShortPress;//Anything except NotPressed + drawQuickList(); + initSelector(&quickListMenuSelectedItemRaw, + quickListMenuButtons, + QUICKLIST_MENU_NUM_BUTTONS, + MorsePlaybackType_e::PlayChar); +} + +MenuReturn_e runQuickList(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob) +{ + if(ButtonPress_e::NotPressed != tuner_button){ + uint8_t menu_index = quickListMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + Button button; + Button* bp; + memcpy_P(&bp,&(quickListMenuButtons[menu_index]),sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + quickListSelectionMode = tuner_button; + button.on_select(); + }//tuner_button + + else if(ButtonPress_e::NotPressed != touch_button){ + Button button; + if(findPressedButton(quickListMenuButtons,QUICKLIST_MENU_NUM_BUTTONS,&button,touch_point)){ + quickListSelectionMode = touch_button; + button.on_select(); + } + else{ + //Touch detected, but not on our buttons, so ignore + } + }//touch_button + + else{//Neither button input type found, so handle the knob + adjustSelector(&quickListMenuSelectedItemRaw, + knob, + quickListMenuButtons, + QUICKLIST_MENU_NUM_BUTTONS, + MorsePlaybackType_e::PlayChar); + } + + if(ButtonPress_e::NotPressed == quickListSelectionMode){ + return MenuReturn_e::ExitedRedraw; + } + else{ + return MenuReturn_e::StillActive; + } +} \ No newline at end of file diff --git a/menu_quicklist.h b/menu_quicklist.h new file mode 100644 index 0000000..62fcbc0 --- /dev/null +++ b/menu_quicklist.h @@ -0,0 +1,2 @@ +#include "menu.h" +extern Menu_t* const quickListMenu; diff --git a/menu_quicklist_buttons.cpp b/menu_quicklist_buttons.cpp new file mode 100644 index 0000000..5b4fdfa --- /dev/null +++ b/menu_quicklist_buttons.cpp @@ -0,0 +1,137 @@ +#include "menu_quicklist_buttons.h" + +#include +#include //F() + +#include "color_theme.h" +#include "nano_gui.h" +#include "scratch_space.h" +#include "settings.h" +#include "utils.h" + +static const unsigned int LAYOUT_BUTTON_X = 180; +static const unsigned int LAYOUT_BUTTON_Y = 47; +static const unsigned int LAYOUT_BUTTON_WIDTH = 140; +static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; +static const unsigned int LAYOUT_BUTTON_PITCH_X = LAYOUT_BUTTON_WIDTH + 1; +static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; + +ButtonPress_e quickListSelectionMode; + +#define D_STRINGIFY(x) #x +#define D_STRING(x) D_STRINGIFY(x) +#define QUICKLIST_BUTTON_GENERATE(number) \ + void toQL##number(char* text_out, const uint16_t max_text_size);\ + void osQL##number();\ + constexpr Button bQL##number PROGMEM = {\ + LAYOUT_BUTTON_X,\ + LAYOUT_BUTTON_Y + number*LAYOUT_BUTTON_PITCH_Y,\ + LAYOUT_BUTTON_WIDTH,\ + LAYOUT_BUTTON_HEIGHT,\ + nullptr,\ + toQL##number,\ + bsQuickList,\ + osQL##number,\ + '0'+number\ + } + +ButtonStatus_e bsQuickList(void){ + return ButtonStatus_e::Stateless; +} + +//Unfortunately there's no easy way to auto-generate NUM_QUICKLIST_SETTINGS copies of this +QUICKLIST_BUTTON_GENERATE(0); +QUICKLIST_BUTTON_GENERATE(1); +QUICKLIST_BUTTON_GENERATE(2); +QUICKLIST_BUTTON_GENERATE(3); + +constexpr char txtQLCancel [] PROGMEM = "Can"; +void osQLCancel(); +constexpr Button bQLCancel PROGMEM = { + LAYOUT_BUTTON_X, + LAYOUT_BUTTON_Y + 4*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtQLCancel, + nullptr, + bsQuickList, + osQLCancel, + 'C' +}; + +//Declare in menu select order, not graphical order +const Button* const quickListMenuButtons [] PROGMEM = { + &bQL0, &bQL1, &bQL2, &bQL3, &bQLCancel +}; +const uint8_t QUICKLIST_MENU_NUM_BUTTONS = sizeof(quickListMenuButtons)/sizeof(quickListMenuButtons[0]); + +void osQuickListRecall(uint8_t index) +{ + SetActiveVfoFreq(globalSettings.quickList[index].frequency); + SetActiveVfoMode(globalSettings.quickList[index].mode); +} + +void osQuickListSave(uint8_t index) +{ + globalSettings.quickList[index].frequency = GetActiveVfoFreq(); + globalSettings.quickList[index].mode = GetActiveVfoMode(); + SaveSettingsToEeprom(); +} + +void osQuickList(uint8_t index) +{ + if(ButtonPress_e::ShortPress == quickListSelectionMode){ + osQuickListRecall(index); + } + else if(ButtonPress_e::LongPress == quickListSelectionMode){ + osQuickListSave(index); + } + quickListSelectionMode = ButtonPress_e::NotPressed;//Selection was made. Exit. +} + +#define QUICKLIST_ONSELECT_GENERATE(number) \ + void osQL##number(void){\ + osQuickList(number);\ + } + +//Unfortunately there's no easy way to auto-generate NUM_QUICKLIST_SETTINGS copies of this +QUICKLIST_ONSELECT_GENERATE(0); +QUICKLIST_ONSELECT_GENERATE(1); +QUICKLIST_ONSELECT_GENERATE(2); +QUICKLIST_ONSELECT_GENERATE(3); + +#define QUICKLIST_TEXTOVERRIDE_GENERATE(number) \ + void toQL##number(char* text_out, const uint16_t max_text_size){\ + toQuickList(number, text_out, max_text_size);\ + } + +void toQuickList(uint8_t index, char* text_out, const uint16_t max_text_size) +{ + + if(max_text_size < 2){ + return;//Can't do much with that space + } + if(max_text_size < (3+10+1)){ + //Give an indicator that's debuggable + text_out[0] = 'X'; + text_out[1] = '\0'; + return; + } + + //Normal operation + text_out[0] = '0'+index;//Assume a 1-digit number for now + text_out[1] = ':'; + text_out[2] = ' '; + formatFreq(globalSettings.quickList[index].frequency, text_out+3, max_text_size-3, 10); +} + +//Unfortunately there's no easy way to auto-generate NUM_QUICKLIST_SETTINGS copies of this +QUICKLIST_TEXTOVERRIDE_GENERATE(0); +QUICKLIST_TEXTOVERRIDE_GENERATE(1); +QUICKLIST_TEXTOVERRIDE_GENERATE(2); +QUICKLIST_TEXTOVERRIDE_GENERATE(3); + +void osQLCancel() +{ + quickListSelectionMode = ButtonPress_e::NotPressed; +} diff --git a/menu_quicklist_buttons.h b/menu_quicklist_buttons.h new file mode 100644 index 0000000..d03017c --- /dev/null +++ b/menu_quicklist_buttons.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "button.h" +#include "button_press_e.h" + +extern const Button* const quickListMenuButtons[]; +extern const uint8_t QUICKLIST_MENU_NUM_BUTTONS; + +extern ButtonPress_e quickListSelectionMode;//NotPressed means exit menu. Other press types are consumed by selectors From aa7e6825b4175b41d1bcf985cc0d1e12fcf05833 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 17:30:58 -0700 Subject: [PATCH 274/324] Add quicklist to main menu, but disable numpad temporarily for size reasons --- menu_main_buttons.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 7757356..19bf0bc 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -10,6 +10,7 @@ #include "color_theme.h" #include "menu_main.h" #include "menu_numpad.h" +#include "menu_quicklist.h" #include "morse.h" #include "nano_gui.h" #include "scratch_space.h" @@ -285,6 +286,21 @@ constexpr Button b10 PROGMEM = { '1' }; +constexpr char txtQuickList [] PROGMEM = "\x83";//star icon +ButtonStatus_e bsIgnore(); +void osQuickList(); +constexpr Button bQuickList PROGMEM = { + LAYOUT_BUTTON_X + 2*LAYOUT_BUTTON_PITCH_X, + LAYOUT_BUTTON_Y + 2*LAYOUT_BUTTON_PITCH_Y, + LAYOUT_BUTTON_WIDTH, + LAYOUT_BUTTON_HEIGHT, + txtQuickList, + nullptr, + bsIgnore, + osQuickList, + 'Q' +}; + constexpr char txtMenu [] PROGMEM = "\x7F";//gear icon ButtonStatus_e bsIgnore(); void osMenu(); @@ -300,7 +316,7 @@ constexpr Button bMenu PROGMEM = { 'M' }; -constexpr char txtNumpad [] PROGMEM = "\x82"; +constexpr char txtNumpad [] PROGMEM = "\x82";//numpad icon ButtonStatus_e bsIgnore(); void osNumpad(); constexpr Button bNumpad PROGMEM = { @@ -316,11 +332,11 @@ constexpr Button bNumpad PROGMEM = { }; const Button* const mainMenuButtons [] PROGMEM = { - &bVfoA, &bVfoB, + &bVfoA, &bVfoB, - &bRit, &bUsb, &bLsb, &bCw, &bSpl, - &b80, &b40, &b30, &b20, &b17, - &b15, &b10, &bMenu, &bNumpad + &bRit, &bUsb, &bLsb, &bCw, &bSpl, + &b80, &b40, &b30, &b20, &b17, + &b15, &b10, &bQuickList, &bMenu, &bNumpad }; const uint8_t MAIN_MENU_NUM_BUTTONS = sizeof(mainMenuButtons) / sizeof(mainMenuButtons[0]); @@ -622,10 +638,14 @@ ButtonStatus_e bsIgnore(){ return ButtonStatus_e::Stateless; } +void osQuickList(){ + enterSubmenu(quickListMenu); +} + void osMenu(){ enterSubmenu(setupMenu); } void osNumpad(){ - enterSubmenu(numpadMenu); + //enterSubmenu(numpadMenu); } From 77b1bd291ec0a593ba87788c8e48331b491f5e1c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 21:32:19 -0700 Subject: [PATCH 275/324] Save ~100 bytes by combining these two functions --- button.cpp | 6 ++++++ button.h | 2 +- menu_main.cpp | 8 +++----- menu_main_buttons.cpp | 42 ++++++++++++++---------------------------- menu_numpad.cpp | 3 +-- menu_quicklist.cpp | 3 +-- 6 files changed, 26 insertions(+), 38 deletions(-) diff --git a/button.cpp b/button.cpp index ac221ac..536f196 100644 --- a/button.cpp +++ b/button.cpp @@ -42,3 +42,9 @@ void drawButton(Button* button) } displayText(b, button->x, button->y, button->w, button->h, tc, bgc, bdc); } + +void extractAndDrawButton(Button* button_out, const Button* button_P) +{ + memcpy_P(button_out,button_P,sizeof(*button_out)); + drawButton(button_out); +} diff --git a/button.h b/button.h index 6aba532..7a9e33d 100644 --- a/button.h +++ b/button.h @@ -17,4 +17,4 @@ struct Button { char morse; }; -void drawButton(Button* button); +void extractAndDrawButton(Button* button_out, const Button* button_P); diff --git a/menu_main.cpp b/menu_main.cpp index 102fa86..2285ef2 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -37,8 +37,7 @@ void drawMainMenu(void) Button* bp; for(uint8_t i = 0; i < MAIN_MENU_NUM_BUTTONS; ++i){ memcpy_P(&bp, &(mainMenuButtons[i]), sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,bp); } drawVersion(); drawCallsign(); @@ -70,12 +69,11 @@ void mainMenuTune(int16_t knob) Button button; if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoA,sizeof(button)); + extractAndDrawButton(&button,&bVfoA); } else{ - memcpy_P(&button,&bVfoB,sizeof(button)); + extractAndDrawButton(&button,&bVfoB); } - drawButton(&button); updateBandButtons(old_freq); } diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index 19bf0bc..d495948 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -350,8 +350,7 @@ void updateBandButtons(const uint32_t old_freq) Button button; for(uint8_t i = 0; i < sizeof(bands)/sizeof(bands[0]); ++i){ if(isFreqInBand(old_freq,bands[i]) != isFreqInBand(curr_freq,bands[i])){ - memcpy_P(&button,band_buttons[i],sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,band_buttons[i]); morseBool(ButtonStatus_e::Active == button.status()); } } @@ -421,10 +420,8 @@ void osVfo(const Vfo_e vfo){ morseText(b); Button button; - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bVfoA); + extractAndDrawButton(&button,&bVfoB); updateBandButtons(old_freq); updateSidebandButtons(); } @@ -473,17 +470,14 @@ void osRit(){ displayFillrect(LAYOUT_MODE_TEXT_X,LAYOUT_MODE_TEXT_Y,LAYOUT_MODE_TEXT_WIDTH,LAYOUT_MODE_TEXT_HEIGHT, COLOR_BACKGROUND); if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bVfoA); } else{ - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bVfoB); } } - memcpy_P(&button,&bRit,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bRit); } void osSidebandMode(VfoMode_e mode){ @@ -492,10 +486,8 @@ void osSidebandMode(VfoMode_e mode){ SaveSettingsToEeprom(); Button button; - memcpy_P(&button,&bUsb,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bLsb,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bUsb); + extractAndDrawButton(&button,&bLsb); } void updateSidebandButtons() @@ -534,8 +526,7 @@ void osCw(){ setFrequency(GetActiveVfoFreq()); Button button; - memcpy_P(&button,&bCw,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bCw); } ButtonStatus_e bsSpl(){ @@ -546,12 +537,9 @@ void osSpl(){ globalSettings.splitOn = !globalSettings.splitOn; Button button; - memcpy_P(&button,&bSpl,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bSpl); + extractAndDrawButton(&button,&bVfoA); + extractAndDrawButton(&button,&bVfoB); } ButtonStatus_e bsBand(const uint8_t band){ @@ -567,12 +555,10 @@ void osBand(const uint8_t band){ Button button; if(Vfo_e::VFO_A == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoA,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bVfoA); } else if(Vfo_e::VFO_B == globalSettings.activeVfo){ - memcpy_P(&button,&bVfoB,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,&bVfoB); } updateBandButtons(old_freq); diff --git a/menu_numpad.cpp b/menu_numpad.cpp index 847fb2e..437bfc3 100644 --- a/menu_numpad.cpp +++ b/menu_numpad.cpp @@ -29,8 +29,7 @@ void drawNumpad(void) Button* bp; for(uint8_t i = 0; i < NUMPAD_MENU_NUM_BUTTONS; ++i){ memcpy_P(&bp, &(numpadMenuButtons[i]), sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,bp); } } diff --git a/menu_quicklist.cpp b/menu_quicklist.cpp index 8cc00a2..062c1e3 100644 --- a/menu_quicklist.cpp +++ b/menu_quicklist.cpp @@ -31,8 +31,7 @@ void drawQuickList(void) Button* bp; for(uint8_t i = 0; i < QUICKLIST_MENU_NUM_BUTTONS; ++i){ memcpy_P(&bp, &(quickListMenuButtons[i]), sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - drawButton(&button); + extractAndDrawButton(&button,bp); } strncpy_P(b,(const char*)F("Short press = load\nLong press = save"),sizeof(b)); displayText(b,10,47,170,200,COLOR_TEXT,COLOR_BACKGROUND,COLOR_BACKGROUND); From 61c22474e9778bae0ae6593b266a207866aed4eb Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 22:11:26 -0700 Subject: [PATCH 276/324] Slim down some of the setup text --- setup.cpp | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/setup.cpp b/setup.cpp index 024aff0..5024e60 100644 --- a/setup.cpp +++ b/setup.cpp @@ -63,6 +63,10 @@ static const unsigned int LAYOUT_CONFIRM_TEXT_Y = LAYOUT_ITEM_Y + 5*LAYOUT_ITEM_ static const unsigned int LAYOUT_CONFIRM_TEXT_WIDTH = LAYOUT_ITEM_WIDTH; static const unsigned int LAYOUT_CONFIRM_TEXT_HEIGHT = LAYOUT_ITEM_HEIGHT; +constexpr char strYes [] PROGMEM = "Yes"; +constexpr char strNo [] PROGMEM = "No"; +constexpr char strHz [] PROGMEM = "Hz"; + void displayDialog(const char* title, const char* instructions){ displayClear(COLOR_BACKGROUND); @@ -194,7 +198,7 @@ void ssLocalOscChange(const long int new_value, char* buff_out, const size_t buf ++buff_out; } formatFreq(u,buff_out,buff_out_size - strlen(buff_out)); - strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); + strncat_P(buff_out,strHz,buff_out_size - strlen(buff_out)); } void ssLocalOscFinalize(const long int final_value) { @@ -204,7 +208,7 @@ void ssLocalOscFinalize(const long int final_value) setFrequency(GetActiveVfoFreq()); } const char SS_LOCAL_OSC_T [] PROGMEM = "Local Oscillator"; -const char SS_LOCAL_OSC_A [] PROGMEM = "Exit menu, tune so that the\ndial displays the desired freq,\nthen tune here until the\nsignal is zerobeat"; +const char SS_LOCAL_OSC_A [] PROGMEM = "Tune so that the dial displays\na known freq, then tune here\nuntil the signal is zerobeat"; const SettingScreen_t ssLocalOsc PROGMEM = { SS_LOCAL_OSC_T, SS_LOCAL_OSC_A, @@ -232,7 +236,7 @@ void ssBfoChange(const long int new_value, char* buff_out, const size_t buff_out setFrequency(GetActiveVfoFreq()); si5351bx_setfreq(0, new_value); formatFreq(new_value,buff_out,buff_out_size); - strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); + strncat_P(buff_out,strHz,buff_out_size - strlen(buff_out)); } void ssBfoFinalize(const long int final_value) { @@ -242,7 +246,7 @@ void ssBfoFinalize(const long int final_value) setFrequency(GetActiveVfoFreq()); } const char SS_BFO_T [] PROGMEM = "Beat Frequency Osc (BFO)"; -const char SS_BFO_A [] PROGMEM = "Exit menu, tune to an unused\nfrequency, then tune here\nuntil the audio is between\n300-3000Hz"; +const char SS_BFO_A [] PROGMEM = "Tune until the audio is\nbetween 300-3000Hz"; const SettingScreen_t ssBfo PROGMEM = { SS_BFO_T, SS_BFO_A, @@ -269,7 +273,7 @@ void ssCwToneChange(const long int new_value, char* buff_out, const size_t buff_ globalSettings.cwSideToneFreq = new_value; toneAC2(PIN_CW_TONE, globalSettings.cwSideToneFreq); ltoa(globalSettings.cwSideToneFreq,buff_out,10); - strncat_P(buff_out,(const char*)F("Hz"),buff_out_size - strlen(buff_out)); + strncat_P(buff_out,strHz,buff_out_size - strlen(buff_out)); } void ssCwToneFinalize(const long int final_value) { @@ -313,7 +317,7 @@ void ssCwSwitchDelayFinalize(const long int final_value) SaveSettingsToEeprom(); } const char SS_CW_SWITCH_T [] PROGMEM = "Tx to Rx Delay"; -const char SS_CW_SWITCH_A [] PROGMEM = "Select how long the radio\nshould wait before switching\nbetween TX and RX when in\nCW mode"; +const char SS_CW_SWITCH_A [] PROGMEM = "How long to wait before\nswitching from TX to RX when\nin CW mode"; const SettingScreen_t ssCwSwitchDelay PROGMEM = { SS_CW_SWITCH_T, SS_CW_SWITCH_A, @@ -359,7 +363,7 @@ void ssKeyerFinalize(const long int final_value) SaveSettingsToEeprom(); } const char SS_KEYER_T [] PROGMEM = "Keyer Type"; -const char SS_KEYER_A [] PROGMEM = "Select which type of\nkeyer/paddle is being used"; +const char SS_KEYER_A [] PROGMEM = "Select which type of keyer\nor paddle is being used"; const SettingScreen_t ssKeyer PROGMEM = { SS_KEYER_T, SS_KEYER_A, @@ -385,11 +389,11 @@ void ssMorseMenuChange(const long int new_value, char* buff_out, const size_t bu { char m; if(new_value){ - strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size); + strncpy_P(buff_out,strYes,buff_out_size); m = 'Y'; } else{ - strncpy_P(buff_out,(const char*)F("No"),buff_out_size); + strncpy_P(buff_out,strNo,buff_out_size); m = 'N'; } morseLetter(m); @@ -401,7 +405,7 @@ void ssMorseMenuFinalize(const long int final_value) SaveSettingsToEeprom(); } const char SS_MORSE_MENU_T [] PROGMEM = "Menu Audio"; -const char SS_MORSE_MENU_A [] PROGMEM = "When on, menu selections\nwill play morse code"; +const char SS_MORSE_MENU_A [] PROGMEM = "Menu selections will play\nmorse code"; const SettingScreen_t ssMorseMenu PROGMEM = { SS_MORSE_MENU_T, SS_MORSE_MENU_A, @@ -435,7 +439,7 @@ void ssCwSpeedFinalize(const long int final_value) SaveSettingsToEeprom(); } const char SS_CW_SPEED_T [] PROGMEM = "Play Speed"; -const char SS_CW_SPEED_A [] PROGMEM = "Select speed to play CW\ncharacters"; +const char SS_CW_SPEED_A [] PROGMEM = "Speed to play CW characters"; const SettingScreen_t ssCwSpeed PROGMEM = { SS_CW_SPEED_T, SS_CW_SPEED_A, @@ -461,11 +465,11 @@ void ssResetAllChange(const long int new_value, char* buff_out, const size_t buf { char m; if(new_value){ - strncpy_P(buff_out,(const char*)F("Yes"),buff_out_size); + strncpy_P(buff_out,strYes,buff_out_size); m = 'Y'; } else{ - strncpy_P(buff_out,(const char*)F("No"),buff_out_size); + strncpy_P(buff_out,strNo,buff_out_size); m = 'N'; } morseLetter(m); @@ -480,7 +484,7 @@ void ssResetAllFinalize(const long int final_value) } } const char SS_RESET_ALL_T [] PROGMEM = "Reset All"; -const char SS_RESET_ALL_A [] PROGMEM = "WARNING: Selecting \"Yes\"\nwill reset all calibrations and\nsettings to their default\nvalues"; +const char SS_RESET_ALL_A [] PROGMEM = "Resets all calibrations and\nsettings to their default\nvalues"; const SettingScreen_t ssResetAll PROGMEM = { SS_RESET_ALL_T, SS_RESET_ALL_A, From ab8ba66067684fd9f86b841ade210550ebff3007 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 22:43:47 -0700 Subject: [PATCH 277/324] Reuse menu running code between quicklist and numpad --- menu_np_ql_shared.cpp | 52 +++++++++++++++++++++++++++++++++++++++++ menu_np_ql_shared.h | 14 +++++++++++ menu_numpad.cpp | 45 ++++++++--------------------------- menu_numpad_buttons.cpp | 6 ++--- menu_numpad_buttons.h | 2 ++ menu_quicklist.cpp | 44 +++++++--------------------------- 6 files changed, 90 insertions(+), 73 deletions(-) create mode 100644 menu_np_ql_shared.cpp create mode 100644 menu_np_ql_shared.h diff --git a/menu_np_ql_shared.cpp b/menu_np_ql_shared.cpp new file mode 100644 index 0000000..fc988d1 --- /dev/null +++ b/menu_np_ql_shared.cpp @@ -0,0 +1,52 @@ +#include "menu_np_ql_shared.h" + +#include + +#include "button.h" +#include "menu_utils.h" + +MenuReturn_e runNpQlShared(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob, + int16_t *const menuSelectedItemRaw, + const Button *const *const menu_buttons, + const uint8_t menu_num_buttons, + ButtonPress_e *const selection_mode) +{ + if(ButtonPress_e::NotPressed != tuner_button){ + uint8_t menu_index = *menuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; + Button button; + Button* bp; + memcpy_P(&bp,&(menu_buttons[menu_index]),sizeof(bp)); + memcpy_P(&button,bp,sizeof(button)); + *selection_mode = tuner_button; + button.on_select(); + }//tuner_button + + else if(ButtonPress_e::NotPressed != touch_button){ + Button button; + if(findPressedButton(menu_buttons,menu_num_buttons,&button,touch_point)){ + *selection_mode = touch_button; + button.on_select(); + } + else{ + //Touch detected, but not on our buttons, so ignore + } + }//touch_button + + else{//Neither button input type found, so handle the knob + adjustSelector(menuSelectedItemRaw, + knob, + menu_buttons, + menu_num_buttons, + MorsePlaybackType_e::PlayChar); + } + + if(ButtonPress_e::NotPressed == *selection_mode){ + return MenuReturn_e::ExitedRedraw; + } + else{ + return MenuReturn_e::StillActive; + } +} diff --git a/menu_np_ql_shared.h b/menu_np_ql_shared.h new file mode 100644 index 0000000..9a260c9 --- /dev/null +++ b/menu_np_ql_shared.h @@ -0,0 +1,14 @@ +#pragma once + +#include "button.h" +#include "menu.h" + +MenuReturn_e runNpQlShared(const ButtonPress_e tuner_button, + const ButtonPress_e touch_button, + const Point touch_point, + const int16_t knob, + int16_t *const menuSelectedItemRaw, + const Button *const *const menu_buttons, + const uint8_t menu_num_buttons, + ButtonPress_e *const selection_mode); + diff --git a/menu_numpad.cpp b/menu_numpad.cpp index 437bfc3..1fa060f 100644 --- a/menu_numpad.cpp +++ b/menu_numpad.cpp @@ -4,6 +4,7 @@ #include #include "color_theme.h" +#include "menu_np_ql_shared.h" #include "menu_utils.h" #include "nano_gui.h" @@ -36,6 +37,7 @@ void drawNumpad(void) void initNumpad(void) { numpadMenuFrequency = 0; + numpadSelectionMode = ButtonPress_e::LongPress;//Anything except NotPressed drawNumpad(); initSelector(&numpadMenuSelectedItemRaw, numpadMenuButtons, @@ -48,39 +50,12 @@ MenuReturn_e runNumpad(const ButtonPress_e tuner_button, const Point touch_point, const int16_t knob) { - if(ButtonPress_e::NotPressed != tuner_button){ - //We treat long and short presses the same, so no need to have a switch - uint8_t menu_index = numpadMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; - Button button; - Button* bp; - memcpy_P(&bp,&(numpadMenuButtons[menu_index]),sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - button.on_select(); - }//tuner_button - - else if(ButtonPress_e::NotPressed != touch_button){ - //We treat long and short presses the same, so no need to have a switch - Button button; - if(findPressedButton(numpadMenuButtons,NUMPAD_MENU_NUM_BUTTONS,&button,touch_point)){ - button.on_select(); - } - else{ - //Touch detected, but not on our buttons, so ignore - } - }//touch_button - - else{//Neither button input type found, so handle the knob - adjustSelector(&numpadMenuSelectedItemRaw, - knob, - numpadMenuButtons, - NUMPAD_MENU_NUM_BUTTONS, - MorsePlaybackType_e::PlayChar); - } - - if(NUMPAD_MENU_EXIT_FREQ == numpadMenuFrequency){ - return MenuReturn_e::ExitedRedraw; - } - else{ - return MenuReturn_e::StillActive; - } + return runNpQlShared(tuner_button, + touch_button, + touch_point, + knob, + &numpadMenuSelectedItemRaw, + numpadMenuButtons, + NUMPAD_MENU_NUM_BUTTONS, + &numpadSelectionMode); } \ No newline at end of file diff --git a/menu_numpad_buttons.cpp b/menu_numpad_buttons.cpp index 252eaa6..c9cdabe 100644 --- a/menu_numpad_buttons.cpp +++ b/menu_numpad_buttons.cpp @@ -22,8 +22,8 @@ static const unsigned int LAYOUT_BUTTON_HEIGHT = 36; static const unsigned int LAYOUT_BUTTON_PITCH_X = 64; static const unsigned int LAYOUT_BUTTON_PITCH_Y = 40; -const uint32_t NUMPAD_MENU_EXIT_FREQ = -1; uint32_t numpadMenuFrequency; +ButtonPress_e numpadSelectionMode; #define D_STRINGIFY(x) #x #define D_STRING(x) D_STRINGIFY(x) @@ -152,10 +152,10 @@ void osOk(void) SetActiveVfoFreq(numpadMenuFrequency); SaveSettingsToEeprom(); setFrequency(numpadMenuFrequency); - numpadMenuFrequency = NUMPAD_MENU_EXIT_FREQ; + numpadSelectionMode = ButtonPress_e::NotPressed; } void osCancel(void) { - numpadMenuFrequency = NUMPAD_MENU_EXIT_FREQ; + numpadSelectionMode = ButtonPress_e::NotPressed; } diff --git a/menu_numpad_buttons.h b/menu_numpad_buttons.h index a7d555e..3628a3f 100644 --- a/menu_numpad_buttons.h +++ b/menu_numpad_buttons.h @@ -3,9 +3,11 @@ #include #include "button.h" +#include "button_press_e.h" extern const Button* const numpadMenuButtons[]; extern const uint8_t NUMPAD_MENU_NUM_BUTTONS; extern const uint32_t NUMPAD_MENU_EXIT_FREQ; extern uint32_t numpadMenuFrequency; +extern ButtonPress_e numpadSelectionMode;//NotPressed means exit menu. Other press types are consumed by selectors diff --git a/menu_quicklist.cpp b/menu_quicklist.cpp index 062c1e3..63526af 100644 --- a/menu_quicklist.cpp +++ b/menu_quicklist.cpp @@ -5,6 +5,7 @@ #include //F() #include "color_theme.h" +#include "menu_np_ql_shared.h" #include "menu_utils.h" #include "nano_gui.h" #include "scratch_space.h" @@ -52,39 +53,12 @@ MenuReturn_e runQuickList(const ButtonPress_e tuner_button, const Point touch_point, const int16_t knob) { - if(ButtonPress_e::NotPressed != tuner_button){ - uint8_t menu_index = quickListMenuSelectedItemRaw/MENU_KNOB_COUNTS_PER_ITEM; - Button button; - Button* bp; - memcpy_P(&bp,&(quickListMenuButtons[menu_index]),sizeof(bp)); - memcpy_P(&button,bp,sizeof(button)); - quickListSelectionMode = tuner_button; - button.on_select(); - }//tuner_button - - else if(ButtonPress_e::NotPressed != touch_button){ - Button button; - if(findPressedButton(quickListMenuButtons,QUICKLIST_MENU_NUM_BUTTONS,&button,touch_point)){ - quickListSelectionMode = touch_button; - button.on_select(); - } - else{ - //Touch detected, but not on our buttons, so ignore - } - }//touch_button - - else{//Neither button input type found, so handle the knob - adjustSelector(&quickListMenuSelectedItemRaw, - knob, - quickListMenuButtons, - QUICKLIST_MENU_NUM_BUTTONS, - MorsePlaybackType_e::PlayChar); - } - - if(ButtonPress_e::NotPressed == quickListSelectionMode){ - return MenuReturn_e::ExitedRedraw; - } - else{ - return MenuReturn_e::StillActive; - } + return runNpQlShared(tuner_button, + touch_button, + touch_point, + knob, + &quickListMenuSelectedItemRaw, + quickListMenuButtons, + QUICKLIST_MENU_NUM_BUTTONS, + &quickListSelectionMode); } \ No newline at end of file From 55822dadf7c321a5007e9eef8dd4dc932dc634df Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 23:46:32 -0700 Subject: [PATCH 278/324] Give min/max frequency variable names --- si5351.cpp | 3 ++- si5351.h | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/si5351.cpp b/si5351.cpp index ec4879b..d42687d 100644 --- a/si5351.cpp +++ b/si5351.cpp @@ -1,6 +1,7 @@ #include #include #include "settings.h" +#include "si5351.h" // ************* SI5315 routines - tks Jerry Gaffke, KE7ER *********************** @@ -84,7 +85,7 @@ void si5351bx_init() { // Call once at power-up, start PLLA void si5351bx_setfreq(uint8_t clknum, uint32_t fout) { // Set a CLK to fout Hz uint32_t msa, msb, msc, msxp1, msxp2, msxp3p2top; - if ((fout < 500000) || (fout > 109000000)) // If clock freq out of range + if ((fout < SI5351_MIN_FREQUENCY_HZ) || (fout > SI5351_MAX_FREQUENCY_HZ)) // If clock freq out of range si5351bx_clken |= 1 << clknum; // shut down the clock else { msa = si5351bx_vcoa / fout; // Integer part of vco/fout diff --git a/si5351.h b/si5351.h index 2a9d38e..f2afc85 100644 --- a/si5351.h +++ b/si5351.h @@ -1,5 +1,10 @@ #pragma once +#include + +static const uint32_t SI5351_MIN_FREQUENCY_HZ = 500000; +static const uint32_t SI5351_MAX_FREQUENCY_HZ = 109000000; + void initOscillators(); void si5351bx_setfreq(uint8_t clknum, uint32_t fout); void si5351_set_calibration(int32_t cal); //calibration is a small value that is nudged to make up for the inaccuracies of the reference 25 MHz crystal frequency From a9b9b62dd1fe62bbbb4a77049736c8977e59eaae Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 26 Apr 2020 23:49:26 -0700 Subject: [PATCH 279/324] Use driver-specified min/max frequencies --- settings.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/settings.cpp b/settings.cpp index 4336e08..efdd6ef 100644 --- a/settings.cpp +++ b/settings.cpp @@ -4,6 +4,7 @@ #include //only needed for debugging's Serial.print stuff #include "nano_gui.h"//redrawVFOs() function #include "settings.h" +#include "si5351.h" /** * These are the "magic" indices where these user changable settinngs are stored in the EEPROM @@ -95,8 +96,8 @@ void LoadDefaultSettings() void LoadSettingsFromEeprom() { LoadSane(globalSettings.usbCarrierFreq,EEPROM_ADDR_USB_CAL,11048000UL,11060000UL); - LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver - LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver + LoadSane(globalSettings.vfoA.frequency,EEPROM_ADDR_VFO_A_FREQ,SI5351_MIN_FREQUENCY_HZ,SI5351_MAX_FREQUENCY_HZ); + LoadSane(globalSettings.vfoB.frequency,EEPROM_ADDR_VFO_B_FREQ,SI5351_MIN_FREQUENCY_HZ,SI5351_MAX_FREQUENCY_HZ); LoadSane(globalSettings.cwSideToneFreq,EEPROM_ADDR_CW_SIDETONE,100UL,2000UL); LoadSane(globalSettings.cwDitDurationMs,EEPROM_ADDR_CW_DIT_TIME,10U,1000U); if(LoadSane(globalSettings.cwActiveTimeoutMs,EEPROM_ADDR_CW_DELAYTIME,10U,100U)){ @@ -111,7 +112,7 @@ void LoadSettingsFromEeprom() globalSettings.morseMenuOn = morse_on; for(uint8_t i = 0; i < NUM_QUICKLIST_SETTINGS; ++i){ - LoadSane(globalSettings.quickList[i].frequency,EEPROM_ADDR_QUICKLIST_FREQ+(sizeof(uint32_t)*i),500000UL+1,109000000UL-1);//Allow all freq supported by si5351 driver + LoadSane(globalSettings.quickList[i].frequency,EEPROM_ADDR_QUICKLIST_FREQ+(sizeof(uint32_t)*i),SI5351_MIN_FREQUENCY_HZ,SI5351_MAX_FREQUENCY_HZ); LoadSane(globalSettings.quickList[i].mode,EEPROM_ADDR_QUICKLIST_MODE+(sizeof(uint8_t)*i),VFO_MODE_LSB,VFO_MODE_USB); } From 501205ebd50020ffd1a692bb5dfee36055cc2c07 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 27 Apr 2020 00:17:41 -0700 Subject: [PATCH 280/324] Save ~100 bytes by rolling up the frequency parser --- ubitx_cat.cpp | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index a034bc5..66ffabb 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -98,23 +98,15 @@ void writeFreq(unsigned long freq,byte* cmd) { // unsigned long readFreq(byte* cmd) { // Pull off each of the digits - byte d7 = getHighNibble(cmd[0]); - byte d6 = getLowNibble(cmd[0]); - byte d5 = getHighNibble(cmd[1]); - byte d4 = getLowNibble(cmd[1]); - byte d3 = getHighNibble(cmd[2]); - byte d2 = getLowNibble(cmd[2]); - byte d1 = getHighNibble(cmd[3]); - byte d0 = getLowNibble(cmd[3]); - return - (unsigned long)d7 * 100000000L + - (unsigned long)d6 * 10000000L + - (unsigned long)d5 * 1000000L + - (unsigned long)d4 * 100000L + - (unsigned long)d3 * 10000L + - (unsigned long)d2 * 1000L + - (unsigned long)d1 * 100L + - (unsigned long)d0 * 10L; + unsigned long ret = 0; + for(uint8_t i = 0; i < 4; ++i){ + const uint8_t d1 = getHighNibble(cmd[i]); + const uint8_t d0 = getLowNibble(cmd[i]); + ret *= 100; + ret += 10*d1 + d0; + } + + return ret*10; } //void ReadEEPRom_FT817(byte fromType) From 4e961bdea736748bc5d76b8f22915356533856a2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 14:46:42 -0700 Subject: [PATCH 281/324] Give indicies names, so that it's easier to tell what's being extracted/set --- ubitx_cat.cpp | 113 +++++++++++++++++++++++++++----------------------- 1 file changed, 60 insertions(+), 53 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 66ffabb..d4992b9 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -17,24 +17,32 @@ static unsigned long rxBufferArriveTime = 0; static byte rxBufferCheckCount = 0; -#define CAT_RECEIVE_TIMEOUT 500 -static byte cat[5]; + +static uint8_t cat[5];//Data is ordered parameters 1-4, then command code last +enum CatDataIndex_e : uint8_t { + P1 = 0, + P2 = 1, + P3 = 2, + P4 = 3, + CMD = 4 +}; + static byte insideCat = 0; //for broken protocol -#define CAT_RECEIVE_TIMEOUT 500 +static const uint16_t CAT_RECEIVE_TIMEOUT = 500; -#define CAT_MODE_LSB 0x00 -#define CAT_MODE_USB 0x01 -#define CAT_MODE_CW 0x02 -#define CAT_MODE_CWR 0x03 -#define CAT_MODE_AM 0x04 -#define CAT_MODE_FM 0x08 -#define CAT_MODE_DIG 0x0A -#define CAT_MODE_PKT 0x0C -#define CAT_MODE_FMN 0x88 +static const uint8_t CAT_MODE_LSB = 0x00; +static const uint8_t CAT_MODE_USB = 0x01; +static const uint8_t CAT_MODE_CW = 0x02; +static const uint8_t CAT_MODE_CWR = 0x03; +static const uint8_t CAT_MODE_AM = 0x04; +static const uint8_t CAT_MODE_FM = 0x08; +static const uint8_t CAT_MODE_DIG = 0x0A; +static const uint8_t CAT_MODE_PKT = 0x0C; +static const uint8_t CAT_MODE_FMN = 0x88; -#define ACK 0 +static const uint8_t ACK = 0; unsigned int skipTimeCount = 0; @@ -113,11 +121,11 @@ unsigned long readFreq(byte* cmd) { void catReadEEPRom(void) { //for remove warnings - byte temp0 = cat[0]; - byte temp1 = cat[1]; + byte temp0 = cat[P1]; + byte temp1 = cat[P2]; - cat[0] = 0; - cat[1] = 0; + cat[P1] = 0; + cat[P2] = 0; //for remove warnings[1] = 0; switch (temp1) @@ -125,15 +133,15 @@ void catReadEEPRom(void) case 0x45 : // if (temp0 == 0x03) { - cat[0] = 0x00; - cat[1] = 0xD0; + cat[P1] = 0x00; + cat[P2] = 0xD0; } break; case 0x47 : // if (temp0 == 0x03) { - cat[0] = 0xDC; - cat[1] = 0xE0; + cat[P1] = 0xDC; + cat[P2] = 0xE0; } break; case 0x55 : @@ -145,8 +153,8 @@ void catReadEEPRom(void) //5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE //6 : //7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0) - cat[0] = 0x80 + ((VFO_B == globalSettings.activeVfo) ? 1 : 0); - cat[1] = 0x00; + cat[P1] = 0x80 + ((VFO_B == globalSettings.activeVfo) ? 1 : 0); + cat[P2] = 0x00; break; case 0x57 : // //0 : 1-0 AGC Mode 00 = Auto, 01 = Fast, 10 = Slow, 11 = Off @@ -156,8 +164,8 @@ void catReadEEPRom(void) //6 Lock On/Off 0 = Off, 1 = On (Dial Lock) //7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning) - cat[0] = 0xC0; - cat[1] = 0x40; + cat[P1] = 0xC0; + cat[P2] = 0x40; break; case 0x59 : // band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom) //http://www.ka7oei.com/ft817_memmap.html @@ -165,59 +173,58 @@ void catReadEEPRom(void) //CAT_BUFF[1] = 0x82; break; case 0x5C : //Beep Volume (0-100) (#13) - cat[0] = 0xB2; - cat[1] = 0x42; + cat[P1] = 0xB2; + cat[P2] = 0x42; break; case 0x5E : //3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz //5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel //7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW //CAT_BUFF[0] = 0x08; - cat[0] = (globalSettings.cwSideToneFreq - 300)/50; - cat[1] = 0x25; + cat[P1] = (globalSettings.cwSideToneFreq - 300)/50; + cat[P2] = 0x25; break; case 0x61 : //globalSettings.cwSideToneFreq (Volume) (#44) - cat[0] = globalSettings.cwSideToneFreq % 50; - cat[1] = 0x08; + cat[P1] = globalSettings.cwSideToneFreq % 50; + cat[P2] = 0x08; break; case 0x5F : // //4-0 CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps //5 420 ARS (#2) 0 = Off, 1 = On //6 144 ARS (#1) 0 = Off, 1 = On //7 Sql/RF-G (#45) 0 = Off, 1 = On - cat[0] = 0x32; - cat[1] = 0x08; + cat[P1] = 0x32; + cat[P2] = 0x08; break; case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms - cat[0] = globalSettings.cwActiveTimeoutMs / 10; - cat[1] = 0x32; + cat[P1] = globalSettings.cwActiveTimeoutMs / 10; + cat[P2] = 0x32; break; case 0x62 : // //5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps) //7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours //CAT_BUFF[0] = 0x08; - cat[0] = 1200 / globalSettings.cwDitDurationMs - 4; - cat[1] = 0xB2; + cat[P1] = 1200 / globalSettings.cwDitDurationMs - 4; + cat[P2] = 0xB2; break; case 0x63 : // //6-0 VOX Gain (#51) Contains 1-100 (decimal) as displayed //7 Disable AM/FM Dial (#4) 0 = Enable, 1 = Disable - cat[0] = 0xB2; - cat[1] = 0xA5; + cat[P1] = 0xB2; + cat[P2] = 0xA5; break; case 0x64 : // break; case 0x67 : //6-0 SSB Mic (#46) Contains 0-100 (decimal) as displayed - cat[0] = 0xB2; - cat[1] = 0xB2; - break; case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed + cat[P1] = 0xB2; + cat[P2] = 0xB2; + break; + case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed case 0x78 : if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) - cat[0] = CAT_MODE_USB; + cat[P1] = CAT_MODE_USB << 5; else - cat[0] = CAT_MODE_LSB; - - if (cat[0] != 0) cat[0] = 1 << 5; + cat[P1] = CAT_MODE_LSB << 5; break; case 0x79 : // //1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1 @@ -225,8 +232,8 @@ void catReadEEPRom(void) //DW On/Off 0 = Off, 1 = On //SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down //ART On/Off 0 = Off, 1 = On - cat[0] = 0x00; - cat[1] = 0x00; + cat[P1] = 0x00; + cat[P2] = 0x00; break; case 0x7A : //SPLIT //7A 0 HF Antenna Select 0 = Front, 1 = Rear @@ -238,11 +245,11 @@ void catReadEEPRom(void) //7A 6 ? ? //7A 7 SPL On/Off 0 = Off, 1 = On - cat[0] = (globalSettings.splitOn ? 0xFF : 0x7F); + cat[P1] = (globalSettings.splitOn ? 0xFF : 0x7F); break; case 0xB3 : // - cat[0] = 0x00; - cat[1] = 0x4D; + cat[P1] = 0x00; + cat[P2] = 0x4D; break; } @@ -421,8 +428,8 @@ void checkCAT(){ catCount++; /* - if (cat[4] != 0xf7 && cat[4] != 0xbb && cat[4] != 0x03){ - sprintf(b, "%d %02x %02x%02x%02x%02x", catCount, cat[4],cat[0], cat[1], cat[2], cat[3]); + if (cat[CMD] != 0xf7 && cat[CMD] != 0xbb && cat[CMD] != 0x03){ + sprintf(b, "%d %02x %02x%02x%02x%02x", catCount, cat[CMD],cat[P1], cat[P2], cat[P3], cat[P4]); printLine2(b); } */ From e8c80a830447620ed98f03773cfe3b3329cdc5b7 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 14:48:11 -0700 Subject: [PATCH 282/324] Replace 'byte' with 'uint8_t' --- ubitx_cat.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index d4992b9..090244f 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -16,7 +16,7 @@ */ static unsigned long rxBufferArriveTime = 0; -static byte rxBufferCheckCount = 0; +static uint8_t rxBufferCheckCount = 0; static uint8_t cat[5];//Data is ordered parameters 1-4, then command code last enum CatDataIndex_e : uint8_t { @@ -27,7 +27,7 @@ enum CatDataIndex_e : uint8_t { CMD = 4 }; -static byte insideCat = 0; +static uint8_t insideCat = 0; //for broken protocol static const uint16_t CAT_RECEIVE_TIMEOUT = 500; @@ -46,32 +46,32 @@ static const uint8_t ACK = 0; unsigned int skipTimeCount = 0; -byte setHighNibble(byte b,byte v) { +uint8_t setHighNibble(uint8_t b, uint8_t v) { // Clear the high nibble b &= 0x0f; // Set the high nibble return b | ((v & 0x0f) << 4); } -byte setLowNibble(byte b,byte v) { +uint8_t setLowNibble(uint8_t b, uint8_t v) { // Clear the low nibble b &= 0xf0; // Set the low nibble return b | (v & 0x0f); } -byte getHighNibble(byte b) { +uint8_t getHighNibble(uint8_t b) { return (b >> 4) & 0x0f; } -byte getLowNibble(byte b) { +uint8_t getLowNibble(uint8_t b) { return b & 0x0f; } // Takes a number and produces the requested number of decimal digits, staring // from the least significant digit. // -void getDecimalDigits(unsigned long number,byte* result,int digits) { +void getDecimalDigits(unsigned long number, uint8_t* result,int digits) { for (int i = 0; i < digits; i++) { // "Mask off" (in a decimal sense) the LSD and return it result[i] = number % 10; @@ -82,11 +82,11 @@ void getDecimalDigits(unsigned long number,byte* result,int digits) { // Takes a frequency and writes it into the CAT command buffer in BCD form. // -void writeFreq(unsigned long freq,byte* cmd) { +void writeFreq(unsigned long freq, uint8_t* cmd) { // Convert the frequency to a set of decimal digits. We are taking 9 digits // so that we can get up to 999 MHz. But the protocol doesn't care about the // LSD (1's place), so we ignore that digit. - byte digits[9]; + uint8_t digits[9]; getDecimalDigits(freq,digits,9); // Start from the LSB and get each nibble cmd[3] = setLowNibble(cmd[3],digits[1]); @@ -99,12 +99,12 @@ void writeFreq(unsigned long freq,byte* cmd) { cmd[0] = setHighNibble(cmd[0],digits[8]); } -// This function takes a frquency that is encoded using 4 bytes of BCD +// This function takes a frquency that is encoded using 4 uint8_ts of BCD // representation and turns it into an long measured in Hz. // // [12][34][56][78] = 123.45678? Mhz // -unsigned long readFreq(byte* cmd) { +unsigned long readFreq(uint8_t* cmd) { // Pull off each of the digits unsigned long ret = 0; for(uint8_t i = 0; i < 4; ++i){ @@ -117,12 +117,12 @@ unsigned long readFreq(byte* cmd) { return ret*10; } -//void ReadEEPRom_FT817(byte fromType) +//void ReadEEPRom_FT817(uint8_t fromType) void catReadEEPRom(void) { //for remove warnings - byte temp0 = cat[P1]; - byte temp1 = cat[P2]; + uint8_t temp0 = cat[P1]; + uint8_t temp1 = cat[P2]; cat[P1] = 0; cat[P2] = 0; @@ -258,8 +258,8 @@ void catReadEEPRom(void) Serial.write(cat, 2); } -void processCATCommand2(byte* cmd) { - byte response[5]; +void processCATCommand2(uint8_t* cmd) { + uint8_t response[5]; unsigned long f; switch(cmd[4]){ @@ -376,7 +376,7 @@ void processCATCommand2(byte* cmd) { break; default: - //somehow, get this to print the four bytes + //somehow, get this to print the four uint8_ts ultoa(*((unsigned long *)cmd), c, 16); response[0] = 0x00; Serial.write(response[0]); @@ -387,7 +387,7 @@ void processCATCommand2(byte* cmd) { int catCount = 0; void checkCAT(){ - byte i; + uint8_t i; //Check Serial Port Buffer if (Serial.available() == 0) { //Set Buffer Clear status From 18a05460aa31d78a803b33a0539c3788c263abf3 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 15:32:06 -0700 Subject: [PATCH 283/324] Simplify timeout logic, saving nearly 100 bytes --- ubitx_cat.cpp | 82 ++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 60 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 090244f..3ed4123 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -15,10 +15,9 @@ * it gives time out error with WSJTX 1.8.0 */ -static unsigned long rxBufferArriveTime = 0; -static uint8_t rxBufferCheckCount = 0; +static const uint8_t FT817_MESSAGE_SIZE = 5; -static uint8_t cat[5];//Data is ordered parameters 1-4, then command code last +//Data is ordered parameters 1-4, then command code last enum CatDataIndex_e : uint8_t { P1 = 0, P2 = 1, @@ -27,10 +26,8 @@ enum CatDataIndex_e : uint8_t { CMD = 4 }; -static uint8_t insideCat = 0; - //for broken protocol -static const uint16_t CAT_RECEIVE_TIMEOUT = 500; +static const uint16_t CAT_RECEIVE_TIMEOUT_MS = 500; static const uint8_t CAT_MODE_LSB = 0x00; static const uint8_t CAT_MODE_USB = 0x01; @@ -44,8 +41,6 @@ static const uint8_t CAT_MODE_FMN = 0x88; static const uint8_t ACK = 0; -unsigned int skipTimeCount = 0; - uint8_t setHighNibble(uint8_t b, uint8_t v) { // Clear the high nibble b &= 0x0f; @@ -118,7 +113,7 @@ unsigned long readFreq(uint8_t* cmd) { } //void ReadEEPRom_FT817(uint8_t fromType) -void catReadEEPRom(void) +void catReadEEPRom(uint8_t* cat) { //for remove warnings uint8_t temp0 = cat[P1]; @@ -347,7 +342,7 @@ void processCATCommand2(uint8_t* cmd) { break; case 0xBB: //Read FT-817 EEPROM Data (for comfirtable) - catReadEEPRom(); + catReadEEPRom(cmd); break; case 0xe7 : @@ -381,67 +376,34 @@ void processCATCommand2(uint8_t* cmd) { response[0] = 0x00; Serial.write(response[0]); } - - insideCat = false; } -int catCount = 0; void checkCAT(){ - uint8_t i; - + static uint8_t rx_buffer[FT817_MESSAGE_SIZE]; + static uint8_t current_index = 0; + static uint32_t timeout = 0; //Check Serial Port Buffer if (Serial.available() == 0) { //Set Buffer Clear status - rxBufferCheckCount = 0; + if(timeout < millis()){ + current_index = 0; + timeout = 0; + } return; } - else if (Serial.available() < 5) { //First Arrived - if (rxBufferCheckCount == 0){ - rxBufferCheckCount = Serial.available(); - rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout + else{ + if(0 == current_index){ + timeout = millis() + CAT_RECEIVE_TIMEOUT_MS; } - else if (rxBufferArriveTime < millis()){ //Clear Buffer - for (i = 0; i < Serial.available(); i++) - rxBufferCheckCount = Serial.read(); - rxBufferCheckCount = 0; + rx_buffer[current_index] = Serial.read(); + ++current_index; + if(current_index < FT817_MESSAGE_SIZE){ + return; } - else if (rxBufferCheckCount < Serial.available()){ // Increase buffer count, slow arrive - rxBufferCheckCount = Serial.available(); - rxBufferArriveTime = millis() + CAT_RECEIVE_TIMEOUT; //Set time for timeout - } - return; } - - //Arived CAT DATA - for (i = 0; i < 5; i++) - cat[i] = Serial.read(); - - - //this code is not re-entrant. - if (insideCat == 1) - return; - insideCat = 1; - -/** - * This routine is enabled to debug the cat protocol -**/ - catCount++; - -/* - if (cat[CMD] != 0xf7 && cat[CMD] != 0xbb && cat[CMD] != 0x03){ - sprintf(b, "%d %02x %02x%02x%02x%02x", catCount, cat[CMD],cat[P1], cat[P2], cat[P3], cat[P4]); - printLine2(b); - } -*/ - -/* - if (!doingCAT){ - doingCAT = 1; - displayText("CAT on", 100,120,100,40, ILI9341_ORANGE, ILI9341_BLACK, ILI9341_WHITE); - } -*/ - processCATCommand2(cat); - insideCat = 0; + processCATCommand2(rx_buffer); + current_index = 0; + timeout = 0; } From 8aa80bdbc7f8ae55c477389fbc502fad2d5849d1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 15:34:13 -0700 Subject: [PATCH 284/324] Rename processing function, remove trailing spaces --- ubitx_cat.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 3ed4123..d87da83 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -7,12 +7,12 @@ /** * The CAT protocol is used by many radios to provide remote control to comptuers through * the serial port. - * + * * This is very much a work in progress. Parts of this code have been liberally * borrowed from other GPLicensed works like hamlib. - * - * WARNING : This is an unstable version and it has worked with fldigi, - * it gives time out error with WSJTX 1.8.0 + * + * WARNING : This is an unstable version and it has worked with fldigi, + * it gives time out error with WSJTX 1.8.0 */ static const uint8_t FT817_MESSAGE_SIZE = 5; @@ -64,7 +64,7 @@ uint8_t getLowNibble(uint8_t b) { } // Takes a number and produces the requested number of decimal digits, staring -// from the least significant digit. +// from the least significant digit. // void getDecimalDigits(unsigned long number, uint8_t* result,int digits) { for (int i = 0; i < digits; i++) { @@ -83,7 +83,7 @@ void writeFreq(unsigned long freq, uint8_t* cmd) { // LSD (1's place), so we ignore that digit. uint8_t digits[9]; getDecimalDigits(freq,digits,9); - // Start from the LSB and get each nibble + // Start from the LSB and get each nibble cmd[3] = setLowNibble(cmd[3],digits[1]); cmd[3] = setHighNibble(cmd[3],digits[2]); cmd[2] = setLowNibble(cmd[2],digits[3]); @@ -91,7 +91,7 @@ void writeFreq(unsigned long freq, uint8_t* cmd) { cmd[1] = setLowNibble(cmd[1],digits[5]); cmd[1] = setHighNibble(cmd[1],digits[6]); cmd[0] = setLowNibble(cmd[0],digits[7]); - cmd[0] = setHighNibble(cmd[0],digits[8]); + cmd[0] = setHighNibble(cmd[0],digits[8]); } // This function takes a frquency that is encoded using 4 uint8_ts of BCD @@ -122,7 +122,7 @@ void catReadEEPRom(uint8_t* cat) cat[P1] = 0; cat[P2] = 0; //for remove warnings[1] = 0; - + switch (temp1) { case 0x45 : // @@ -253,36 +253,36 @@ void catReadEEPRom(uint8_t* cat) Serial.write(cat, 2); } -void processCATCommand2(uint8_t* cmd) { +void processCatCommand(uint8_t* cmd) { uint8_t response[5]; unsigned long f; - + switch(cmd[4]){ /* case 0x00: response[0]=0; Serial.write(response, 1); break; -*/ +*/ case 0x01: //set frequency f = readFreq(cmd); - setFrequency(f); + setFrequency(f); updateDisplay(); response[0]=0; Serial.write(response, 1); - //sprintf(b, "set:%ld", f); + //sprintf(b, "set:%ld", f); //printLine2(b); break; case 0x02: - //split on + //split on globalSettings.splitOn = 1; break; case 0x82: //split off globalSettings.splitOn = 0; break; - + case 0x03: writeFreq(GetActiveVfoFreq(),response); // Put the frequency into the buffer if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) @@ -292,7 +292,7 @@ void processCATCommand2(uint8_t* cmd) { Serial.write(response,5); //printLine2("cat:getfreq"); break; - + case 0x07: // set mode if (cmd[0] == 0x00 || cmd[0] == 0x03) SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); @@ -303,8 +303,8 @@ void processCATCommand2(uint8_t* cmd) { setFrequency(GetActiveVfoFreq()); //printLine2("cat: mode changed"); //updateDisplay(); - break; - + break; + case 0x08: // PTT On if (!globalSettings.txActive) { response[0] = 0; @@ -313,7 +313,7 @@ void processCATCommand2(uint8_t* cmd) { updateDisplay(); } else { response[0] = 0xf0; - } + } Serial.write(response,1); updateDisplay(); break; @@ -345,18 +345,18 @@ void processCATCommand2(uint8_t* cmd) { catReadEEPRom(cmd); break; - case 0xe7 : + case 0xe7 : // get receiver status, we have hardcoded this as //as we dont' support ctcss, etc. response[0] = 0x09; Serial.write(response,1); break; - + case 0xf7: { boolean isHighSWR = false; boolean issplitOn = false; - + /* Inverted -> *ptt = ((p->tx_status & 0x80) == 0); <-- souce code in ft817.c (hamlib) */ @@ -369,7 +369,7 @@ void processCATCommand2(uint8_t* cmd) { Serial.write(response, 1); } break; - + default: //somehow, get this to print the four uint8_ts ultoa(*((unsigned long *)cmd), c, 16); @@ -401,7 +401,7 @@ void checkCAT(){ } } - processCATCommand2(rx_buffer); + processCatCommand(rx_buffer); current_index = 0; timeout = 0; } From a3b9f703ba74d68f1cbbd21aea441175d7326d78 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 15:36:37 -0700 Subject: [PATCH 285/324] Replace more indicies with enums --- ubitx_cat.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index d87da83..67cb7fc 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -84,14 +84,14 @@ void writeFreq(unsigned long freq, uint8_t* cmd) { uint8_t digits[9]; getDecimalDigits(freq,digits,9); // Start from the LSB and get each nibble - cmd[3] = setLowNibble(cmd[3],digits[1]); - cmd[3] = setHighNibble(cmd[3],digits[2]); - cmd[2] = setLowNibble(cmd[2],digits[3]); - cmd[2] = setHighNibble(cmd[2],digits[4]); - cmd[1] = setLowNibble(cmd[1],digits[5]); - cmd[1] = setHighNibble(cmd[1],digits[6]); - cmd[0] = setLowNibble(cmd[0],digits[7]); - cmd[0] = setHighNibble(cmd[0],digits[8]); + cmd[P4] = setLowNibble(cmd[P4],digits[1]); + cmd[P4] = setHighNibble(cmd[P4],digits[2]); + cmd[P3] = setLowNibble(cmd[P3],digits[3]); + cmd[P3] = setHighNibble(cmd[P3],digits[4]); + cmd[P2] = setLowNibble(cmd[P2],digits[5]); + cmd[P2] = setHighNibble(cmd[P2],digits[6]); + cmd[P1] = setLowNibble(cmd[P1],digits[7]); + cmd[P1] = setHighNibble(cmd[P1],digits[8]); } // This function takes a frquency that is encoded using 4 uint8_ts of BCD @@ -257,7 +257,7 @@ void processCatCommand(uint8_t* cmd) { uint8_t response[5]; unsigned long f; - switch(cmd[4]){ + switch(cmd[CMD]){ /* case 0x00: response[0]=0; Serial.write(response, 1); @@ -294,7 +294,7 @@ void processCatCommand(uint8_t* cmd) { break; case 0x07: // set mode - if (cmd[0] == 0x00 || cmd[0] == 0x03) + if (cmd[P1] == 0x00 || cmd[P1] == 0x03) SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); else SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); From 8e4adbff72de12adc148fde26e820600cc0606eb Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 16:36:27 -0700 Subject: [PATCH 286/324] Add enums for a bunch of commands --- ubitx_cat.cpp | 82 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 67cb7fc..a4a3685 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -26,19 +26,77 @@ enum CatDataIndex_e : uint8_t { CMD = 4 }; +enum Ft817Command_e : uint8_t { + //Listed in the order presented by FT-817ND_OM_ENG_E13771011.pdf + OffBit = 0x80, + LockOn = 0x00, + LockOff = LockOn | OffBit, + PttOn = 0x08, + PttOff = PttOn | OffBit, + SetFrequency = 0x01,//P1-P4 are BCD, 0x01 0x42 0x34 0x56 = 14.23456MHz + OperatingMode = 0x07,//See OperatingMode_e for P1 decode + ClarOn = 0x05, + ClarOff = ClarOn | OffBit, + ClarFrequency = 0xF5,//P1 is sign/direction (0x00 = +, - otherwise), P3-P4 are BCD, 0x12 0x34 = 12.34kHz + VfoToggle = 0x81, + SplitOn = 0x02, + SplitOff = SplitOn | OffBit, + RepeaterMode = 0x09,//See RepeaterMode_e for P1 decode + RepeaterOffset = 0xF9,//P1-P4 are BCD + CtcssDcsMode = 0x0A,//See CtcssDcsMode_e for P1 decode + CtcssTone = 0x0B,//P1-P2 are BCD, 0x08 0x85 = 88.5MHz + DcsTone = 0x0C,//P1-P2 are BCD, 0x00 0x23 = code 023 + ReadRxStatus = 0xE7,//Returns ReadRxStatus_t + ReadTxStatus = 0xF7,//Returns ReadTxStatus_t + ReadFreqAndMode = 0x03,//Returns current frequency (BCD, 4 bytes), then mode (OperatingMode_e) + PowerOn = 0x0F, + PowerOff = PowerOn | OffBit, +}; + +enum OperatingMode_e : uint8_t { + LSB = 0x00, + USB = 0x01, + CW = 0x02, + CWR = 0x03, + AM = 0x04, + FM = 0x08, + DIG = 0x0A, + PKT = 0x0C, +}; + +enum RepeaterMode_e : uint8_t { + ShiftMinus = 0x09, + ShiftPlus = 0x49, + Simplex = 0x89, +}; + +enum CtcssDcsMode_e : uint8_t { + DcsOn = 0x0A, + CtcssOn = 0x2A, + EncoderOn = 0x4A, + Off = 0x8A, +}; + +struct ReadRxStatus_t { + //Bitfields are not defined by the standard to be portable, which is unfortunate + uint8_t Smeter : 4; + uint8_t Dummy : 1; + uint8_t DiscriminatorCenteringOff : 1; + uint8_t CodeUnmatched : 1; + uint8_t SquelchSuppressionActive : 1; +}; + +struct ReadTxStatus_t { + uint8_t PowerOutputMeter : 4; + uint8_t Dummy : 1; + uint8_t SplitOff : 1; + uint8_t HighSwrDetected : 1; + uint8_t PttOff : 1; +}; + //for broken protocol static const uint16_t CAT_RECEIVE_TIMEOUT_MS = 500; -static const uint8_t CAT_MODE_LSB = 0x00; -static const uint8_t CAT_MODE_USB = 0x01; -static const uint8_t CAT_MODE_CW = 0x02; -static const uint8_t CAT_MODE_CWR = 0x03; -static const uint8_t CAT_MODE_AM = 0x04; -static const uint8_t CAT_MODE_FM = 0x08; -static const uint8_t CAT_MODE_DIG = 0x0A; -static const uint8_t CAT_MODE_PKT = 0x0C; -static const uint8_t CAT_MODE_FMN = 0x88; - static const uint8_t ACK = 0; uint8_t setHighNibble(uint8_t b, uint8_t v) { @@ -217,9 +275,9 @@ void catReadEEPRom(uint8_t* cat) case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed case 0x78 : if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) - cat[P1] = CAT_MODE_USB << 5; + cat[P1] = OperatingMode_e::USB << 5; else - cat[P1] = CAT_MODE_LSB << 5; + cat[P1] = OperatingMode_e::LSB << 5; break; case 0x79 : // //1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1 From c6d83beff0de78c9116dccf426480e9fc3f3651c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 17:45:43 -0700 Subject: [PATCH 287/324] Use enums instead of hardcoded numbers --- ubitx_cat.cpp | 124 +++++++++++++++++++++++++------------------------- 1 file changed, 63 insertions(+), 61 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index a4a3685..c088e1d 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -57,7 +57,7 @@ enum OperatingMode_e : uint8_t { LSB = 0x00, USB = 0x01, CW = 0x02, - CWR = 0x03, + CWR = 0x03,//CW-reverse aka LSB CW AM = 0x04, FM = 0x08, DIG = 0x0A, @@ -79,7 +79,7 @@ enum CtcssDcsMode_e : uint8_t { struct ReadRxStatus_t { //Bitfields are not defined by the standard to be portable, which is unfortunate - uint8_t Smeter : 4; + uint8_t Smeter : 4;//0x00 = S0, 0x09 = S9, etc. uint8_t Dummy : 1; uint8_t DiscriminatorCenteringOff : 1; uint8_t CodeUnmatched : 1; @@ -87,6 +87,7 @@ struct ReadRxStatus_t { }; struct ReadTxStatus_t { + //Bitfields are not defined by the standard to be portable, which is unfortunate uint8_t PowerOutputMeter : 4; uint8_t Dummy : 1; uint8_t SplitOff : 1; @@ -157,7 +158,7 @@ void writeFreq(unsigned long freq, uint8_t* cmd) { // // [12][34][56][78] = 123.45678? Mhz // -unsigned long readFreq(uint8_t* cmd) { +uint32_t readFreq(uint8_t* cmd) { // Pull off each of the digits unsigned long ret = 0; for(uint8_t i = 0; i < 4; ++i){ @@ -312,82 +313,82 @@ void catReadEEPRom(uint8_t* cat) } void processCatCommand(uint8_t* cmd) { - uint8_t response[5]; - unsigned long f; + uint8_t response[FT817_MESSAGE_SIZE]; switch(cmd[CMD]){ -/* case 0x00: +/* case Ft817Command_e::LockOn: response[0]=0; Serial.write(response, 1); break; */ - case 0x01: - //set frequency - f = readFreq(cmd); + case Ft817Command_e::SetFrequency: + { + uint32_t f = readFreq(cmd); setFrequency(f); updateDisplay(); response[0]=0; Serial.write(response, 1); - //sprintf(b, "set:%ld", f); - //printLine2(b); break; + } - case 0x02: - //split on - globalSettings.splitOn = 1; + case Ft817Command_e::SplitOn: + globalSettings.splitOn = true; break; - case 0x82: - //split off - globalSettings.splitOn = 0; + case Ft817Command_e::SplitOff: + globalSettings.splitOn = false; break; - case 0x03: - writeFreq(GetActiveVfoFreq(),response); // Put the frequency into the buffer - if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) - response[4] = 0x01; //USB - else - response[4] = 0x00; //LSB + case Ft817Command_e::ReadFreqAndMode: + //First 4 bytes are the frequency + writeFreq(GetActiveVfoFreq(),response);//bytes 0-3 + //Last byte is the mode + if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + response[4] = OperatingMode_e::USB; + } + else{ + response[4] = OperatingMode_e::LSB; + } Serial.write(response,5); - //printLine2("cat:getfreq"); break; - case 0x07: // set mode - if (cmd[P1] == 0x00 || cmd[P1] == 0x03) + case Ft817Command_e::OperatingMode: + if(OperatingMode_e::LSB == cmd[P1] || OperatingMode_e::CWR == cmd[P1]){ SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - else + } + else{ SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + } response[0] = 0x00; Serial.write(response, 1); - setFrequency(GetActiveVfoFreq()); - //printLine2("cat: mode changed"); - //updateDisplay(); + + setFrequency(GetActiveVfoFreq());//Refresh frequency to get new mode to take effect + updateDisplay(); break; - case 0x08: // PTT On + case Ft817Command_e::PttOn: if (!globalSettings.txActive) { response[0] = 0; globalSettings.txCatActive = true; - startTx(TuningMode_e::TUNE_SSB); - updateDisplay(); - } else { + startTx(globalSettings.tuningMode); + } + else { response[0] = 0xf0; } Serial.write(response,1); updateDisplay(); break; - case 0x88 : //PTT OFF + case Ft817Command_e::PttOff: if (globalSettings.txActive) { stopTx(); - globalSettings.txCatActive = false; } + globalSettings.txCatActive = false; response[0] = 0; Serial.write(response,1); updateDisplay(); break; - case 0x81: - //toggle the VFOs + case Ft817Command_e::VfoToggle: response[0] = 0; if (Vfo_e::VFO_A == globalSettings.activeVfo){ globalSettings.activeVfo = Vfo_e::VFO_B; @@ -399,38 +400,39 @@ void processCatCommand(uint8_t* cmd) { updateDisplay(); break; - case 0xBB: //Read FT-817 EEPROM Data (for comfirtable) + case 0xBB: //Read FT-817 EEPROM Data (for comfirtable) catReadEEPRom(cmd); break; - case 0xe7 : - // get receiver status, we have hardcoded this as - //as we dont' support ctcss, etc. - response[0] = 0x09; + case Ft817Command_e::ReadRxStatus: + //We don't have visibility into these values, so just hard code stuff + ReadRxStatus_t reply_status; + reply_status.Dummy = 0; + reply_status.Smeter = 9;//S9 + reply_status.SquelchSuppressionActive = 0; + reply_status.DiscriminatorCenteringOff = 1; + reply_status.CodeUnmatched = 0; + response[0] = *(uint8_t*)&reply_status; Serial.write(response,1); break; - case 0xf7: - { - boolean isHighSWR = false; - boolean issplitOn = false; - - /* - Inverted -> *ptt = ((p->tx_status & 0x80) == 0); <-- souce code in ft817.c (hamlib) - */ - response[0] = ((globalSettings.txActive ? 0 : 1) << 7) + - ((isHighSWR ? 1 : 0) << 6) + //hi swr off / on - ((issplitOn ? 1 : 0) << 5) + //Split on / off - (0 << 4) + //dummy data - 0x08; //P0 meter data - - Serial.write(response, 1); - } + case Ft817Command_e::ReadTxStatus: + { + //We don't have visibility into some of these values, so just hard code stuff + ReadTxStatus_t reply_status; + reply_status.Dummy = 0; + reply_status.HighSwrDetected = 0; + reply_status.PowerOutputMeter = 0xF; + reply_status.PttOff = !globalSettings.txActive; + reply_status.SplitOff = !globalSettings.splitOn; + + response[0] = *(uint8_t*)&reply_status; + + Serial.write(response, 1); break; + } default: - //somehow, get this to print the four uint8_ts - ultoa(*((unsigned long *)cmd), c, 16); response[0] = 0x00; Serial.write(response[0]); } From 53a39b06996822c3dc6756f2552827c70220995c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 17:55:23 -0700 Subject: [PATCH 288/324] Revise switch to use a single Serial.write, based on switched changes --- ubitx_cat.cpp | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index c088e1d..d33e0af 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -313,21 +313,17 @@ void catReadEEPRom(uint8_t* cat) } void processCatCommand(uint8_t* cmd) { - uint8_t response[FT817_MESSAGE_SIZE]; + uint8_t response[FT817_MESSAGE_SIZE] = {0}; + uint8_t response_length = 0; switch(cmd[CMD]){ -/* case Ft817Command_e::LockOn: - response[0]=0; - Serial.write(response, 1); - break; -*/ case Ft817Command_e::SetFrequency: { uint32_t f = readFreq(cmd); setFrequency(f); updateDisplay(); - response[0]=0; - Serial.write(response, 1); + response[0] = 0x00; + response_length = 1; break; } @@ -359,7 +355,7 @@ void processCatCommand(uint8_t* cmd) { SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); } response[0] = 0x00; - Serial.write(response, 1); + response_length = 1; setFrequency(GetActiveVfoFreq());//Refresh frequency to get new mode to take effect updateDisplay(); @@ -367,14 +363,14 @@ void processCatCommand(uint8_t* cmd) { case Ft817Command_e::PttOn: if (!globalSettings.txActive) { - response[0] = 0; + response[0] = 0x00; globalSettings.txCatActive = true; startTx(globalSettings.tuningMode); } else { - response[0] = 0xf0; + response[0] = 0xF0; } - Serial.write(response,1); + response_length = 1; updateDisplay(); break; @@ -383,20 +379,20 @@ void processCatCommand(uint8_t* cmd) { stopTx(); } globalSettings.txCatActive = false; - response[0] = 0; - Serial.write(response,1); + response[0] = 0x00; + response_length = 1; updateDisplay(); break; case Ft817Command_e::VfoToggle: - response[0] = 0; if (Vfo_e::VFO_A == globalSettings.activeVfo){ globalSettings.activeVfo = Vfo_e::VFO_B; } else{ globalSettings.activeVfo = Vfo_e::VFO_A; } - Serial.write(response,1); + response[0] = 0x00; + response_length = 1; updateDisplay(); break; @@ -413,7 +409,7 @@ void processCatCommand(uint8_t* cmd) { reply_status.DiscriminatorCenteringOff = 1; reply_status.CodeUnmatched = 0; response[0] = *(uint8_t*)&reply_status; - Serial.write(response,1); + response_length = 1; break; case Ft817Command_e::ReadTxStatus: @@ -427,15 +423,17 @@ void processCatCommand(uint8_t* cmd) { reply_status.SplitOff = !globalSettings.splitOn; response[0] = *(uint8_t*)&reply_status; - - Serial.write(response, 1); + response_length = 1; break; } default: response[0] = 0x00; - Serial.write(response[0]); + response_length = 1; + break; } + + Serial.write(response, response_length); } void checkCAT(){ From eba70c64ef858d5afe887ca9629a93a91f9c4062 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 21:35:44 -0700 Subject: [PATCH 289/324] Swap EEPROM virtualization hardcoding for multi-byte reading using enums --- ubitx_cat.cpp | 205 ++++++++++++++++++++++++++++---------------------- 1 file changed, 116 insertions(+), 89 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index d33e0af..d2ff735 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -95,6 +95,27 @@ struct ReadTxStatus_t { uint8_t PttOff : 1; }; +//Values based on http://www.ka7oei.com/ft817_memmap.html +enum Ft817Eeprom_e : uint16_t { + VfoAndBankSelect = 0x0055, + TuningModes = 0x0057, + KeyerStatus = 0x0058, + BandSelect = 0x0059, + BeepVolume = 0x005C, + CwPitch = 0x005E, + CwWeight = 0x005F, + CwDelay = 0x0060, + SidetoneVolume = 0x0061, + CwSpeed = 0x0062, + VoxGain = 0x0063, + CatBaudRate = 0x0064, + SsbMicVolume = 0x0067, + AmMicVolume = 0x0068, + FmMicVolume = 0x0069, + TxPower = 0x0079, + AntennaSelectAndSplit = 0x007A, +}; + //for broken protocol static const uint16_t CAT_RECEIVE_TIMEOUT_MS = 500; @@ -171,34 +192,11 @@ uint32_t readFreq(uint8_t* cmd) { return ret*10; } -//void ReadEEPRom_FT817(uint8_t fromType) -void catReadEEPRom(uint8_t* cat) +void catGetEeprom(const uint16_t read_address, uint8_t* response) { - //for remove warnings - uint8_t temp0 = cat[P1]; - uint8_t temp1 = cat[P2]; - - cat[P1] = 0; - cat[P2] = 0; - //for remove warnings[1] = 0; - - switch (temp1) + switch (read_address) { - case 0x45 : // - if (temp0 == 0x03) - { - cat[P1] = 0x00; - cat[P2] = 0xD0; - } - break; - case 0x47 : // - if (temp0 == 0x03) - { - cat[P1] = 0xDC; - cat[P2] = 0xE0; - } - break; - case 0x55 : + case Ft817Eeprom_e::VfoAndBankSelect: //0 : VFO A/B 0 = VFO-A, 1 = VFO-B //1 : MTQMB Select 0 = (Not MTQMB), 1 = MTQMB ("Memory Tune Quick Memory Bank") //2 : QMB Select 0 = (Not QMB), 1 = QMB ("Quick Memory Bank") @@ -207,10 +205,10 @@ void catReadEEPRom(uint8_t* cat) //5 : Memory/MTUNE select 0 = Memory, 1 = MTUNE //6 : //7 : MEM/VFO Select 0 = Memory, 1 = VFO (A or B - see bit 0) - cat[P1] = 0x80 + ((VFO_B == globalSettings.activeVfo) ? 1 : 0); - cat[P2] = 0x00; + *response = 0x80 //always report VFO mode + | ((VFO_B == globalSettings.activeVfo) ? 0x01 : 0x00); break; - case 0x57 : // + case Ft817Eeprom_e::TuningModes: //0 : 1-0 AGC Mode 00 = Auto, 01 = Fast, 10 = Slow, 11 = Off //2 DSP On/Off 0 = Off, 1 = On (Display format) //4 PBT On/Off 0 = Off, 1 = On (Passband Tuning) @@ -218,98 +216,126 @@ void catReadEEPRom(uint8_t* cat) //6 Lock On/Off 0 = Off, 1 = On (Dial Lock) //7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning) - cat[P1] = 0xC0; - cat[P2] = 0x40; + *response = 0xC0; + break; + case Ft817Eeprom_e::KeyerStatus: + //1-0: power meter mode: 00 = Power, 01 = ALC, 10 = SWR, 11 = MOD + //2 : CW paddle reverse: 1 = reverse + //3 : + //4 : CW keyer on/off: 1 = on + //5 : break on/off: 1 = semi break-in + //6 : voltmeter display on/off: 1 = display voltmeter + //7 : VOX on/off: 1 = on + *response = 0x40; break; - case 0x59 : // band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom) + case Ft817Eeprom_e::BandSelect: + //band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom) //http://www.ka7oei.com/ft817_memmap.html //CAT_BUFF[0] = 0xC2; //CAT_BUFF[1] = 0x82; break; - case 0x5C : //Beep Volume (0-100) (#13) - cat[P1] = 0xB2; - cat[P2] = 0x42; + case Ft817Eeprom_e::BeepVolume: + //6-0 : Beep Volume (0-100) (#13) + //7 : Beep Freq: 0 = 440Hz, 1 = 880Hz + *response = 0xB2; break; - case 0x5E : + case Ft817Eeprom_e::CwPitch: //3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz //5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel //7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW //CAT_BUFF[0] = 0x08; - cat[P1] = (globalSettings.cwSideToneFreq - 300)/50; - cat[P2] = 0x25; + *response = (globalSettings.cwSideToneFreq - 300)/50; break; - case 0x61 : //globalSettings.cwSideToneFreq (Volume) (#44) - cat[P1] = globalSettings.cwSideToneFreq % 50; - cat[P2] = 0x08; + case Ft817Eeprom_e::CwWeight: + //4-0 : CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps + //5 : 420 ARS (#2), 1 = on + //6 : 144 ARS (#1), 1 = on + //7 : Sql/RF-G (#45), 1 = on + *response = 0x25; break; - case 0x5F : // - //4-0 CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps - //5 420 ARS (#2) 0 = Off, 1 = On - //6 144 ARS (#1) 0 = Off, 1 = On - //7 Sql/RF-G (#45) 0 = Off, 1 = On - cat[P1] = 0x32; - cat[P2] = 0x08; + case Ft817Eeprom_e::SidetoneVolume: + //Sidetone (Volume) (#44) + *response = globalSettings.cwSideToneFreq % 50; break; - case 0x60 : //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms - cat[P1] = globalSettings.cwActiveTimeoutMs / 10; - cat[P2] = 0x32; + case Ft817Eeprom_e::CwDelay: + //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms + *response = globalSettings.cwActiveTimeoutMs / 10; break; - case 0x62 : // + case Ft817Eeprom_e::CwSpeed: //5-0 CW Speed (4-60 WPM) (#21) From 0 to 38 (HEX) with 0 = 4 WPM and 38 = 60 WPM (1 WPM steps) //7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours - //CAT_BUFF[0] = 0x08; - cat[P1] = 1200 / globalSettings.cwDitDurationMs - 4; - cat[P2] = 0xB2; + *response = (1200 / globalSettings.cwDitDurationMs) - 4; break; - case 0x63 : // + case Ft817Eeprom_e::VoxGain: //6-0 VOX Gain (#51) Contains 1-100 (decimal) as displayed //7 Disable AM/FM Dial (#4) 0 = Enable, 1 = Disable - cat[P1] = 0xB2; - cat[P2] = 0xA5; + *response = 0xB2; break; - case 0x64 : // + case Ft817Eeprom_e::CatBaudRate: + //4-0 : VOX Delay (#50) 0 = 100 Ms with each step representing 100 Ms. 24 = 2500 Ms + //5 : Emergency (#28) 0 = Off, 1 = On + //7-6 : CAT Rate (4800, 9600, 38400) (#14) 00 = 4800, 01 = 9600, 10 = 38400 Baud + *response = 0xA5; break; - case 0x67 : //6-0 SSB Mic (#46) Contains 0-100 (decimal) as displayed - cat[P1] = 0xB2; - cat[P2] = 0xB2; + case Ft817Eeprom_e::SsbMicVolume: + //6-0 : SSB Mic (#46) Contains 0-100 (decimal) as displayed + *response = 0xB2; break; - case 0x69 : //FM Mic (#29) Contains 0-100 (decimal) as displayed - case 0x78 : - if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()) - cat[P1] = OperatingMode_e::USB << 5; - else - cat[P1] = OperatingMode_e::LSB << 5; + case Ft817Eeprom_e::AmMicVolume: + //6-0 : AM Mic (#5) Contains 0-100 (decimal) as displayed + //7 : Mic Key (#36) 1 = on + *response = 0xB2; break; - case 0x79 : // + case Ft817Eeprom_e::FmMicVolume: + //6-0 : FM Mic (#29) Contains 0-100 (decimal) as displayed + //7 : Mic Scan (#37) 1 = on + case 0x78 ://?? + if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + *response = OperatingMode_e::USB << 5; + } + else{ + *response = OperatingMode_e::LSB << 5; + } + break; + case Ft817Eeprom_e::TxPower: //1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1 //3 PRI On/Off 0 = Off, 1 = On //DW On/Off 0 = Off, 1 = On //SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down //ART On/Off 0 = Off, 1 = On - cat[P1] = 0x00; - cat[P2] = 0x00; + *response = 0x00; break; - case 0x7A : //SPLIT - //7A 0 HF Antenna Select 0 = Front, 1 = Rear - //7A 1 6 M Antenna Select 0 = Front, 1 = Rear - //7A 2 FM BCB Antenna Select 0 = Front, 1 = Rear - //7A 3 Air Antenna Select 0 = Front, 1 = Rear - //7A 4 2 M Antenna Select 0 = Front, 1 = Rear - //7A 5 UHF Antenna Select 0 = Front, 1 = Rear - //7A 6 ? ? - //7A 7 SPL On/Off 0 = Off, 1 = On - - cat[P1] = (globalSettings.splitOn ? 0xFF : 0x7F); + case Ft817Eeprom_e::AntennaSelectAndSplit: + //0 : HF Antenna Select 0 = Front, 1 = Rear + //1 : 6 M Antenna Select 0 = Front, 1 = Rear + //2 : FM BCB Antenna Select 0 = Front, 1 = Rear + //3 : Air Antenna Select 0 = Front, 1 = Rear + //4 : 2 M Antenna Select 0 = Front, 1 = Rear + //5 : UHF Antenna Select 0 = Front, 1 = Rear + //6 : ? ? + //7 : SPL On/Off 0 = Off, 1 = On + + *response = (globalSettings.splitOn ? 0xFF : 0x7F); break; - case 0xB3 : // - cat[P1] = 0x00; - cat[P2] = 0x4D; + case 0xB3 : //0xB1 is the base address of Base address of VFO A, 40 M. + *response = 0x00; + break; + case 0xB4 : //0xB1 is the base address of Base address of VFO A, 40 M. + //2-0 : FM Step (Menu # 30) 000 = 5 kHz, 001 = 6.25 kHz, 010 = 10 kHz, 011 = 12.5 kHz, 100 = 15 kHz, 101 = 20 kHz, 110 = 25 kHz, 111 = 50 kHz + //5-3 : AM Step (Menu #6) 000 = 2.5 kHz, 001 = 5 kHz, 010 = 9 kHz, 011 = 10 kHz, 100 = 12.5 kHz, 101 = 25 kHz + //7-6 : SSB Step (Menu # 47) 00 = 1 kHz, 01 = 2.5 kHz, 10 = 5 kHz + *response = 0x4D; break; - } +} + +//Maps some of the fixed memory layout of the FT817's EEPROM +void catReadEEPRom(uint8_t* cmd, uint8_t* response) +{ + const uint16_t read_address = cmd[P1] << 8 | cmd[P2]; - // sent the data - Serial.write(cat, 2); + catGetEeprom(read_address,response); + catGetEeprom(read_address+1,response+1); } void processCatCommand(uint8_t* cmd) { @@ -397,7 +423,8 @@ void processCatCommand(uint8_t* cmd) { break; case 0xBB: //Read FT-817 EEPROM Data (for comfirtable) - catReadEEPRom(cmd); + catReadEEPRom(cmd,response); + response_length = 2; break; case Ft817Command_e::ReadRxStatus: From 8045b9b02b1f6775da724f304067ea8eeed80eba Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 22:35:35 -0700 Subject: [PATCH 290/324] Remove explicit 0 sets --- ubitx_cat.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index d2ff735..35be19d 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -303,7 +303,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //DW On/Off 0 = Off, 1 = On //SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down //ART On/Off 0 = Off, 1 = On - *response = 0x00; break; case Ft817Eeprom_e::AntennaSelectAndSplit: //0 : HF Antenna Select 0 = Front, 1 = Rear @@ -318,7 +317,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) *response = (globalSettings.splitOn ? 0xFF : 0x7F); break; case 0xB3 : //0xB1 is the base address of Base address of VFO A, 40 M. - *response = 0x00; break; case 0xB4 : //0xB1 is the base address of Base address of VFO A, 40 M. //2-0 : FM Step (Menu # 30) 000 = 5 kHz, 001 = 6.25 kHz, 010 = 10 kHz, 011 = 12.5 kHz, 100 = 15 kHz, 101 = 20 kHz, 110 = 25 kHz, 111 = 50 kHz @@ -380,7 +378,6 @@ void processCatCommand(uint8_t* cmd) { else{ SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); } - response[0] = 0x00; response_length = 1; setFrequency(GetActiveVfoFreq());//Refresh frequency to get new mode to take effect @@ -389,7 +386,6 @@ void processCatCommand(uint8_t* cmd) { case Ft817Command_e::PttOn: if (!globalSettings.txActive) { - response[0] = 0x00; globalSettings.txCatActive = true; startTx(globalSettings.tuningMode); } @@ -405,7 +401,6 @@ void processCatCommand(uint8_t* cmd) { stopTx(); } globalSettings.txCatActive = false; - response[0] = 0x00; response_length = 1; updateDisplay(); break; @@ -417,7 +412,6 @@ void processCatCommand(uint8_t* cmd) { else{ globalSettings.activeVfo = Vfo_e::VFO_A; } - response[0] = 0x00; response_length = 1; updateDisplay(); break; @@ -455,7 +449,6 @@ void processCatCommand(uint8_t* cmd) { } default: - response[0] = 0x00; response_length = 1; break; } From 2505e54235902f84dbd9c05fd49dd179ab1c51da Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 22:37:38 -0700 Subject: [PATCH 291/324] Remove unused cases --- ubitx_cat.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 35be19d..d90ed9b 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -215,7 +215,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //5 NB On/Off 0 = Off, 1 = On (Noise Blanker) //6 Lock On/Off 0 = Off, 1 = On (Dial Lock) //7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning) - *response = 0xC0; break; case Ft817Eeprom_e::KeyerStatus: @@ -228,12 +227,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //7 : VOX on/off: 1 = on *response = 0x40; break; - case Ft817Eeprom_e::BandSelect: - //band select VFO A Band Select 0000 = 160 M, 0001 = 75 M, 0010 = 40 M, 0011 = 30 M, 0100 = 20 M, 0101 = 17 M, 0110 = 15 M, 0111 = 12 M, 1000 = 10 M, 1001 = 6 M, 1010 = FM BCB, 1011 = Air, 1100 = 2 M, 1101 = UHF, 1110 = (Phantom) - //http://www.ka7oei.com/ft817_memmap.html - //CAT_BUFF[0] = 0xC2; - //CAT_BUFF[1] = 0x82; - break; case Ft817Eeprom_e::BeepVolume: //6-0 : Beep Volume (0-100) (#13) //7 : Beep Freq: 0 = 440Hz, 1 = 880Hz @@ -289,7 +282,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) case Ft817Eeprom_e::FmMicVolume: //6-0 : FM Mic (#29) Contains 0-100 (decimal) as displayed //7 : Mic Scan (#37) 1 = on - case 0x78 ://?? if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ *response = OperatingMode_e::USB << 5; } @@ -297,13 +289,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) *response = OperatingMode_e::LSB << 5; } break; - case Ft817Eeprom_e::TxPower: - //1-0 TX Power (All bands) 00 = High, 01 = L3, 10 = L2, 11 = L1 - //3 PRI On/Off 0 = Off, 1 = On - //DW On/Off 0 = Off, 1 = On - //SCN (Scan) Mode 00 = No scan, 10 = Scan up, 11 = Scan down - //ART On/Off 0 = Off, 1 = On - break; case Ft817Eeprom_e::AntennaSelectAndSplit: //0 : HF Antenna Select 0 = Front, 1 = Rear //1 : 6 M Antenna Select 0 = Front, 1 = Rear @@ -313,11 +298,8 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //5 : UHF Antenna Select 0 = Front, 1 = Rear //6 : ? ? //7 : SPL On/Off 0 = Off, 1 = On - *response = (globalSettings.splitOn ? 0xFF : 0x7F); break; - case 0xB3 : //0xB1 is the base address of Base address of VFO A, 40 M. - break; case 0xB4 : //0xB1 is the base address of Base address of VFO A, 40 M. //2-0 : FM Step (Menu # 30) 000 = 5 kHz, 001 = 6.25 kHz, 010 = 10 kHz, 011 = 12.5 kHz, 100 = 15 kHz, 101 = 20 kHz, 110 = 25 kHz, 111 = 50 kHz //5-3 : AM Step (Menu #6) 000 = 2.5 kHz, 001 = 5 kHz, 010 = 9 kHz, 011 = 10 kHz, 100 = 12.5 kHz, 101 = 25 kHz From ce0fac95fee5f2260f30bf2b81461ce4db5ef2e6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 23:02:10 -0700 Subject: [PATCH 292/324] Remove unused and fixed-output cases --- ubitx_cat.cpp | 66 +++++++-------------------------------------------- 1 file changed, 8 insertions(+), 58 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index d90ed9b..35b1141 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -114,6 +114,7 @@ enum Ft817Eeprom_e : uint16_t { FmMicVolume = 0x0069, TxPower = 0x0079, AntennaSelectAndSplit = 0x007A, + VfoAPhantomMode = 0x01E9, }; //for broken protocol @@ -208,30 +209,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) *response = 0x80 //always report VFO mode | ((VFO_B == globalSettings.activeVfo) ? 0x01 : 0x00); break; - case Ft817Eeprom_e::TuningModes: - //0 : 1-0 AGC Mode 00 = Auto, 01 = Fast, 10 = Slow, 11 = Off - //2 DSP On/Off 0 = Off, 1 = On (Display format) - //4 PBT On/Off 0 = Off, 1 = On (Passband Tuning) - //5 NB On/Off 0 = Off, 1 = On (Noise Blanker) - //6 Lock On/Off 0 = Off, 1 = On (Dial Lock) - //7 FST (Fast Tuning) On/Off 0 = Off, 1 = On (Fast tuning) - *response = 0xC0; - break; - case Ft817Eeprom_e::KeyerStatus: - //1-0: power meter mode: 00 = Power, 01 = ALC, 10 = SWR, 11 = MOD - //2 : CW paddle reverse: 1 = reverse - //3 : - //4 : CW keyer on/off: 1 = on - //5 : break on/off: 1 = semi break-in - //6 : voltmeter display on/off: 1 = display voltmeter - //7 : VOX on/off: 1 = on - *response = 0x40; - break; - case Ft817Eeprom_e::BeepVolume: - //6-0 : Beep Volume (0-100) (#13) - //7 : Beep Freq: 0 = 440Hz, 1 = 880Hz - *response = 0xB2; - break; case Ft817Eeprom_e::CwPitch: //3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz //5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel @@ -239,16 +216,9 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //CAT_BUFF[0] = 0x08; *response = (globalSettings.cwSideToneFreq - 300)/50; break; - case Ft817Eeprom_e::CwWeight: - //4-0 : CW Weight (1.:2.5-1:4.5) (#22) From 0 to 14 (HEX) with 0 = 1:2.5, incrementing in 0.1 weight steps - //5 : 420 ARS (#2), 1 = on - //6 : 144 ARS (#1), 1 = on - //7 : Sql/RF-G (#45), 1 = on - *response = 0x25; - break; case Ft817Eeprom_e::SidetoneVolume: - //Sidetone (Volume) (#44) - *response = globalSettings.cwSideToneFreq % 50; + //Sidetone (Volume) (#44) 0-100 + *response = globalSettings.cwSideToneFreq / 100; break; case Ft817Eeprom_e::CwDelay: //CW Delay (10-2500 ms) (#17) From 1 to 250 (decimal) with each step representing 10 ms @@ -259,34 +229,20 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //7-6 Batt-Chg (6/8/10 Hours (#11) 00 = 6 Hours, 01 = 8 Hours, 10 = 10 Hours *response = (1200 / globalSettings.cwDitDurationMs) - 4; break; - case Ft817Eeprom_e::VoxGain: - //6-0 VOX Gain (#51) Contains 1-100 (decimal) as displayed - //7 Disable AM/FM Dial (#4) 0 = Enable, 1 = Disable - *response = 0xB2; - break; case Ft817Eeprom_e::CatBaudRate: //4-0 : VOX Delay (#50) 0 = 100 Ms with each step representing 100 Ms. 24 = 2500 Ms //5 : Emergency (#28) 0 = Off, 1 = On //7-6 : CAT Rate (4800, 9600, 38400) (#14) 00 = 4800, 01 = 9600, 10 = 38400 Baud *response = 0xA5; break; - case Ft817Eeprom_e::SsbMicVolume: - //6-0 : SSB Mic (#46) Contains 0-100 (decimal) as displayed - *response = 0xB2; - break; - case Ft817Eeprom_e::AmMicVolume: - //6-0 : AM Mic (#5) Contains 0-100 (decimal) as displayed - //7 : Mic Key (#36) 1 = on - *response = 0xB2; - break; - case Ft817Eeprom_e::FmMicVolume: - //6-0 : FM Mic (#29) Contains 0-100 (decimal) as displayed - //7 : Mic Scan (#37) 1 = on + case Ft817Eeprom_e::VfoAPhantomMode: + //2-0 : 000 = LSB, 001 = USB, 010 = CW, 011 = CWR, 100 = AM, 101 = FM, 110 = DIG, 111 = PKT + //7-3 : ? if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ - *response = OperatingMode_e::USB << 5; + *response = OperatingMode_e::USB; } else{ - *response = OperatingMode_e::LSB << 5; + *response = OperatingMode_e::LSB; } break; case Ft817Eeprom_e::AntennaSelectAndSplit: @@ -300,12 +256,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //7 : SPL On/Off 0 = Off, 1 = On *response = (globalSettings.splitOn ? 0xFF : 0x7F); break; - case 0xB4 : //0xB1 is the base address of Base address of VFO A, 40 M. - //2-0 : FM Step (Menu # 30) 000 = 5 kHz, 001 = 6.25 kHz, 010 = 10 kHz, 011 = 12.5 kHz, 100 = 15 kHz, 101 = 20 kHz, 110 = 25 kHz, 111 = 50 kHz - //5-3 : AM Step (Menu #6) 000 = 2.5 kHz, 001 = 5 kHz, 010 = 9 kHz, 011 = 10 kHz, 100 = 12.5 kHz, 101 = 25 kHz - //7-6 : SSB Step (Menu # 47) 00 = 1 kHz, 01 = 2.5 kHz, 10 = 5 kHz - *response = 0x4D; - break; } } From 2e74193d9346b2252ab87b747258ac3d729217b3 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 23:54:38 -0700 Subject: [PATCH 293/324] Give 0xBB a name --- ubitx_cat.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 35b1141..e3eead1 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -51,6 +51,8 @@ enum Ft817Command_e : uint8_t { ReadFreqAndMode = 0x03,//Returns current frequency (BCD, 4 bytes), then mode (OperatingMode_e) PowerOn = 0x0F, PowerOff = PowerOn | OffBit, + //Unofficial commands + ReadEeprom = 0xBB, }; enum OperatingMode_e : uint8_t { @@ -96,6 +98,7 @@ struct ReadTxStatus_t { }; //Values based on http://www.ka7oei.com/ft817_memmap.html +//hamlib likes to read addresses 0x0064 and 0x007A, but including support for some others enum Ft817Eeprom_e : uint16_t { VfoAndBankSelect = 0x0055, TuningModes = 0x0057, @@ -213,7 +216,6 @@ void catGetEeprom(const uint16_t read_address, uint8_t* response) //3-0 : CW Pitch (300-1000 Hz) (#20) From 0 to E (HEX) with 0 = 300 Hz and each step representing 50 Hz //5-4 : Lock Mode (#32) 00 = Dial, 01 = Freq, 10 = Panel //7-6 : Op Filter (#38) 00 = Off, 01 = SSB, 10 = CW - //CAT_BUFF[0] = 0x08; *response = (globalSettings.cwSideToneFreq - 300)/50; break; case Ft817Eeprom_e::SidetoneVolume: @@ -348,7 +350,7 @@ void processCatCommand(uint8_t* cmd) { updateDisplay(); break; - case 0xBB: //Read FT-817 EEPROM Data (for comfirtable) + case Ft817Command_e::ReadEeprom: catReadEEPRom(cmd,response); response_length = 2; break; @@ -392,6 +394,7 @@ void checkCAT(){ static uint8_t rx_buffer[FT817_MESSAGE_SIZE]; static uint8_t current_index = 0; static uint32_t timeout = 0; + //Check Serial Port Buffer if (Serial.available() == 0) { //Set Buffer Clear status if(timeout < millis()){ From 97d825351c7db326f7424b8bfca3d0d0041c2e91 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 23:56:08 -0700 Subject: [PATCH 294/324] Re-enable numpad, now that we have some more space --- menu_main_buttons.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/menu_main_buttons.cpp b/menu_main_buttons.cpp index d495948..034b830 100644 --- a/menu_main_buttons.cpp +++ b/menu_main_buttons.cpp @@ -633,5 +633,5 @@ void osMenu(){ } void osNumpad(){ - //enterSubmenu(numpadMenu); + enterSubmenu(numpadMenu); } From 7a32c8e205df5958d2aa46c354dd9b9ba5be8950 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sun, 3 May 2020 23:58:58 -0700 Subject: [PATCH 295/324] Bump version number --- version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cpp b/version.cpp index 3534814..6ac2e9b 100644 --- a/version.cpp +++ b/version.cpp @@ -1,4 +1,4 @@ #include "version.h" -const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.2.0"; +const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.3.0"; const char* const VERSION_STRING = VERSION_STRING_PRIVATE; \ No newline at end of file From e770230d14a7cbe44bb697cc3821db7fcbe33f32 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 00:03:43 -0700 Subject: [PATCH 296/324] CAT debug stuff added --- ubitx_cat.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index e3eead1..1d0beb7 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -270,10 +270,23 @@ void catReadEEPRom(uint8_t* cmd, uint8_t* response) catGetEeprom(read_address+1,response+1); } +#include "nano_gui.h" +#include "color_theme.h" void processCatCommand(uint8_t* cmd) { uint8_t response[FT817_MESSAGE_SIZE] = {0}; uint8_t response_length = 0; + static uint8_t x = 0; + static uint8_t y = 0; + for(uint8_t i = 0; i < FT817_MESSAGE_SIZE; ++i){ + snprintf(b+2*i,sizeof(b)-2*i,"%02x",cmd[i]); + } + displayText(b,100*x,40*(1+y),320,30,DISPLAY_WHITE,DISPLAY_BLACK,DISPLAY_BLACK,TextJustification_e::Left); + x = (x + 1) % 3; + if(0 == x){ + y = (y + 1) % 5; + } + switch(cmd[CMD]){ case Ft817Command_e::SetFrequency: { @@ -394,7 +407,7 @@ void checkCAT(){ static uint8_t rx_buffer[FT817_MESSAGE_SIZE]; static uint8_t current_index = 0; static uint32_t timeout = 0; - +/* //Check Serial Port Buffer if (Serial.available() == 0) { //Set Buffer Clear status if(timeout < millis()){ @@ -412,7 +425,10 @@ void checkCAT(){ if(current_index < FT817_MESSAGE_SIZE){ return; } - } + }*/ + rx_buffer[P1] = timeout; + rx_buffer[P2] = current_index; + rx_buffer[CMD] = Ft817Command_e::ReadTxStatus; processCatCommand(rx_buffer); current_index = 0; From e809b37e29694b8d244087d16837179e74e051c6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 00:34:15 -0700 Subject: [PATCH 297/324] Invert split value from what Yaesu's documentation says, because hamlib reads it inverted --- ubitx_cat.cpp | 213 +++++++++++++++++++++++++------------------------- 1 file changed, 105 insertions(+), 108 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 1d0beb7..d561a81 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -288,116 +288,116 @@ void processCatCommand(uint8_t* cmd) { } switch(cmd[CMD]){ - case Ft817Command_e::SetFrequency: - { - uint32_t f = readFreq(cmd); - setFrequency(f); - updateDisplay(); - response[0] = 0x00; - response_length = 1; - break; - } - - case Ft817Command_e::SplitOn: - globalSettings.splitOn = true; - break; - case Ft817Command_e::SplitOff: - globalSettings.splitOn = false; - break; - - case Ft817Command_e::ReadFreqAndMode: - //First 4 bytes are the frequency - writeFreq(GetActiveVfoFreq(),response);//bytes 0-3 - //Last byte is the mode - if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ - response[4] = OperatingMode_e::USB; - } - else{ - response[4] = OperatingMode_e::LSB; + case Ft817Command_e::SetFrequency: + { + uint32_t f = readFreq(cmd); + setFrequency(f); + updateDisplay(); + response[0] = 0x00; + response_length = 1; + break; } - Serial.write(response,5); - break; - case Ft817Command_e::OperatingMode: - if(OperatingMode_e::LSB == cmd[P1] || OperatingMode_e::CWR == cmd[P1]){ - SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); - } - else{ - SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); - } - response_length = 1; + case Ft817Command_e::SplitOn: + globalSettings.splitOn = true; + break; + case Ft817Command_e::SplitOff: + globalSettings.splitOn = false; + break; - setFrequency(GetActiveVfoFreq());//Refresh frequency to get new mode to take effect - updateDisplay(); - break; + case Ft817Command_e::ReadFreqAndMode: + //First 4 bytes are the frequency + writeFreq(GetActiveVfoFreq(),response);//bytes 0-3 + //Last byte is the mode + if (VfoMode_e::VFO_MODE_USB == GetActiveVfoMode()){ + response[4] = OperatingMode_e::USB; + } + else{ + response[4] = OperatingMode_e::LSB; + } + Serial.write(response,5); + break; - case Ft817Command_e::PttOn: - if (!globalSettings.txActive) { - globalSettings.txCatActive = true; - startTx(globalSettings.tuningMode); - } - else { - response[0] = 0xF0; - } - response_length = 1; - updateDisplay(); - break; + case Ft817Command_e::OperatingMode: + if(OperatingMode_e::LSB == cmd[P1] || OperatingMode_e::CWR == cmd[P1]){ + SetActiveVfoMode(VfoMode_e::VFO_MODE_LSB); + } + else{ + SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); + } + response_length = 1; - case Ft817Command_e::PttOff: - if (globalSettings.txActive) { - stopTx(); - } - globalSettings.txCatActive = false; - response_length = 1; - updateDisplay(); - break; - - case Ft817Command_e::VfoToggle: - if (Vfo_e::VFO_A == globalSettings.activeVfo){ - globalSettings.activeVfo = Vfo_e::VFO_B; - } - else{ - globalSettings.activeVfo = Vfo_e::VFO_A; + setFrequency(GetActiveVfoFreq());//Refresh frequency to get new mode to take effect + updateDisplay(); + break; + + case Ft817Command_e::PttOn: + if (!globalSettings.txActive) { + globalSettings.txCatActive = true; + startTx(globalSettings.tuningMode); + } + else { + response[0] = 0xF0; + } + response_length = 1; + updateDisplay(); + break; + + case Ft817Command_e::PttOff: + if (globalSettings.txActive) { + stopTx(); + } + globalSettings.txCatActive = false; + response_length = 1; + updateDisplay(); + break; + + case Ft817Command_e::VfoToggle: + if (Vfo_e::VFO_A == globalSettings.activeVfo){ + globalSettings.activeVfo = Vfo_e::VFO_B; + } + else{ + globalSettings.activeVfo = Vfo_e::VFO_A; + } + response_length = 1; + updateDisplay(); + break; + + case Ft817Command_e::ReadEeprom: + catReadEEPRom(cmd,response); + response_length = 2; + break; + + case Ft817Command_e::ReadRxStatus: + //We don't have visibility into these values, so just hard code stuff + ReadRxStatus_t reply_status; + reply_status.Dummy = 0; + reply_status.Smeter = 9;//S9 + reply_status.SquelchSuppressionActive = 0; + reply_status.DiscriminatorCenteringOff = 1; + reply_status.CodeUnmatched = 0; + response[0] = *(uint8_t*)&reply_status; + response_length = 1; + break; + + case Ft817Command_e::ReadTxStatus: + { + //We don't have visibility into some of these values, so just hard code stuff + ReadTxStatus_t reply_status; + reply_status.Dummy = 0; + reply_status.HighSwrDetected = 0; + reply_status.PowerOutputMeter = 0xF; + reply_status.PttOff = !globalSettings.txActive; + reply_status.SplitOff = globalSettings.splitOn;//Yaesu's documentation says that 1 = split off, but as of 2020-05-04 hamlib reads (*split = (p->tx_status & 0x20) ? RIG_SPLIT_ON : RIG_SPLIT_OFF), so do what hamlib wants + + response[0] = *(uint8_t*)&reply_status; + response_length = 1; + break; } - response_length = 1; - updateDisplay(); - break; - - case Ft817Command_e::ReadEeprom: - catReadEEPRom(cmd,response); - response_length = 2; - break; - - case Ft817Command_e::ReadRxStatus: - //We don't have visibility into these values, so just hard code stuff - ReadRxStatus_t reply_status; - reply_status.Dummy = 0; - reply_status.Smeter = 9;//S9 - reply_status.SquelchSuppressionActive = 0; - reply_status.DiscriminatorCenteringOff = 1; - reply_status.CodeUnmatched = 0; - response[0] = *(uint8_t*)&reply_status; - response_length = 1; - break; - - case Ft817Command_e::ReadTxStatus: - { - //We don't have visibility into some of these values, so just hard code stuff - ReadTxStatus_t reply_status; - reply_status.Dummy = 0; - reply_status.HighSwrDetected = 0; - reply_status.PowerOutputMeter = 0xF; - reply_status.PttOff = !globalSettings.txActive; - reply_status.SplitOff = !globalSettings.splitOn; - - response[0] = *(uint8_t*)&reply_status; - response_length = 1; - break; - } - default: - response_length = 1; - break; + default: + response_length = 1; + break; } Serial.write(response, response_length); @@ -407,7 +407,7 @@ void checkCAT(){ static uint8_t rx_buffer[FT817_MESSAGE_SIZE]; static uint8_t current_index = 0; static uint32_t timeout = 0; -/* + //Check Serial Port Buffer if (Serial.available() == 0) { //Set Buffer Clear status if(timeout < millis()){ @@ -425,10 +425,7 @@ void checkCAT(){ if(current_index < FT817_MESSAGE_SIZE){ return; } - }*/ - rx_buffer[P1] = timeout; - rx_buffer[P2] = current_index; - rx_buffer[CMD] = Ft817Command_e::ReadTxStatus; + } processCatCommand(rx_buffer); current_index = 0; From a7cbf503849467c0fea70f5fbc9cce49404848ad Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 00:43:38 -0700 Subject: [PATCH 298/324] Fix comment based on reviewing hamlib code --- ubitx_cat.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index d561a81..dd7adfa 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -98,7 +98,7 @@ struct ReadTxStatus_t { }; //Values based on http://www.ka7oei.com/ft817_memmap.html -//hamlib likes to read addresses 0x0064 and 0x007A, but including support for some others +//hamlib likes to read addresses 0x0065 (read as 0x0064) and 0x007A, but including support for some others enum Ft817Eeprom_e : uint16_t { VfoAndBankSelect = 0x0055, TuningModes = 0x0057, From 6a6dc2a29a7aa467364baafcd201dfe9db918ec1 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 00:56:25 -0700 Subject: [PATCH 299/324] Remove debug drawing --- ubitx_cat.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index dd7adfa..86b950f 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -270,23 +270,10 @@ void catReadEEPRom(uint8_t* cmd, uint8_t* response) catGetEeprom(read_address+1,response+1); } -#include "nano_gui.h" -#include "color_theme.h" void processCatCommand(uint8_t* cmd) { uint8_t response[FT817_MESSAGE_SIZE] = {0}; uint8_t response_length = 0; - static uint8_t x = 0; - static uint8_t y = 0; - for(uint8_t i = 0; i < FT817_MESSAGE_SIZE; ++i){ - snprintf(b+2*i,sizeof(b)-2*i,"%02x",cmd[i]); - } - displayText(b,100*x,40*(1+y),320,30,DISPLAY_WHITE,DISPLAY_BLACK,DISPLAY_BLACK,TextJustification_e::Left); - x = (x + 1) % 3; - if(0 == x){ - y = (y + 1) % 5; - } - switch(cmd[CMD]){ case Ft817Command_e::SetFrequency: { From 4cf8f7a840dca931baeec8fae0b27730a5919a79 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 00:58:49 -0700 Subject: [PATCH 300/324] Use ACK/RACK, and set default response length to 1 so that it usually doesn't have to be re-set. --- ubitx_cat.cpp | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index 86b950f..b09192b 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -17,6 +17,9 @@ static const uint8_t FT817_MESSAGE_SIZE = 5; +static const uint8_t ACK = 0x00; +static const uint8_t RACK = 0xF0;//Re-Acknowledge sent when the state requests is already active + //Data is ordered parameters 1-4, then command code last enum CatDataIndex_e : uint8_t { P1 = 0, @@ -123,8 +126,6 @@ enum Ft817Eeprom_e : uint16_t { //for broken protocol static const uint16_t CAT_RECEIVE_TIMEOUT_MS = 500; -static const uint8_t ACK = 0; - uint8_t setHighNibble(uint8_t b, uint8_t v) { // Clear the high nibble b &= 0x0f; @@ -271,8 +272,9 @@ void catReadEEPRom(uint8_t* cmd, uint8_t* response) } void processCatCommand(uint8_t* cmd) { - uint8_t response[FT817_MESSAGE_SIZE] = {0}; - uint8_t response_length = 0; + //A response of a single byte, 0x00, is an ACK, so default to that + uint8_t response[FT817_MESSAGE_SIZE] = {ACK}; + uint8_t response_length = 1; switch(cmd[CMD]){ case Ft817Command_e::SetFrequency: @@ -280,15 +282,19 @@ void processCatCommand(uint8_t* cmd) { uint32_t f = readFreq(cmd); setFrequency(f); updateDisplay(); - response[0] = 0x00; - response_length = 1; break; } case Ft817Command_e::SplitOn: + if(globalSettings.splitOn){ + response[0] = RACK; + } globalSettings.splitOn = true; break; case Ft817Command_e::SplitOff: + if(!globalSettings.splitOn){ + response[0] = RACK; + } globalSettings.splitOn = false; break; @@ -302,7 +308,7 @@ void processCatCommand(uint8_t* cmd) { else{ response[4] = OperatingMode_e::LSB; } - Serial.write(response,5); + response_length = 5; break; case Ft817Command_e::OperatingMode: @@ -312,7 +318,6 @@ void processCatCommand(uint8_t* cmd) { else{ SetActiveVfoMode(VfoMode_e::VFO_MODE_USB); } - response_length = 1; setFrequency(GetActiveVfoFreq());//Refresh frequency to get new mode to take effect updateDisplay(); @@ -324,9 +329,8 @@ void processCatCommand(uint8_t* cmd) { startTx(globalSettings.tuningMode); } else { - response[0] = 0xF0; + response[0] = RACK; } - response_length = 1; updateDisplay(); break; @@ -334,8 +338,10 @@ void processCatCommand(uint8_t* cmd) { if (globalSettings.txActive) { stopTx(); } + else{ + response[0] = RACK; + } globalSettings.txCatActive = false; - response_length = 1; updateDisplay(); break; @@ -346,7 +352,6 @@ void processCatCommand(uint8_t* cmd) { else{ globalSettings.activeVfo = Vfo_e::VFO_A; } - response_length = 1; updateDisplay(); break; @@ -364,7 +369,6 @@ void processCatCommand(uint8_t* cmd) { reply_status.DiscriminatorCenteringOff = 1; reply_status.CodeUnmatched = 0; response[0] = *(uint8_t*)&reply_status; - response_length = 1; break; case Ft817Command_e::ReadTxStatus: @@ -378,12 +382,11 @@ void processCatCommand(uint8_t* cmd) { reply_status.SplitOff = globalSettings.splitOn;//Yaesu's documentation says that 1 = split off, but as of 2020-05-04 hamlib reads (*split = (p->tx_status & 0x20) ? RIG_SPLIT_ON : RIG_SPLIT_OFF), so do what hamlib wants response[0] = *(uint8_t*)&reply_status; - response_length = 1; break; } default: - response_length = 1; + //Do something? break; } From a138490dcc2f55e569aa0859bba35fe6a2f08dd3 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 21:57:24 -0700 Subject: [PATCH 301/324] Change decision making in main menu loop to ensure display consistency when CAT changes --- menu_main.cpp | 67 +++++++++++++++++++++++++++++++-------------- menu_main_buttons.h | 3 ++ 2 files changed, 50 insertions(+), 20 deletions(-) diff --git a/menu_main.cpp b/menu_main.cpp index 2285ef2..908826e 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -46,35 +46,62 @@ void drawMainMenu(void) morseText(b); } -void mainMenuTune(int16_t knob) +void drawMainMenuIncrement() { - static uint32_t current_freq = 0; + //State variables + static uint32_t last_freq = 0; + static Vfo_e last_vfo = Vfo_e::VFO_A; + static VfoMode_e last_mode = VfoMode_e::VFO_MODE_LSB; + static bool last_split = false; + static bool last_rit = false; + static TuningMode_e last_tuning = TuningMode_e::TUNE_SSB; - if((0 == knob) && (GetActiveVfoFreq() == current_freq)){ - //Nothing to do - we're already set! - return; - } + Button button; - current_freq = GetActiveVfoFreq(); - const uint32_t new_freq = current_freq + (50 * knob); - - setFrequency(new_freq); + if((last_freq != GetActiveVfoFreq()) + ||(last_vfo != globalSettings.activeVfo)){ + extractAndDrawButton(&button,&bVfoA); + extractAndDrawButton(&button,&bVfoB); + updateBandButtons(last_freq); + last_freq = GetActiveVfoFreq(); + last_vfo = globalSettings.activeVfo; + } - if(autoSelectSidebandChanged(current_freq)){ + if(last_mode != GetActiveVfoMode()){ updateSidebandButtons(); + last_mode = GetActiveVfoMode(); } - const uint32_t old_freq = current_freq; - current_freq = new_freq; - - Button button; - if(Vfo_e::VFO_A == globalSettings.activeVfo){ + if(last_split != globalSettings.splitOn){ extractAndDrawButton(&button,&bVfoA); - } - else{ extractAndDrawButton(&button,&bVfoB); + extractAndDrawButton(&button,&bSpl); + last_split = globalSettings.splitOn; } - updateBandButtons(old_freq); + + if(last_rit != globalSettings.ritOn){ + extractAndDrawButton(&button,&bRit); + last_rit = globalSettings.ritOn; + } + + if(last_tuning != globalSettings.tuningMode){ + extractAndDrawButton(&button,&bCw); + last_tuning = globalSettings.tuningMode; + } +} + +void mainMenuTune(int16_t knob) +{ + if(0 == knob){ + //Nothing to do - we're already set! + return; + } + + const uint32_t current_freq = GetActiveVfoFreq(); + const uint32_t new_freq = current_freq + (50 * knob); + + setFrequency(new_freq); + autoSelectSidebandChanged(current_freq); } MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, @@ -156,7 +183,7 @@ MenuReturn_e runMainMenu(const ButtonPress_e tuner_button, } } - // + drawMainMenuIncrement(); return MenuReturn_e::StillActive;//main menu always returns StillActive } \ No newline at end of file diff --git a/menu_main_buttons.h b/menu_main_buttons.h index 7795c82..8d5a0ae 100644 --- a/menu_main_buttons.h +++ b/menu_main_buttons.h @@ -9,6 +9,9 @@ extern const uint8_t MAIN_MENU_NUM_BUTTONS; extern const Button bVfoA; extern const Button bVfoB; +extern const Button bRit; +extern const Button bCw; +extern const Button bSpl; void updateBandButtons(const uint32_t old_freq); void updateSidebandButtons(); void drawTx(); From 2a412fd34af3b59a9e80ef7863d59c1abecb8b08 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 22:06:47 -0700 Subject: [PATCH 302/324] Force frequency change after recall. Unfortunately, this puts us just 4 bytes over the limit --- menu_quicklist_buttons.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/menu_quicklist_buttons.cpp b/menu_quicklist_buttons.cpp index 5b4fdfa..8fcec1f 100644 --- a/menu_quicklist_buttons.cpp +++ b/menu_quicklist_buttons.cpp @@ -7,6 +7,7 @@ #include "nano_gui.h" #include "scratch_space.h" #include "settings.h" +#include "tuner.h" #include "utils.h" static const unsigned int LAYOUT_BUTTON_X = 180; @@ -69,6 +70,7 @@ void osQuickListRecall(uint8_t index) { SetActiveVfoFreq(globalSettings.quickList[index].frequency); SetActiveVfoMode(globalSettings.quickList[index].mode); + setFrequency(GetActiveVfoFreq()); } void osQuickListSave(uint8_t index) From 0b65559e97694c0d09db2fa3bdbe933ea8a81207 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 22:26:09 -0700 Subject: [PATCH 303/324] Revert the previous commit --- menu_quicklist_buttons.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/menu_quicklist_buttons.cpp b/menu_quicklist_buttons.cpp index 8fcec1f..5b4fdfa 100644 --- a/menu_quicklist_buttons.cpp +++ b/menu_quicklist_buttons.cpp @@ -7,7 +7,6 @@ #include "nano_gui.h" #include "scratch_space.h" #include "settings.h" -#include "tuner.h" #include "utils.h" static const unsigned int LAYOUT_BUTTON_X = 180; @@ -70,7 +69,6 @@ void osQuickListRecall(uint8_t index) { SetActiveVfoFreq(globalSettings.quickList[index].frequency); SetActiveVfoMode(globalSettings.quickList[index].mode); - setFrequency(GetActiveVfoFreq()); } void osQuickListSave(uint8_t index) From e3f23ae755b7965be7f1dd6561075ba215585886 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 22:27:37 -0700 Subject: [PATCH 304/324] Slight tweak to how frequencies are changed so that quicklist changes will update the actual oscillators --- menu_main.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/menu_main.cpp b/menu_main.cpp index 908826e..08e8ff4 100644 --- a/menu_main.cpp +++ b/menu_main.cpp @@ -65,6 +65,9 @@ void drawMainMenuIncrement() updateBandButtons(last_freq); last_freq = GetActiveVfoFreq(); last_vfo = globalSettings.activeVfo; + + //We set this here so that we're always hearing what's displayed + setFrequency(last_freq); } if(last_mode != GetActiveVfoMode()){ @@ -100,7 +103,7 @@ void mainMenuTune(int16_t knob) const uint32_t current_freq = GetActiveVfoFreq(); const uint32_t new_freq = current_freq + (50 * knob); - setFrequency(new_freq); + SetActiveVfoFreq(new_freq); autoSelectSidebandChanged(current_freq); } From e168a4d5b0371c96de3ec44d2119a1066c00a17e Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 22:28:43 -0700 Subject: [PATCH 305/324] Bump version --- version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cpp b/version.cpp index 6ac2e9b..bb412ca 100644 --- a/version.cpp +++ b/version.cpp @@ -1,4 +1,4 @@ #include "version.h" -const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.3.0"; +const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.4.0"; const char* const VERSION_STRING = VERSION_STRING_PRIVATE; \ No newline at end of file From e7748d28782b772760e5ba4bee0105e1b99131cc Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 22:53:41 -0700 Subject: [PATCH 306/324] Switch colors from defines to consts --- colors.h | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/colors.h b/colors.h index 1743dbe..bb56762 100644 --- a/colors.h +++ b/colors.h @@ -1,20 +1,20 @@ // Color definitions -#define DISPLAY_BLACK 0x0000 ///< 0, 0, 0 -#define DISPLAY_NAVY 0x000F ///< 0, 0, 123 -#define DISPLAY_DARKGREEN 0x03E0 ///< 0, 125, 0 -#define DISPLAY_DARKCYAN 0x03EF ///< 0, 125, 123 -#define DISPLAY_MAROON 0x7800 ///< 123, 0, 0 -#define DISPLAY_PURPLE 0x780F ///< 123, 0, 123 -#define DISPLAY_OLIVE 0x7BE0 ///< 123, 125, 0 -#define DISPLAY_LIGHTGREY 0xC618 ///< 198, 195, 198 -#define DISPLAY_DARKGREY 0x7BEF ///< 123, 125, 123 -#define DISPLAY_BLUE 0x001F ///< 0, 0, 255 -#define DISPLAY_GREEN 0x07E0 ///< 0, 255, 0 -#define DISPLAY_CYAN 0x07FF ///< 0, 255, 255 -#define DISPLAY_RED 0xF800 ///< 255, 0, 0 -#define DISPLAY_MAGENTA 0xF81F ///< 255, 0, 255 -#define DISPLAY_YELLOW 0xFFE0 ///< 255, 255, 0 -#define DISPLAY_WHITE 0xFFFF ///< 255, 255, 255 -#define DISPLAY_ORANGE 0xFD20 ///< 255, 165, 0 -#define DISPLAY_GREENYELLOW 0xAFE5 ///< 173, 255, 41 -#define DISPLAY_PINK 0xFC18 ///< 255, 130, 198 +static const uint16_t DISPLAY_BLACK = 0x0000; ///< 0, 0, 0 +static const uint16_t DISPLAY_NAVY = 0x000F; ///< 0, 0, 123 +static const uint16_t DISPLAY_DARKGREEN = 0x03E0; ///< 0, 125, 0 +static const uint16_t DISPLAY_DARKCYAN = 0x03EF; ///< 0, 125, 123 +static const uint16_t DISPLAY_MAROON = 0x7800; ///< 123, 0, 0 +static const uint16_t DISPLAY_PURPLE = 0x780F; ///< 123, 0, 123 +static const uint16_t DISPLAY_OLIVE = 0x7BE0; ///< 123, 125, 0 +static const uint16_t DISPLAY_LIGHTGREY = 0xC618; ///< 198, 195, 198 +static const uint16_t DISPLAY_DARKGREY = 0x7BEF; ///< 123, 125, 123 +static const uint16_t DISPLAY_BLUE = 0x001F; ///< 0, 0, 255 +static const uint16_t DISPLAY_GREEN = 0x07E0; ///< 0, 255, 0 +static const uint16_t DISPLAY_CYAN = 0x07FF; ///< 0, 255, 255 +static const uint16_t DISPLAY_RED = 0xF800; ///< 255, 0, 0 +static const uint16_t DISPLAY_MAGENTA = 0xF81F; ///< 255, 0, 255 +static const uint16_t DISPLAY_YELLOW = 0xFFE0; ///< 255, 255, 0 +static const uint16_t DISPLAY_WHITE = 0xFFFF; ///< 255, 255, 255 +static const uint16_t DISPLAY_ORANGE = 0xFD20; ///< 255, 165, 0 +static const uint16_t DISPLAY_GREENYELLOW = 0xAFE5; ///< 173, 255, 41 +static const uint16_t DISPLAY_PINK = 0xFC18; ///< 255, 130, 198 From f541ff8928b962e252f5306772747740159257e6 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 23:00:31 -0700 Subject: [PATCH 307/324] Get rid of do-nothing functions --- nano_gui.h | 2 -- settings.cpp | 1 - tmp.cpp | 2 -- tuner.cpp | 2 -- ubitx_cat.cpp | 5 ----- 5 files changed, 12 deletions(-) delete mode 100644 tmp.cpp diff --git a/nano_gui.h b/nano_gui.h index e00d4c5..c8681ad 100644 --- a/nano_gui.h +++ b/nano_gui.h @@ -19,8 +19,6 @@ void displayChar(int16_t x, int16_t y, unsigned char c, uint16_t color, uint16_t void displayText(const char *const text, int x1, int y1, int w, int h, int color, int background, int border, TextJustification_e justification = TextJustification_e::Center); /* these functions are called universally to update the display */ -void updateDisplay(); //updates just the VFO frequency to show what is in 'frequency' variable -void redrawVFOs(); //redraws only the changed digits of the vfo void drawTx(); #define TEXT_LINE_HEIGHT 18 diff --git a/settings.cpp b/settings.cpp index efdd6ef..f496439 100644 --- a/settings.cpp +++ b/settings.cpp @@ -189,5 +189,4 @@ void SetActiveVfoMode(VfoMode_e mode) else{ globalSettings.vfoB.mode = mode; } - redrawVFOs(); } diff --git a/tmp.cpp b/tmp.cpp deleted file mode 100644 index 53c8aba..0000000 --- a/tmp.cpp +++ /dev/null @@ -1,2 +0,0 @@ -void updateDisplay() {} -void redrawVFOs(){} diff --git a/tuner.cpp b/tuner.cpp index 1eb3724..9e99ea6 100644 --- a/tuner.cpp +++ b/tuner.cpp @@ -19,7 +19,6 @@ void switchVFO(Vfo_e new_vfo){ globalSettings.activeVfo = new_vfo; setFrequency(GetActiveVfoFreq()); - redrawVFOs(); saveVFOs(); } @@ -194,7 +193,6 @@ void ritDisable(){ if(globalSettings.ritOn){ globalSettings.ritOn = false; setFrequency(globalSettings.ritFrequency); - updateDisplay(); } } diff --git a/ubitx_cat.cpp b/ubitx_cat.cpp index b09192b..b5fd491 100644 --- a/ubitx_cat.cpp +++ b/ubitx_cat.cpp @@ -281,7 +281,6 @@ void processCatCommand(uint8_t* cmd) { { uint32_t f = readFreq(cmd); setFrequency(f); - updateDisplay(); break; } @@ -320,7 +319,6 @@ void processCatCommand(uint8_t* cmd) { } setFrequency(GetActiveVfoFreq());//Refresh frequency to get new mode to take effect - updateDisplay(); break; case Ft817Command_e::PttOn: @@ -331,7 +329,6 @@ void processCatCommand(uint8_t* cmd) { else { response[0] = RACK; } - updateDisplay(); break; case Ft817Command_e::PttOff: @@ -342,7 +339,6 @@ void processCatCommand(uint8_t* cmd) { response[0] = RACK; } globalSettings.txCatActive = false; - updateDisplay(); break; case Ft817Command_e::VfoToggle: @@ -352,7 +348,6 @@ void processCatCommand(uint8_t* cmd) { else{ globalSettings.activeVfo = Vfo_e::VFO_A; } - updateDisplay(); break; case Ft817Command_e::ReadEeprom: From c323cec0cb4ae6146681d6bc0bd5f8b6828a073d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Mon, 4 May 2020 23:17:05 -0700 Subject: [PATCH 308/324] Update readme with lots of information for other prospective developers --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/README.md b/README.md index 23ca865..64d1a66 100644 --- a/README.md +++ b/README.md @@ -7,10 +7,59 @@ It was forked from https://github.com/afarhan/ubitxv6/ The purpose of this project is to clean up (modularize) the source code, and add features that were not present in Ashhar's original version of the project, without requiring any hardware modifications to a stock uBiTXv6. +New features include: + +* Much faster screen refresh (vs Ashhar's 6.3.1 aka 6.0 release) +* Morse code readback for sightless operation +* Save/recall your favorite frequencies +* When adjusting settings, the existing/current setting is shown as reference + +# Installing on Your Radio + +There are plenty of tutorials on how to upload sketches to Arduino Nanos. Just search for them. Addtionally, +Ashhar created a video explaining the process specifically for uBiTX6: https://www.youtube.com/watch?v=3n_V3prSJ_E + +I developed this code using the Arduino IDE 1.8.9 toolchain, with -Wall and -Wextra compiler options turned on, so +it should compile on newer or older versions, but may result in slightly different binary output sizes. + # Personalized Callsign To edit the callsign displayed, open the file `callsign.cpp` and change the string. Then re-compile and upload. +# Future Features/Modifications + +There are some features that would be good to add, but I just didn't get around to. + +* Setting to choose the tuning step size +* Setting to choose whether or not the knob tuning should accelerate (current behavior) or have a fixed interval +* Provide an option in each menu screen to load the default option for each setting +* Cancel out of the touch cal if the knob button is pressed + +While the current code (as of 2020-05-04) is 2 bytes shy of the 30720 available on the nano, there's still opportunity +to add new features by "creating" room. Below is a list of places you might create room: + +I added lots of bounds checking, especially on string writes, that, if removed, could free a good number of bytes. +While keeping them is best practice, for a non-IoT, non-critical piece of hardware, it shouldn't be a huge issue. + +I added the RACK to the CAT to better emulate the FT-817 (I hope, at least!). Removing the RACK's and just leaving +the default ACK's will also free up bytes. + +I added a bunch of strings to the menuing with the intention of helping people understand their functions, but +technically they're not necessary, and could all be removed. + +I switched to a smaller footprint font than Ashhar's original code, but there are MUCH smaller fonts out there. +Changing to a lower resolution, scaled up font can save hundreds or thousands of bytes, but won't look as pretty. +Also, the star, gear, and numpad icons will need to be either added to the new font, or replaced with characters. + +The first change I made to this fork was to replace Ashhar's original (incredibly slow) screen drawing routines +with PDQ. Since that change, Ashhar has updated his drawing routine to be MUCH faster than his original, but +still slightly slower than PDQ. It may be that Ashhar's new routines are smaller that PDQ, but I don't actually +know that for certain. + +There are a good number of instances of back-to-back calls of strncpy_P and displayText. Creating a single +function that performs these operations together, and then calling that new function instead of the +back-to-back calls everywhere may save space. + # License The majority of this code is released under GPL v3 license, per Ashhar's original code. From 488e462c6ca18b6160edb7dc394f7aee7d16619d Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 19:54:07 -0700 Subject: [PATCH 309/324] Debugging checkpoint --- touch.cpp | 65 ++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 17 deletions(-) diff --git a/touch.cpp b/touch.cpp index 74756cd..40c47de 100644 --- a/touch.cpp +++ b/touch.cpp @@ -8,6 +8,26 @@ constexpr int16_t Z_THRESHOLD = 400; constexpr uint8_t MSEC_THRESHOLD = 3; +constexpr uint8_t START_COMMAND = 1 << 7; +constexpr uint8_t CHANNEL_Y = 1 << 4; +constexpr uint8_t CHANNEL_Z1 = 3 << 4; +constexpr uint8_t CHANNEL_Z2 = 4 << 4; +constexpr uint8_t CHANNEL_X = 5 << 4; +constexpr uint8_t CHANNEL_TEMPERATURE = 7 << 4; +constexpr uint8_t USE_8_INSTEAD_OF_12_BIT = 1 << 3; +constexpr uint8_t USE_SINGLE_ENDED_MEASUREMENT = 1 << 2; +constexpr uint8_t POWER_OFF = 0 << 0; +constexpr uint8_t POWER_ADC = 1 << 0; +constexpr uint8_t POWER_REF = 2 << 0; +constexpr uint8_t POWER_ADC_REF = 3 << 0; + +constexpr uint16_t MEASURE_X = START_COMMAND | POWER_ADC | CHANNEL_Y;//X and Y channel labelling flip due to screen orientation +constexpr uint16_t MEASURE_Y = START_COMMAND | POWER_ADC | CHANNEL_X;//X and Y channel labelling flip due to screen orientation +constexpr uint16_t MEASURE_Z1 = START_COMMAND | POWER_ADC | CHANNEL_Z1; +constexpr uint16_t MEASURE_Z2 = START_COMMAND | POWER_ADC | CHANNEL_Z2; + +constexpr uint8_t RAW_READ_TO_12BIT_VALUE_SHIFT = 3;//16 bits read, zero-padded, but the MSB of the 16 is where the "BUSY" signal is asserted, so only need to shift by 3 instead of 4 + uint32_t msraw=0x80000000; int16_t xraw=0, yraw=0, zraw=0; constexpr uint8_t rotation = 1; @@ -29,35 +49,45 @@ int16_t touch_besttwoavg( int16_t x , int16_t y , int16_t z ) { } void touch_update(){ - int16_t data[6]; + zraw = 0;//Default value to report uint32_t now = millis(); - if (now - msraw < MSEC_THRESHOLD) return; + if (now - msraw < MSEC_THRESHOLD){ + return; + } SPI.beginTransaction(spiSettingsTouch); digitalWrite(PIN_TOUCH_CS, LOW); - SPI.transfer(0xB1 /* Z1 */); - int16_t z1 = SPI.transfer16(0xC1 /* Z2 */) >> 3; - int z = z1 + 4095; - int16_t z2 = SPI.transfer16(0x91 /* X */) >> 3; + + //NOTE: SPI transfers are synchronous, but require setup! + // What happens here is that we first send a command to measure + // an axis, then send our next measure command while receiving + // the measurement requested previously, which is why it looks + // like we're "off by one" between the variable names and the + // commands being issued + SPI.transfer(MEASURE_Z1); + int16_t z1 = SPI.transfer16(MEASURE_Z2) >> RAW_READ_TO_12BIT_VALUE_SHIFT; + int32_t z = z1 + 4095; + int16_t z2 = SPI.transfer16(MEASURE_X) >> RAW_READ_TO_12BIT_VALUE_SHIFT; z -= z2; - if (z < 0) z = 0; - if (z < Z_THRESHOLD) { // if ( !touched ) { - // Serial.println(); - zraw = 0; + Serial.print(F("z1:"));Serial.print(z1);Serial.print(F(" z2:"));Serial.print(z2);Serial.print(F(" z:"));Serial.println(z); + if (z < Z_THRESHOLD) { + SPI.transfer16(MEASURE_X & ~POWER_ADC_REF);//throw away the X measure so that we don't see it on the next check, and turn off the system + SPI.transfer16(0); digitalWrite(PIN_TOUCH_CS, HIGH); SPI.endTransaction(); return; } zraw = z; - SPI.transfer16(0x91 /* X */); // dummy X measure, 1st is always noisy - data[0] = SPI.transfer16(0xD1 /* Y */) >> 3; - data[1] = SPI.transfer16(0x91 /* X */) >> 3; // make 3 x-y measurements - data[2] = SPI.transfer16(0xD1 /* Y */) >> 3; - data[3] = SPI.transfer16(0x91 /* X */) >> 3; - data[4] = SPI.transfer16(0xD0 /* Y */) >> 3; // Last Y touch power down - data[5] = SPI.transfer16(0) >> 3; + SPI.transfer16(MEASURE_X); //throw away the first X measure, 1st is always noisy + int16_t data[6]; + data[0] = SPI.transfer16(MEASURE_Y) >> RAW_READ_TO_12BIT_VALUE_SHIFT; + data[1] = SPI.transfer16(MEASURE_X) >> RAW_READ_TO_12BIT_VALUE_SHIFT; // make 3 x-y measurements + data[2] = SPI.transfer16(MEASURE_Y) >> RAW_READ_TO_12BIT_VALUE_SHIFT; + data[3] = SPI.transfer16(MEASURE_X) >> RAW_READ_TO_12BIT_VALUE_SHIFT; + data[4] = SPI.transfer16(MEASURE_Y) >> RAW_READ_TO_12BIT_VALUE_SHIFT; + data[5] = SPI.transfer16(0) >> RAW_READ_TO_12BIT_VALUE_SHIFT; digitalWrite(PIN_TOUCH_CS, HIGH); SPI.endTransaction(); @@ -93,6 +123,7 @@ void initTouch(){ bool readTouch(Point *const touch_point_out){ touch_update(); + Serial.print(F("readTouch found zraw of "));Serial.println(zraw); if (zraw >= Z_THRESHOLD) { touch_point_out->x = xraw; touch_point_out->y = yraw; From f76b50fcc33813781f3f57e2100a8fac674140b2 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 20:34:28 -0700 Subject: [PATCH 310/324] Update commented out debug print, and remove black screen draw at the end --- nano_gui.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index 64cba7b..e1e0151 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -153,20 +153,20 @@ void setupTouch(){ globalSettings.touchOffsetX = cal_points[0].x - ((CROSS_CORNER_OFFSET * globalSettings.touchSlopeX)/SCALE_SENSITIVITY_MULTIPLIER); globalSettings.touchOffsetY = cal_points[0].y - ((CROSS_CORNER_OFFSET * globalSettings.touchSlopeY)/SCALE_SENSITIVITY_MULTIPLIER); + /* - Serial.print(x1);Serial.print(':');Serial.println(y1); - Serial.print(x2);Serial.print(':');Serial.println(y2); - Serial.print(x3);Serial.print(':');Serial.println(y3); - Serial.print(x4);Serial.print(':');Serial.println(y4); + for(uint8_t i = 0; i < sizeof(cal_points)/sizeof(cal_points[0]); ++i){ + Serial.print(cal_points[i].x);Serial.print(':');Serial.println(cal_points[i].y); + } //for debugging Serial.print(globalSettings.touchSlopeX); Serial.print(' '); Serial.print(globalSettings.touchSlopeY); Serial.print(' '); Serial.print(globalSettings.touchOffsetX); Serial.print(' '); Serial.println(globalSettings.touchOffsetY); Serial.println(' '); -*/ +*/ + SaveSettingsToEeprom(); - displayClear(DISPLAY_BLACK); } From d282062eefb17b2f2f7bf3cdc6064289dd2859ee Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 20:35:17 -0700 Subject: [PATCH 311/324] Force redraw after setupTouch is called so that menu is on screen --- setup.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/setup.cpp b/setup.cpp index 5024e60..64691f9 100644 --- a/setup.cpp +++ b/setup.cpp @@ -539,16 +539,23 @@ MenuReturn_e runSetupMenu(const MenuItem_t* const menu_items, enterSubmenu(&setupMenu##menu_name);\ }\ -const char MT_CAL [] PROGMEM = "Calibrations"; const char MI_TOUCH [] PROGMEM = "Touch Screen"; +void setupTouchSetting(); + +const char MT_CAL [] PROGMEM = "Calibrations"; const MenuItem_t menuItemsCalibration [] PROGMEM { {MT_CAL,nullptr},//Title {SS_LOCAL_OSC_T,runLocalOscSetting}, {SS_BFO_T,runBfoSetting}, - {MI_TOUCH,setupTouch}, + {MI_TOUCH,setupTouchSetting}, }; GENERATE_MENU_T(Calibration); +void setupTouchSetting(){ + setupTouch(); + initSetupMenuCalibration(); +} + const char MT_CW [] PROGMEM = "CW Setup"; const MenuItem_t menuItemsCw [] PROGMEM { {MT_CW,nullptr},//Title From b3a7e34d1b92e34677ed48a920f1018a7328c171 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 20:36:03 -0700 Subject: [PATCH 312/324] Replace 16-bit read style with slower, but apparently more reliable 8-bit read style --- touch.cpp | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/touch.cpp b/touch.cpp index 40c47de..47afcc0 100644 --- a/touch.cpp +++ b/touch.cpp @@ -28,6 +28,7 @@ constexpr uint16_t MEASURE_Z2 = START_COMMAND | POWER_ADC | CHANNEL_Z2; constexpr uint8_t RAW_READ_TO_12BIT_VALUE_SHIFT = 3;//16 bits read, zero-padded, but the MSB of the 16 is where the "BUSY" signal is asserted, so only need to shift by 3 instead of 4 + uint32_t msraw=0x80000000; int16_t xraw=0, yraw=0, zraw=0; constexpr uint8_t rotation = 1; @@ -48,6 +49,14 @@ int16_t touch_besttwoavg( int16_t x , int16_t y , int16_t z ) { return (reta); } +uint16_t touchReadChannel(uint8_t channel_command){ + //We assume that SPI.beginTransaction has already been called, and CS is LOW + SPI.transfer(channel_command);//Throw away any bytes here + const uint16_t tmpH = SPI.transfer(0) & 0x7F;//Leading 0 (during "busy" signal), followed by bits 11-5 + const uint16_t tmpL = SPI.transfer(0);//Bits 4-0, followed by 0s + return tmpH << 5 | tmpL >> 3; +} + void touch_update(){ zraw = 0;//Default value to report @@ -59,35 +68,26 @@ void touch_update(){ SPI.beginTransaction(spiSettingsTouch); digitalWrite(PIN_TOUCH_CS, LOW); - //NOTE: SPI transfers are synchronous, but require setup! - // What happens here is that we first send a command to measure - // an axis, then send our next measure command while receiving - // the measurement requested previously, which is why it looks - // like we're "off by one" between the variable names and the - // commands being issued - SPI.transfer(MEASURE_Z1); - int16_t z1 = SPI.transfer16(MEASURE_Z2) >> RAW_READ_TO_12BIT_VALUE_SHIFT; - int32_t z = z1 + 4095; - int16_t z2 = SPI.transfer16(MEASURE_X) >> RAW_READ_TO_12BIT_VALUE_SHIFT; - z -= z2; - Serial.print(F("z1:"));Serial.print(z1);Serial.print(F(" z2:"));Serial.print(z2);Serial.print(F(" z:"));Serial.println(z); + int16_t z1 = touchReadChannel(MEASURE_Z1);//~0 when not pressed, increases with pressure + int32_t z = z1; + int16_t z2 = touchReadChannel(MEASURE_Z2);//~4095 when not pressed, decreases with pressure + z += (4095 - z2); + //Serial.print(F("z1:"));Serial.print(z1);Serial.print(F(" z2:"));Serial.print(z2);Serial.print(F(" z:"));Serial.println(z); if (z < Z_THRESHOLD) { - SPI.transfer16(MEASURE_X & ~POWER_ADC_REF);//throw away the X measure so that we don't see it on the next check, and turn off the system - SPI.transfer16(0); digitalWrite(PIN_TOUCH_CS, HIGH); SPI.endTransaction(); return; } zraw = z; - SPI.transfer16(MEASURE_X); //throw away the first X measure, 1st is always noisy + // make 3 x-y measurements int16_t data[6]; - data[0] = SPI.transfer16(MEASURE_Y) >> RAW_READ_TO_12BIT_VALUE_SHIFT; - data[1] = SPI.transfer16(MEASURE_X) >> RAW_READ_TO_12BIT_VALUE_SHIFT; // make 3 x-y measurements - data[2] = SPI.transfer16(MEASURE_Y) >> RAW_READ_TO_12BIT_VALUE_SHIFT; - data[3] = SPI.transfer16(MEASURE_X) >> RAW_READ_TO_12BIT_VALUE_SHIFT; - data[4] = SPI.transfer16(MEASURE_Y) >> RAW_READ_TO_12BIT_VALUE_SHIFT; - data[5] = SPI.transfer16(0) >> RAW_READ_TO_12BIT_VALUE_SHIFT; + data[0] = touchReadChannel(MEASURE_X); + data[1] = touchReadChannel(MEASURE_Y); + data[2] = touchReadChannel(MEASURE_X); + data[3] = touchReadChannel(MEASURE_Y); + data[4] = touchReadChannel(MEASURE_X); + data[5] = touchReadChannel(MEASURE_Y & ~POWER_ADC_REF);//Turn off sensor digitalWrite(PIN_TOUCH_CS, HIGH); SPI.endTransaction(); @@ -123,7 +123,7 @@ void initTouch(){ bool readTouch(Point *const touch_point_out){ touch_update(); - Serial.print(F("readTouch found zraw of "));Serial.println(zraw); + //Serial.print(F("readTouch found zraw of "));Serial.println(zraw); if (zraw >= Z_THRESHOLD) { touch_point_out->x = xraw; touch_point_out->y = yraw; From e6fa6f935bf02b28f13636cab5483fb58e85a02f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 21:25:52 -0700 Subject: [PATCH 313/324] Fix zraw assignment issue that was preventing touch press-and-hold from working --- touch.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/touch.cpp b/touch.cpp index 47afcc0..56c84d4 100644 --- a/touch.cpp +++ b/touch.cpp @@ -6,7 +6,7 @@ #include "settings.h" constexpr int16_t Z_THRESHOLD = 400; -constexpr uint8_t MSEC_THRESHOLD = 3; +constexpr uint8_t MSEC_THRESHOLD = 3;//Max sample rate is 125kHz, but we'll limit ourselves conservatively constexpr uint8_t START_COMMAND = 1 << 7; constexpr uint8_t CHANNEL_Y = 1 << 4; @@ -58,8 +58,6 @@ uint16_t touchReadChannel(uint8_t channel_command){ } void touch_update(){ - zraw = 0;//Default value to report - uint32_t now = millis(); if (now - msraw < MSEC_THRESHOLD){ return; @@ -73,12 +71,13 @@ void touch_update(){ int16_t z2 = touchReadChannel(MEASURE_Z2);//~4095 when not pressed, decreases with pressure z += (4095 - z2); //Serial.print(F("z1:"));Serial.print(z1);Serial.print(F(" z2:"));Serial.print(z2);Serial.print(F(" z:"));Serial.println(z); - if (z < Z_THRESHOLD) { + + zraw = z; + if (zraw < Z_THRESHOLD) {//Don't bother reading x/y if we're not being touched digitalWrite(PIN_TOUCH_CS, HIGH); SPI.endTransaction(); return; } - zraw = z; // make 3 x-y measurements int16_t data[6]; @@ -88,14 +87,13 @@ void touch_update(){ data[3] = touchReadChannel(MEASURE_Y); data[4] = touchReadChannel(MEASURE_X); data[5] = touchReadChannel(MEASURE_Y & ~POWER_ADC_REF);//Turn off sensor + digitalWrite(PIN_TOUCH_CS, HIGH); SPI.endTransaction(); int16_t x = touch_besttwoavg( data[0], data[2], data[4] ); int16_t y = touch_besttwoavg( data[1], data[3], data[5] ); - - //Serial.printf(" %d,%d", x, y); - //Serial.println(); + msraw = now; // good read completed, set wait switch (rotation) { case 0: From 71e5f877da58cf5a18e36b9dcb78c1cf1b008a25 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 21:32:30 -0700 Subject: [PATCH 314/324] Add touch cancellation option --- nano_gui.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nano_gui.cpp b/nano_gui.cpp index e1e0151..821d1d7 100644 --- a/nano_gui.cpp +++ b/nano_gui.cpp @@ -2,6 +2,7 @@ #include "nano_gui.h" #include "colors.h" #include "pin_definitions.h" +#include "push_button.h" #include "scratch_space.h" #include "settings.h" #include "touch.h" @@ -116,7 +117,7 @@ void setupTouch(){ }; displayClear(DISPLAY_BLACK); - strncpy_P(b,(const char*)F("Click on the cross"),sizeof(b)); + strncpy_P(b,(const char*)F("Click on the cross\nPush tune to cancel"),sizeof(b)); displayText(b, 20,100, 200, 50, DISPLAY_WHITE, DISPLAY_BLACK, DISPLAY_BLACK); Point cal_points[sizeof(CROSS_CORNER_POINTS)/sizeof(CROSS_CORNER_POINTS[0])]; @@ -124,6 +125,9 @@ void setupTouch(){ for(uint8_t i = 0; i < sizeof(CROSS_CORNER_POINTS)/sizeof(CROSS_CORNER_POINTS[0]); ++i){ drawCross(CROSS_CORNER_POINTS[i].x,CROSS_CORNER_POINTS[i].y,DISPLAY_WHITE); while(!readTouch(&cal_points[i])){ + if(ButtonPress_e::NotPressed != CheckTunerButton()){ + return; + } delay(100); } while(readTouch(&cal_points[i])){ From 740e881d28be2e845bd1cbb186b77e312d336d4f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 21:34:20 -0700 Subject: [PATCH 315/324] Update readme due to new feature --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 64d1a66..c38030f 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ New features include: * Morse code readback for sightless operation * Save/recall your favorite frequencies * When adjusting settings, the existing/current setting is shown as reference +* Cancel touch recalibration # Installing on Your Radio @@ -33,10 +34,9 @@ There are some features that would be good to add, but I just didn't get around * Setting to choose the tuning step size * Setting to choose whether or not the knob tuning should accelerate (current behavior) or have a fixed interval * Provide an option in each menu screen to load the default option for each setting -* Cancel out of the touch cal if the knob button is pressed -While the current code (as of 2020-05-04) is 2 bytes shy of the 30720 available on the nano, there's still opportunity -to add new features by "creating" room. Below is a list of places you might create room: +While the current code (as of 2020-05-05) is ~100 bytes shy of the full 30720 available on the nano, there's still +opportunity to add new features by "creating" room. Below is a list of places you might create room: I added lots of bounds checking, especially on string writes, that, if removed, could free a good number of bytes. While keeping them is best practice, for a non-IoT, non-critical piece of hardware, it shouldn't be a huge issue. From 84f47b0a23986d69e32b0c8136223c82be1eda3c Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Tue, 5 May 2020 21:41:00 -0700 Subject: [PATCH 316/324] Bump version --- version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cpp b/version.cpp index bb412ca..29022ec 100644 --- a/version.cpp +++ b/version.cpp @@ -1,4 +1,4 @@ #include "version.h" -const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.4.0"; +const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.5.0"; const char* const VERSION_STRING = VERSION_STRING_PRIVATE; \ No newline at end of file From c11c8bfbe3cef2c144a38be46cffce49c3ce79bb Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 18 Jul 2020 18:58:43 -0700 Subject: [PATCH 317/324] Remove bands that aren't on dial from band lookup struct --- bands.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bands.cpp b/bands.cpp index c9f04ad..de05d66 100644 --- a/bands.cpp +++ b/bands.cpp @@ -16,19 +16,19 @@ struct Band_t { const char UNKNOWN_BAND_NAME [] PROGMEM = "??"; constexpr Band_t bands [] PROGMEM { - { 0UL, 255UL, 255, "U8"},//Utility conversion option - { 0UL, 65535UL, 254, "UF"},//Utility conversion option - { 530000UL, 1700000UL, 253, "AM"},//Broadcast AM, actually centers at 268, but uint8 can't do that - { 1800000UL, 2000000UL, 160, "A0"},//0xA0 is 160 +// { 0UL, 255UL, 255, "U8"},//Utility conversion option +// { 0UL, 65535UL, 254, "UF"},//Utility conversion option +// { 530000UL, 1700000UL, 253, "AM"},//Broadcast AM, actually centers at 268, but uint8 can't do that +// { 1800000UL, 2000000UL, 160, "A0"},//0xA0 is 160 { 3500000UL, 4000000UL, 80, "80"}, - { 5330500UL, 5403500UL, 60, "60"}, +// { 5330500UL, 5403500UL, 60, "60"}, { 7000000UL, 7300000UL, 40, "40"}, {10100000UL, 10150000UL, 30, "30"}, {14000000UL, 14350000UL, 20, "20"}, {18068000UL, 18168000UL, 17, "17"}, {21000000UL, 21450000UL, 15, "15"}, - {24890000UL, 24990000UL, 12, "12"}, - {26965000UL, 27405000UL, 11, "CB"},//Citizen's Band +// {24890000UL, 24990000UL, 12, "12"}, +// {26965000UL, 27405000UL, 11, "CB"},//Citizen's Band {28000000UL, 29700000UL, 10, "10"}, }; constexpr uint8_t NUM_BANDS = sizeof(bands)/sizeof(bands[0]); From c62eaaba2eff010eb55ad6e6a75327b4031369f8 Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 18 Jul 2020 20:28:43 -0700 Subject: [PATCH 318/324] Update readme with compiler info --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c38030f..0902394 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,11 @@ New features include: # Installing on Your Radio There are plenty of tutorials on how to upload sketches to Arduino Nanos. Just search for them. Addtionally, -Ashhar created a video explaining the process specifically for uBiTX6: https://www.youtube.com/watch?v=3n_V3prSJ_E +Ashhar created a video explaining the process specifically for uBiTX v6: https://www.youtube.com/watch?v=3n_V3prSJ_E -I developed this code using the Arduino IDE 1.8.9 toolchain, with -Wall and -Wextra compiler options turned on, so -it should compile on newer or older versions, but may result in slightly different binary output sizes. +I developed this code using the Arduino IDE 1.8.9 toolchain, with -Wall and -Wextra compiler options turned on. +Arduino IDE 1.8.13 was reported to compile too big (see https://groups.io/g/BITX20/topic/75008576), but this +should be resolved in this project's tag R1.5.1. # Personalized Callsign From a4f5f4b3cb501be0a1665380d074d97a193d0a3f Mon Sep 17 00:00:00 2001 From: Reed Nightingale Date: Sat, 18 Jul 2020 20:43:36 -0700 Subject: [PATCH 319/324] Update displayed version --- version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.cpp b/version.cpp index 29022ec..316e0bf 100644 --- a/version.cpp +++ b/version.cpp @@ -1,4 +1,4 @@ #include "version.h" -const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.5.0"; +const char VERSION_STRING_PRIVATE [] PROGMEM = "R1.5.1"; const char* const VERSION_STRING = VERSION_STRING_PRIVATE; \ No newline at end of file From b136f5e43c4b3e1d7b407261f24aa5cdf157ebcd Mon Sep 17 00:00:00 2001 From: reedbn Date: Sun, 13 Dec 2020 11:42:38 -0800 Subject: [PATCH 320/324] Add parentheses to force correct addition operation. Thanks to Barry Halterman for catching this. --- encoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/encoder.cpp b/encoder.cpp index 55ec6e4..4f42f76 100644 --- a/encoder.cpp +++ b/encoder.cpp @@ -16,7 +16,7 @@ static const uint8_t MOMENTUM_MULTIPLIER = 1; uint8_t enc_state (void) { - return (digitalRead(PIN_ENC_A)?1:0 + digitalRead(PIN_ENC_B)?2:0); + return ((digitalRead(PIN_ENC_A)?1:0) + (digitalRead(PIN_ENC_B)?2:0)); } /* From 50381da6deeda7eedcb1310ffef2ebe086c726b5 Mon Sep 17 00:00:00 2001 From: reedbn Date: Sun, 13 Dec 2020 18:19:13 -0800 Subject: [PATCH 321/324] Adjust keyer behavior to always run PTT button as if in KEYER_STRAIGHT mode --- keyer.cpp | 72 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/keyer.cpp b/keyer.cpp index 45e5c22..0a13dca 100644 --- a/keyer.cpp +++ b/keyer.cpp @@ -77,13 +77,8 @@ uint8_t keyerControl = 0; //create by KD8CEC for compatible with new CW Logic char update_PaddleLatch(bool isUpdateKeyState) { unsigned char tmpKeyerControl = 0; - unsigned int paddle = analogRead(PIN_ANALOG_KEYER); - - //use the PTT as the key for tune up, quick QSOs - if (digitalRead(PIN_PTT) == 0) - tmpKeyerControl |= DIT_L; - else if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo) + if (paddle >= cwAdcDashFrom && paddle <= cwAdcDashTo) tmpKeyerControl |= DAH_L; else if (paddle >= cwAdcDotFrom && paddle <= cwAdcDotTo) tmpKeyerControl |= DIT_L; @@ -110,9 +105,41 @@ char update_PaddleLatch(bool isUpdateKeyState) { ******************************************************************************/ void cwKeyer(void){ bool continue_loop = true; - unsigned tmpKeyControl = 0; + char tmpKeyControl = 0; - if(KeyerMode_e::KEYER_STRAIGHT != globalSettings.keyerMode){ + if((KeyerMode_e::KEYER_STRAIGHT == globalSettings.keyerMode) + || (digitalRead(PIN_PTT) == 0)){//use the PTT as the key for tune up, quick QSOs + while(1){ + tmpKeyControl = update_PaddleLatch(0) | (digitalRead(PIN_PTT)?0:DIT_L); + //Serial.println((int)tmpKeyControl); + if ((tmpKeyControl & DIT_L) == DIT_L) { + // if we are here, it is only because the key is pressed + if (!globalSettings.txActive){ + startTx(TuningMode_e::TUNE_CW); + globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; + } + cwKeydown(); + + while ( tmpKeyControl & DIT_L == DIT_L){ + tmpKeyControl = update_PaddleLatch(0) | (digitalRead(PIN_PTT)?0:DIT_L); + //Serial.println((int)tmpKeyControl); + } + + cwKeyUp(); + } + else{ + if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){ + globalSettings.cwExpirationTimeMs = 0; + stopTx(); + } + return;//Tx stop control by Main Loop + } + + checkCAT(); + } //end of while + + } + else{//KEYER_IAMBIC_* while(continue_loop){ switch(keyerState){ case IDLE: @@ -193,34 +220,7 @@ void cwKeyer(void){ checkCAT(); } //end of while - } - else{//KEYER_STRAIGHT - while(1){ - char state = update_PaddleLatch(0); - // Serial.println((int)state); - if (state == DIT_L) { - // if we are here, it is only because the key is pressed - if (!globalSettings.txActive){ - startTx(TuningMode_e::TUNE_CW); - globalSettings.cwExpirationTimeMs = millis() + globalSettings.cwActiveTimeoutMs; - } - cwKeydown(); - - while ( update_PaddleLatch(0) == DIT_L ); - - cwKeyUp(); - } - else{ - if (0 < globalSettings.cwExpirationTimeMs && globalSettings.cwExpirationTimeMs < millis()){ - globalSettings.cwExpirationTimeMs = 0; - stopTx(); - } - return;//Tx stop control by Main Loop - } - - checkCAT(); - } //end of while - }//end of else KEYER_STRAIGHT + }//end of KEYER_IAMBIC_* } From 4eecda170de2c2fa8eb539af3c32c482faa6c474 Mon Sep 17 00:00:00 2001 From: reedbn Date: Sun, 13 Dec 2020 21:34:55 -0800 Subject: [PATCH 322/324] Add size to comment --- settings.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/settings.cpp b/settings.cpp index f496439..7abad2e 100644 --- a/settings.cpp +++ b/settings.cpp @@ -26,8 +26,9 @@ static const uint16_t EEPROM_ADDR_CW_DELAYTIME = 48;//uint16_t static const uint16_t EEPROM_ADDR_VFO_A_MODE = 256;//uint8_t static const uint16_t EEPROM_ADDR_VFO_B_MODE = 257;//uint8_t static const uint16_t EEPROM_ADDR_CW_KEY_TYPE = 358;//uint8_t -static const uint16_t EEPROM_ADDR_QUICKLIST_FREQ = 630;//uint32_t array -static const uint16_t EEPROM_ADDR_QUICKLIST_MODE = 710;//uint8_t array +static const uint16_t EEPROM_ADDR_QUICKLIST_FREQ = 630;//uint32_t array of size NUM_QUICKLIST_SETTINGS +static const uint16_t EEPROM_ADDR_QUICKLIST_MODE = 710;//uint8_t array of size NUM_QUICKLIST_SETTINGS + template bool LoadSane(T& dest,uint16_t addr, T min, T max) From 4918670eaa97e83468328a6ed0716968e327e248 Mon Sep 17 00:00:00 2001 From: reedbn Date: Sun, 13 Dec 2020 21:51:46 -0800 Subject: [PATCH 323/324] Save 12 bytes by adjusting math, inspried by Jack Purdum --- encoder.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/encoder.cpp b/encoder.cpp index 4f42f76..73bdc06 100644 --- a/encoder.cpp +++ b/encoder.cpp @@ -16,7 +16,7 @@ static const uint8_t MOMENTUM_MULTIPLIER = 1; uint8_t enc_state (void) { - return ((digitalRead(PIN_ENC_A)?1:0) + (digitalRead(PIN_ENC_B)?2:0)); + return (digitalRead(PIN_ENC_B) << 1) + (digitalRead(PIN_ENC_A) << 0); } /* From 6c9e759901676664f0d7f6bb8e0d488fb0943b12 Mon Sep 17 00:00:00 2001 From: reedbn Date: Sun, 11 Apr 2021 18:19:42 -0700 Subject: [PATCH 324/324] Add user manual link to readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0902394..33a74b6 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ New features include: * When adjusting settings, the existing/current setting is shown as reference * Cancel touch recalibration +User Manual: https://docs.google.com/document/d/1jlllZbvFMCzO1MJLzlJDGb10HXSehlFNMDPsxGJZtvY/edit?usp=drivesdk + # Installing on Your Radio There are plenty of tutorials on how to upload sketches to Arduino Nanos. Just search for them. Addtionally,