From 7d3a28e1bdbe4dde10f99ce85f420711ccd33621 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 20 May 2021 16:02:29 -0400 Subject: [PATCH 01/37] Update gitignore for Visual Studio / Visual Micro --- .gitignore | 400 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 400 insertions(+) diff --git a/.gitignore b/.gitignore index 5509140..309f296 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,401 @@ *.DS_Store + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Nuget personal access tokens and Credentials +nuget.config + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +.idea/ +*.sln.iml + +# Visual Micro +__vm/ +vs-readme.txt + +# Visual Studio Project Files +*.sln +*.vcxproj +*.vcxproj.filters +*.vcxitems +*.vcxitems.filters From 52b3d69cae179951c54e3edd5560710b1a84a2a8 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 20 May 2021 19:05:12 -0400 Subject: [PATCH 02/37] Refactor ShowMenuOptions as ShowButtonOptions Distinguishing between the current menu items and the buttons to control them --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 28 +++++++++++----------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 5954501..712e681 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1145,7 +1145,7 @@ void ShowMenu() tft.setCursor( 20, tft.height() - 20 ); tft.println("Reflow Master - Code v" + String(ver)); - ShowMenuOptions( true ); + ShowButtonOptions( true ); } void ShowSettings() @@ -1212,7 +1212,7 @@ void ShowSettings() posY += incY; - ShowMenuOptions( true ); + ShowButtonOptions( true ); } void ShowPaste() @@ -1250,10 +1250,10 @@ void ShowPaste() y += 40; } - ShowMenuOptions( true ); + ShowButtonOptions( true ); } -void ShowMenuOptions( bool clearAll ) +void ShowButtonOptions( bool clearAll ) { // int buttonPosY[] = { 19, 74, 129, 184 }; // int buttonHeight = 16; @@ -1611,7 +1611,7 @@ void StartWarmup() state = WARMUP; timeX = 0; - ShowMenuOptions( true ); + ShowButtonOptions( true ); lastWantedTemp = -1; buzzerCount = 5; keepFanOnTime = 0; @@ -1635,7 +1635,7 @@ void StartReflow() tft.fillScreen(BLACK); state = REFLOW; - ShowMenuOptions( true ); + ShowButtonOptions( true ); timeX = 0; SetupGraph(tft, 0, 0, 30, 220, 270, 180, graphRangeMin_X, graphRangeMax_X, graphRangeStep_X, graphRangeMin_Y, graphRangeMax_Y, graphRangeStep_Y, "Reflow Temp", " Time [s]", "deg [C]", DKBLUE, BLUE, WHITE, BLACK ); @@ -1685,7 +1685,7 @@ void EndReflow() DrawHeading( "DONE!", WHITE, BLACK ); - ShowMenuOptions( false ); + ShowButtonOptions( false ); if ( set.useFan && set.fanTimeAfterReflow > 0 ) { @@ -1768,7 +1768,7 @@ void StartOvenCheck() tft.setCursor( 20, 60 ); tft.println( String(CurrentGraph().tempDeg) + "deg"); - ShowMenuOptions( true ); + ShowButtonOptions( true ); } void ShowOvenCheck() @@ -1788,7 +1788,7 @@ void ShowOvenCheck() tft.setTextColor( WHITE, BLACK ); - ShowMenuOptions( true ); + ShowButtonOptions( true ); tft.setTextSize(2); tft.setCursor( 0, 60 ); @@ -1832,7 +1832,7 @@ void ShowResetDefaults() tft.println( "ARE YOU SURE?" ); state = SETTINGS_RESET; - ShowMenuOptions( false ); + ShowButtonOptions( false ); tft.setTextSize(1); tft.setTextColor( GREEN, BLACK ); @@ -2123,8 +2123,8 @@ void button2Press() else if ( state == SETTINGS ) { settings_pointer = constrain( settings_pointer - 1, 0, 8 ); - ShowMenuOptions( false ); - //UpdateSettingsPointer(); + ShowButtonOptions( false ); + UpdateSettingsPointer(); } else if ( state == SETTINGS_PASTE ) { @@ -2161,8 +2161,8 @@ void button3Press() else if ( state == SETTINGS ) { settings_pointer = constrain( settings_pointer + 1, 0, 8 ); - ShowMenuOptions( false ); - //UpdateSettingsPointer(); + ShowButtonOptions( false ); + UpdateSettingsPointer(); } else if ( state == SETTINGS_PASTE ) { From a1c20f065a677b9729b512cfc34f3cd92070dc89 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 20 May 2021 17:08:09 -0400 Subject: [PATCH 03/37] Create linked list settings menu --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 322 +----------------- Code/Reflow_Master_v2/linked_list.h | 74 ++++ Code/Reflow_Master_v2/menu_settings.cpp | 123 +++++++ Code/Reflow_Master_v2/menu_settings.h | 69 ++++ .../menu_settings_options.cpp | 121 +++++++ 5 files changed, 403 insertions(+), 306 deletions(-) create mode 100644 Code/Reflow_Master_v2/linked_list.h create mode 100644 Code/Reflow_Master_v2/menu_settings.cpp create mode 100644 Code/Reflow_Master_v2/menu_settings.h create mode 100644 Code/Reflow_Master_v2/menu_settings_options.cpp diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 712e681..36cc385 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -57,6 +57,8 @@ #include "ReflowMasterProfile.h" #include "FlashStorage.h" +#include "menu_settings.h" + // used to obtain the size of an array of any type #define ELEMENTS(x) (sizeof(x) / sizeof(x[0])) @@ -108,23 +110,6 @@ #define DKPURPLE 0x4010 #define DKGREY 0x4A49 -// Save data struct -typedef struct { - boolean valid = false; - boolean useFan = false; - int fanTimeAfterReflow = 60; - byte paste = 0; - float power = 1; - int lookAhead = 6; - int lookAheadWarm = 1; - int tempOffset = 0; - long bakeTime = 1200; // 20 mins - float bakeTemp = 45; // Degrees C - int bakeTempGap = 3; // Aim for the desired temp minus this value to compensate for overrun - bool startFullBlast = false; - bool beep = true; -} Settings; - // UI and runtime states enum states { BOOT = 0, @@ -1155,62 +1140,7 @@ void ShowSettings() newSettings = false; - int posY = 45; - int incY = 19; - - tft.setTextColor( BLUE, BLACK ); - tft.fillScreen(BLACK); - - tft.setTextColor( BLUE, BLACK ); - tft.setTextSize(2); - tft.setCursor( 20, 20 ); - tft.println( "SETTINGS" ); - - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - tft.print( "SWITCH PASTE" ); - - posY += incY; - - // y 64 - UpdateSettingsFan( posY ); - - posY += incY; - - // y 83 - UpdateSettingsFanTime( posY ); - - posY += incY; - - // y 102 - UpdateSettingsLookAhead( posY ); - - posY += incY; - - // y 121 - UpdateSettingsPower( posY ); - - posY += incY; - - // y 140 - UpdateSettingsTempOffset( posY ); - - posY += incY; - - // y 159 - UpdateSettingsStartFullBlast( posY ); - - posY += incY; - - // y 178 - UpdateSettingsBakeTempGap( posY ); - - posY += incY; - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - tft.print( "RESET TO DEFAULTS" ); - - posY += incY; + SettingsPage::drawItems(); ShowButtonOptions( true ); } @@ -1292,20 +1222,16 @@ void ShowButtonOptions( bool clearAll ) // button 0 tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - switch ( settings_pointer ) - { - case 1: - case 2: - case 3: - case 4: - case 5: - println_Right( tft, "CHANGE", tft.width() - 27, buttonPosY[0] + 9 ); - break; - - default: - println_Right( tft, "SELECT", tft.width() - 27, buttonPosY[0] + 9 ); - break; + SettingsOption* ptr = SettingsOption::getIndex(settings_pointer); + switch (ptr->Mode) + { + case(OptionMode::Select): + println_Right(tft, "SELECT", tft.width() - 27, buttonPosY[0] + 9); + break; + case(OptionMode::Change): + println_Right(tft, "CHANGE", tft.width() - 27, buttonPosY[0] + 9); + break; } // button 1 @@ -1540,60 +1466,7 @@ void UpdateSettingsPointer() { if ( state == SETTINGS ) { - tft.setTextColor( BLUE, BLACK ); - tft.setTextSize(2); - tft.fillRect( 0, 20, 20, tft.height() - 20, BLACK ); - tft.setCursor( 5, ( 45 + ( 19 * settings_pointer ) ) ); - tft.println(">"); - - tft.setTextSize(1); - tft.setTextColor( GREEN, BLACK ); - tft.fillRect( 0, tft.height() - 20, tft.width(), 20, BLACK ); - - int testPosY = tft.height() - 16; - switch ( settings_pointer ) - { - case 0: - println_Center( tft, "Select which profile to reflow", tft.width() / 2, testPosY ); - break; - - case 1: - println_Center( tft, "Enable fan for end of reflow, requires 5V DC fan", tft.width() / 2, testPosY ); - break; - - case 2: - println_Center( tft, "Keep fan on for XXX sec after reflow", tft.width() / 2, testPosY ); - break; - - case 3: - println_Center( tft, "Soak and Reflow look ahead for rate change speed", tft.width() / 2, testPosY ); - break; - - case 4: - println_Center( tft, "Adjust the power boost", tft.width() / 2, testPosY ); - break; - - case 5: - println_Center( tft, "Adjust temp probe reading offset", tft.width() / 2, testPosY ); - break; - - case 6: - println_Center( tft, "Force full power on initial ramp-up - be careful!", tft.width() / 2, testPosY ); - break; - - case 7: - println_Center( tft, "Bake thermal mass adjustment, higher for more mass", tft.width() / 2, testPosY ); - break; - - case 8: - println_Center( tft, "Reset to default settings", tft.width() / 2, testPosY ); - break; - - default: - //println_Center( tft, "", tft.width() / 2, tft.height() - 20 ); - break; - } - tft.setTextSize(2); + SettingsPage::drawCursor(settings_pointer); } else if ( state == SETTINGS_PASTE ) { @@ -1840,109 +1713,6 @@ void ShowResetDefaults() println_Center( tft, "Settings restore cannot be undone!", tft.width() / 2, tft.height() - 20 ); } -void UpdateSettingsFan( int posY ) -{ - tft.fillRect( 15, posY - 5, 200, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - - tft.setTextColor( WHITE, BLACK ); - tft.print( "USE FAN " ); - tft.setTextColor( YELLOW, BLACK ); - - if ( set.useFan ) - { - tft.println( "ON" ); - } - else - { - tft.println( "OFF" ); - } - tft.setTextColor( WHITE, BLACK ); -} - -void UpdateSettingsFanTime( int posY ) -{ - tft.fillRect( 15, posY - 5, 230, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - - tft.setTextColor( WHITE, BLACK ); - tft.print( "FAN COUNTDOWN " ); - tft.setTextColor( YELLOW, BLACK ); - - tft.println( String( set.fanTimeAfterReflow ) + "s"); - - tft.setTextColor( WHITE, BLACK ); -} - -void UpdateSettingsStartFullBlast( int posY ) -{ - tft.fillRect( 15, posY - 5, 240, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - tft.setCursor( 20, posY ); - tft.print( "START RAMP 100% " ); - tft.setTextColor( YELLOW, BLACK ); - - if ( set.startFullBlast ) - { - tft.println( "ON" ); - } - else - { - tft.println( "OFF" ); - } - tft.setTextColor( WHITE, BLACK ); -} - -void UpdateSettingsPower( int posY ) -{ - tft.fillRect( 15, posY - 5, 240, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - - tft.setCursor( 20, posY ); - tft.print( "POWER "); - tft.setTextColor( YELLOW, BLACK ); - tft.println( String( round((set.power * 100))) + "%"); - tft.setTextColor( WHITE, BLACK ); -} - -void UpdateSettingsLookAhead( int posY ) -{ - tft.fillRect( 15, posY - 5, 260, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - - tft.setCursor( 20, posY ); - tft.print( "GRAPH LOOK AHEAD "); - tft.setTextColor( YELLOW, BLACK ); - tft.println( String( set.lookAhead) ); - tft.setTextColor( WHITE, BLACK ); -} - -void UpdateSettingsBakeTempGap( int posY ) -{ - tft.fillRect( 15, posY - 5, 260, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - - tft.setCursor( 20, posY ); - tft.print( "BAKE TEMP GAP "); - tft.setTextColor( YELLOW, BLACK ); - tft.println( String( set.bakeTempGap ) ); - tft.setTextColor( WHITE, BLACK ); -} - -void UpdateSettingsTempOffset( int posY ) -{ - tft.fillRect( 15, posY - 5, 220, 20, BLACK ); - tft.setTextColor( WHITE, BLACK ); - - tft.setCursor( 20, posY ); - tft.print( "TEMP OFFSET "); - tft.setTextColor( YELLOW, BLACK ); - tft.println( String( set.tempOffset) ); - tft.setTextColor( WHITE, BLACK ); -} - /* Button press code here */ @@ -1980,67 +1750,7 @@ void button0Press() } else if ( state == SETTINGS ) { - if ( settings_pointer == 0 ) // change paste - { - settings_pointer = set.paste; - ShowPaste(); - } - else if ( settings_pointer == 1 ) // switch fan use - { - set.useFan = !set.useFan; - - UpdateSettingsFan( 64 ); - } - else if ( settings_pointer == 2 ) // fan countdown after reflow - { - set.fanTimeAfterReflow += 5; - if ( set.fanTimeAfterReflow > 60 ) - set.fanTimeAfterReflow = 0; - - UpdateSettingsFanTime( 83 ); - } - else if ( settings_pointer == 3 ) // change lookahead for reflow - { - set.lookAhead += 1; - if ( set.lookAhead > 15 ) - set.lookAhead = 1; - - UpdateSettingsLookAhead( 102 ); - } - else if ( settings_pointer == 4 ) // change power - { - set.power += 0.1; - if ( set.power > 1.55 ) - set.power = 0.5; - - UpdateSettingsPower( 121 ); - } - else if ( settings_pointer == 5 ) // change temp probe offset - { - set.tempOffset += 1; - if ( set.tempOffset > 15 ) - set.tempOffset = -15; - - UpdateSettingsTempOffset( 140 ); - } - else if ( settings_pointer == 6 ) // change use full power on initial ramp - { - set.startFullBlast = !set.startFullBlast; - - UpdateSettingsStartFullBlast( 159 ); - } - else if ( settings_pointer == 7 ) // bake temp gap - { - set.bakeTempGap += 1; - if ( set.bakeTempGap > 5 ) - set.bakeTempGap = 0; - - UpdateSettingsBakeTempGap( 178 ); - } - else if ( settings_pointer == 8 ) // reset defaults - { - ShowResetDefaults(); - } + SettingsPage::changeOption(settings_pointer); } else if ( state == SETTINGS_PASTE ) { @@ -2122,7 +1832,7 @@ void button2Press() } else if ( state == SETTINGS ) { - settings_pointer = constrain( settings_pointer - 1, 0, 8 ); + settings_pointer = constrain( settings_pointer - 1, 0, (int) SettingsOption::getCount() - 1 ); ShowButtonOptions( false ); UpdateSettingsPointer(); } @@ -2160,7 +1870,7 @@ void button3Press() } else if ( state == SETTINGS ) { - settings_pointer = constrain( settings_pointer + 1, 0, 8 ); + settings_pointer = constrain( settings_pointer + 1, 0, (int) SettingsOption::getCount() - 1); ShowButtonOptions( false ); UpdateSettingsPointer(); } diff --git a/Code/Reflow_Master_v2/linked_list.h b/Code/Reflow_Master_v2/linked_list.h new file mode 100644 index 0000000..cad5640 --- /dev/null +++ b/Code/Reflow_Master_v2/linked_list.h @@ -0,0 +1,74 @@ +template +class LinkedList { +private: + static T* head; + T* next = nullptr; + +public: + static T* getHead() { return head; } + T* getNext() { return next; } + + static size_t getCount() { + size_t count = 0; + T* ptr = head; + while (ptr != nullptr) { + ptr = ptr->next; + count++; + } + return count; + } + + static T* getIndex(unsigned int i) { + T* ptr = head; + while (ptr != nullptr && i != 0) { + ptr = ptr->getNext(); + i--; + } + if (i != 0) return nullptr; + return ptr; + } + + static int getPositionOf(T* node) { + unsigned int position = 0; + T* ptr = head; + while (ptr != nullptr) { + if (node == ptr) return position; + position++; + ptr = ptr->getNext(); + } + return -1; // not found + } + +protected: + static void add(T* node) { + if (head == nullptr) { + head = node; + } + else { + T* last = head; + while (true) { + if (last->next == nullptr) break; // found last entry + last = last->next; + } + last->next = node; + } + } + + static void remove(T* node) { + if (node == head) { + head = node->next; // Set head to next, and we're done + return; + } + + // Otherwise we're somewhere else in the list. Iterate through to find it. + T* ptr = head; + + while (ptr != nullptr) { + if (ptr->next == node) { // FOUND! + ptr->next = node->next; // Set the previous "next" as this entry's "next" (skip this object) + break; // Stop searching + } + ptr = ptr->next; // Not found. Next entry... + } + } +}; diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp new file mode 100644 index 0000000..6cd6381 --- /dev/null +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -0,0 +1,123 @@ +#include "menu_settings.h" + +// Just a bunch of re-defined colours +#define BLUE 0x001F +#define TEAL 0x0438 +#define GREEN 0x07E0 +#define CYAN 0x07FF +#define RED 0xF800 +#define MAGENTA 0xF81F +#define YELLOW 0xFFE0 +#define ORANGE 0xFC00 +#define PINK 0xF81F +#define PURPLE 0x8010 +#define GREY 0xC618 +#define WHITE 0xFFFF +#define BLACK 0x0000 +#define DKBLUE 0x000D +#define DKTEAL 0x020C +#define DKGREEN 0x03E0 +#define DKCYAN 0x03EF +#define DKRED 0x6000 +#define DKMAGENTA 0x8008 +#define DKYELLOW 0x8400 +#define DKORANGE 0x8200 +#define DKPINK 0x9009 +#define DKPURPLE 0x4010 +#define DKGREY 0x4A49 + + +template<> +SettingsOption* LinkedList::head = nullptr; + +SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, bool refresh, OptionMode m) + : + ItemName(name), ItemDescription(desc), + getFunction(get), setFunction(set), + RefreshOnChange(refresh), + Mode(m) +{ + LinkedList::add(this); +} + +SettingsOption::~SettingsOption() +{ + LinkedList::remove(this); +} + +unsigned long SettingsOption::getYPosition(unsigned int index) { + return (ItemHeight * index) + ItemStartY; // y coordinate on center +} + +void SettingsOption::drawItem(unsigned int position) { + const unsigned int yPos = getYPosition(position); + tft.fillRect(15, yPos - 5, 240, ItemHeight, BLACK); + tft.setCursor(20, yPos); + + tft.setTextSize(2); + tft.setTextColor(WHITE, BLACK); + tft.print(ItemName); + tft.print(' '); + + tft.setTextColor(YELLOW, BLACK); + tft.print(getFunction()); +} + +void SettingsOption::drawDescription() { + const unsigned int height_area = 20; + const unsigned int height_text = 16; + + tft.setTextSize(1); + tft.setTextColor(GREEN, BLACK); + tft.fillRect(0, tft.height() - height_area, tft.width(), height_area, BLACK); + + int textPosY = tft.height() - height_text; + println_Center(tft, this->ItemDescription, tft.width() / 2, textPosY); +} + + +void SettingsPage::drawItems() { + SettingsOption* ptr = SettingsOption::getHead(); + size_t position = 0; + + tft.fillScreen(BLACK); + + tft.setTextColor(BLUE, BLACK); + tft.setTextSize(2); + tft.setCursor(20, 20); + tft.println("SETTINGS"); + + tft.setTextColor(WHITE, BLACK); + + while (ptr != nullptr) { + ptr->drawItem(position); + position++; + ptr = ptr->getNext(); + } +} + +void SettingsPage::drawCursor(unsigned int pos) { + SettingsOption* ptr = SettingsOption::getIndex(pos); + if (ptr == nullptr) return; // out of range + + tft.setTextColor(BLUE, BLACK); + tft.setTextSize(2); + tft.fillRect(0, 20, 20, tft.height() - 20, BLACK); + tft.setCursor(5, SettingsOption::getYPosition(pos)); + tft.println(">"); + + ptr->drawDescription(); +} + +void SettingsPage::changeOption(unsigned int pos) { + SettingsOption* ptr = SettingsOption::getIndex(pos); + if (ptr == nullptr) return; + + ptr->setFunction(); + + if (ptr->RefreshOnChange == true) { + ptr->drawItem(SettingsOption::getPositionOf(ptr)); + } +} + + diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h new file mode 100644 index 0000000..1d1347a --- /dev/null +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -0,0 +1,69 @@ +#include +#include // for TFT drawing + +#include "linked_list.h" + +// Save data struct +typedef struct { + boolean valid = false; + boolean useFan = false; + int fanTimeAfterReflow = 60; + byte paste = 0; + float power = 1; + int lookAhead = 6; + int lookAheadWarm = 1; + int tempOffset = 0; + long bakeTime = 1200; // 20 mins + float bakeTemp = 45; // Degrees C + int bakeTempGap = 3; // Aim for the desired temp minus this value to compensate for overrun + bool startFullBlast = false; + bool beep = true; +} Settings; + + +enum class OptionMode { + Select, + Change, +}; + +class SettingsOption : public LinkedList { +public: + friend LinkedList; + + typedef String(*MenuGetFunc)(); + typedef void (*MenuSetFunc)(); + + const String ItemName; + const String ItemDescription; + + const MenuGetFunc getFunction; + const MenuSetFunc setFunction; + + const bool RefreshOnChange; + const OptionMode Mode; + + SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, bool refresh, OptionMode m); + ~SettingsOption(); + + static unsigned long getYPosition(unsigned int index); + + void drawItem(unsigned int posY); + void drawDescription(); + +private: + static const unsigned int ItemHeight = 19; + static const unsigned int ItemStartY = 45; +}; + +class SettingsPage { +public: + static void drawItems(); + static void drawCursor(unsigned int pos); + static void changeOption(unsigned int pos); +}; + + +extern Settings set; +extern Adafruit_ILI9341 tft; + +void println_Center(Adafruit_ILI9341& d, String heading, int centerX, int centerY); diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp new file mode 100644 index 0000000..aa14c0a --- /dev/null +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -0,0 +1,121 @@ +#include "menu_settings.h" + +void ShowPaste(); +void ShowResetDefaults(); + +// "Switch Paste" menu option +String getSwitchPaste() { + return ""; +} + +void changeSwitchPaste() { + ShowPaste(); +} + +SettingsOption OptionPasteMenu("SWITCH PASTE", "Select which profile to reflow", getSwitchPaste, changeSwitchPaste, false, OptionMode::Select); + + +// "Use Fan" menu option +String getUseFan() { + return set.useFan ? "ON" : "OFF"; +} + +void changeUseFan() { + set.useFan = !set.useFan; +} + +SettingsOption OptionUseFan("USE FAN", "Enable fan for end of reflow, requires 5V DC fan", getUseFan, changeUseFan, true, OptionMode::Change); + + +// "Fan Countdown" menu option +String getFanCountdown() { + return String(set.fanTimeAfterReflow) + "s"; +} + +void changeFanCountdown() { + set.fanTimeAfterReflow += 5; + if (set.fanTimeAfterReflow > 60) + set.fanTimeAfterReflow = 0; +} + +SettingsOption OptionFanCountdown("FAN COUNTDOWN", "Keep fan on for XXX sec after reflow", getFanCountdown, changeFanCountdown, true, OptionMode::Change); + + +// "Graph Look Ahead" menu option +String getGraphLookAhead() { + return String(set.lookAhead); +} + +void changeGraphLookAhead() { + set.lookAhead += 1; + if (set.lookAhead > 15) + set.lookAhead = 1; +} + +SettingsOption OptionGraphLookAhead("GRAPH LOOK AHEAD", "Soak and Reflow look ahead for rate change speed", getGraphLookAhead, changeGraphLookAhead, true, OptionMode::Change); + + +// "Power" menu option +String getPower() { + return String(round((set.power * 100))) + "%"; +} + +void changePower() { + set.power += 0.1; + if (set.power > 1.55) + set.power = 0.5; +} + +SettingsOption OptionPower("POWER", "Adjust the power boost", getPower, changePower, true, OptionMode::Change); + + +// "Temp Offset" menu option +String getTempOffset() { + return String(set.tempOffset); +} + +void changeTempOffset() { + set.tempOffset += 1; + if (set.tempOffset > 15) + set.tempOffset = -15; +} + +SettingsOption OptionTempOffset("TEMP OFFSET", "Adjust temp probe reading offset", getTempOffset, changeTempOffset, true, OptionMode::Change); + + +// "Start Ramp 100%" menu option +String getStartFullBlast() { + return set.startFullBlast ? "ON" : "OFF"; +} + +void changeStartFullBlast() { + set.startFullBlast = !set.startFullBlast; +} + +SettingsOption OptionStartFullBlast("START RAMP 100%", "Force full power on initial ramp-up - be careful!", getStartFullBlast, changeStartFullBlast, true, OptionMode::Change); + + +// "Bake Temp Gap" menu option +String getBakeTempGap() { + return String(set.bakeTempGap); +} + +void changeBakeTempGap() { + set.bakeTempGap += 1; + if (set.bakeTempGap > 5) + set.bakeTempGap = 0; +} + +SettingsOption OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, higher for more mass", getBakeTempGap, changeBakeTempGap, true, OptionMode::Change); + + +// "Reset to defaults" menu option +String getResetToDefaults() { + return ""; +} + +void goToResetDefaults() { + ShowResetDefaults(); +} + +SettingsOption OptionResetToDefaults("RESET TO DEFAULTS", "Reset to default settings", getResetToDefaults, goToResetDefaults, false, OptionMode::Select); From 4bb2d5c71f9077bce64b78fa326466bf2cd50e69 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 20 May 2021 20:50:48 -0400 Subject: [PATCH 04/37] Add scrolling feature to settings menu Now supports an "infinite" (2^16) number of menu items! --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 2 +- Code/Reflow_Master_v2/menu_settings.cpp | 47 +++++++++++++++++----- Code/Reflow_Master_v2/menu_settings.h | 10 ++++- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 36cc385..b0f2638 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1140,7 +1140,7 @@ void ShowSettings() newSettings = false; - SettingsPage::drawItems(); + SettingsPage::drawPage(); ShowButtonOptions( true ); } diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 6cd6381..669abeb 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -30,6 +30,9 @@ template<> SettingsOption* LinkedList::head = nullptr; +unsigned int SettingsPage::startingItem = 0; + + SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, bool refresh, OptionMode m) : ItemName(name), ItemDescription(desc), @@ -76,9 +79,8 @@ void SettingsOption::drawDescription() { } -void SettingsPage::drawItems() { - SettingsOption* ptr = SettingsOption::getHead(); - size_t position = 0; +void SettingsPage::drawPage() { + startingItem = 0; // reset scrolling for initial draw tft.fillScreen(BLACK); @@ -87,12 +89,28 @@ void SettingsPage::drawItems() { tft.setCursor(20, 20); tft.println("SETTINGS"); - tft.setTextColor(WHITE, BLACK); + drawItems(); +} + +void SettingsPage::redraw() { + // drawing over *only* the items, rather than the entire page (title, cursor, button prompts) + tft.fillRect(15, SettingsOption::getYPosition(0) - 5, 240, SettingsOption::getYPosition(ItemsPerPage), BLACK); + + drawItems(); +} + +void SettingsPage::drawItems() { + SettingsOption* ptr = SettingsOption::getHead(); + size_t position = 0; while (ptr != nullptr) { - ptr->drawItem(position); + if (position >= startingItem) { + ptr->drawItem(position - startingItem); + } position++; ptr = ptr->getNext(); + + if (position > startingItem + SettingsPage::ItemsPerPage) break; // break when we've filled the page } } @@ -100,10 +118,23 @@ void SettingsPage::drawCursor(unsigned int pos) { SettingsOption* ptr = SettingsOption::getIndex(pos); if (ptr == nullptr) return; // out of range + // Find if we're offscreen and adjust items accordingly + if (pos < startingItem) { + startingItem--; + redraw(); + } + else if (pos > startingItem + ItemsPerPage) { + startingItem++; + redraw(); + } + + const unsigned int selectedPos = pos - startingItem; + + // Draw the actual cursor tft.setTextColor(BLUE, BLACK); tft.setTextSize(2); tft.fillRect(0, 20, 20, tft.height() - 20, BLACK); - tft.setCursor(5, SettingsOption::getYPosition(pos)); + tft.setCursor(5, SettingsOption::getYPosition(selectedPos)); tft.println(">"); ptr->drawDescription(); @@ -116,8 +147,6 @@ void SettingsPage::changeOption(unsigned int pos) { ptr->setFunction(); if (ptr->RefreshOnChange == true) { - ptr->drawItem(SettingsOption::getPositionOf(ptr)); + ptr->drawItem(SettingsOption::getPositionOf(ptr) - startingItem); } } - - diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 1d1347a..9c9446c 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -57,9 +57,17 @@ class SettingsOption : public LinkedList { class SettingsPage { public: - static void drawItems(); + static void drawPage(); + static void redraw(); + static void drawCursor(unsigned int pos); static void changeOption(unsigned int pos); + +private: + static const unsigned int ItemsPerPage = 8; // should be calculated given font size and screen space, but good enough for testing + static unsigned int startingItem; + + static void drawItems(); }; From d0b918d91d03a2d110e0b84ef5497d8a2646ced1 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 20 May 2021 22:03:45 -0400 Subject: [PATCH 05/37] Add scroll position indicator to settings menu --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 2 ++ Code/Reflow_Master_v2/menu_settings.cpp | 23 ++++++++++++++++++++++ Code/Reflow_Master_v2/menu_settings.h | 5 +++++ 3 files changed, 30 insertions(+) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index b0f2638..96630d4 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1143,6 +1143,8 @@ void ShowSettings() SettingsPage::drawPage(); ShowButtonOptions( true ); + + SettingsPage::drawScrollIndicator(); // needs to be redrawn on top of buttons } void ShowPaste() diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 669abeb..524b758 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -90,6 +90,7 @@ void SettingsPage::drawPage() { tft.println("SETTINGS"); drawItems(); + // drawScrollIndicator(); // skipping this because it's drawn over by the button icons anyways } void SettingsPage::redraw() { @@ -97,6 +98,7 @@ void SettingsPage::redraw() { tft.fillRect(15, SettingsOption::getYPosition(0) - 5, 240, SettingsOption::getYPosition(ItemsPerPage), BLACK); drawItems(); + drawScrollIndicator(); } void SettingsPage::drawItems() { @@ -150,3 +152,24 @@ void SettingsPage::changeOption(unsigned int pos) { ptr->drawItem(SettingsOption::getPositionOf(ptr) - startingItem); } } + +void SettingsPage::drawScrollIndicator() { + if (SettingsOption::getCount() <= ItemsPerPage) return; // no scrolling = no scroll indicator + + const unsigned int Width = 15; + const unsigned int Height = 3; + const unsigned int MarginY = 2; + + const unsigned int XPos = tft.width() - (Width*2); + const unsigned int YMin = buttonPosY[2] + buttonHeight + MarginY; // inside edge + const unsigned int YMax = buttonPosY[3] - MarginY; // outside edge + //const unsigned int MaxYSpace = YMax - YMin; + + const unsigned int NumPositions = (SettingsOption::getCount() - 1) - ItemsPerPage; // -1 for zero index + + const unsigned int yPos = map(startingItem, 0, NumPositions, YMin, YMax); + + tft.fillRect(XPos, YMin, Width, YMax - YMin + Height, BLACK); // clear area + tft.fillRect(XPos + Width / 2, YMin, 1, YMax - YMin + Height, WHITE); // draw center line + tft.fillRect(XPos, yPos, Width, Height, BLUE); // draw indicator +} diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 9c9446c..0618cc0 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -61,6 +61,8 @@ class SettingsPage { static void redraw(); static void drawCursor(unsigned int pos); + static void drawScrollIndicator(); + static void changeOption(unsigned int pos); private: @@ -74,4 +76,7 @@ class SettingsPage { extern Settings set; extern Adafruit_ILI9341 tft; +extern int buttonPosY[]; +extern int buttonHeight; + void println_Center(Adafruit_ILI9341& d, String heading, int centerX, int centerY); From 3a304085f756fbf1492760173ab99acbbe225e7d Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 18:07:11 -0400 Subject: [PATCH 06/37] Fix indexing error for settings menu pagination 9 items per page, not 8. Caused by indexing 'items per' at 1 and the items themselves at 0. --- Code/Reflow_Master_v2/menu_settings.cpp | 4 ++-- Code/Reflow_Master_v2/menu_settings.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 524b758..5780800 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -112,7 +112,7 @@ void SettingsPage::drawItems() { position++; ptr = ptr->getNext(); - if (position > startingItem + SettingsPage::ItemsPerPage) break; // break when we've filled the page + if (position > startingItem + SettingsPage::ItemsPerPage - 1) break; // break when we've filled the page (-1 for zero index) } } @@ -125,8 +125,8 @@ void SettingsPage::drawCursor(unsigned int pos) { startingItem--; redraw(); } - else if (pos > startingItem + ItemsPerPage) { startingItem++; + else if (pos > startingItem + ItemsPerPage - 1) { // -1 for zero index redraw(); } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 0618cc0..1bf7860 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -66,7 +66,7 @@ class SettingsPage { static void changeOption(unsigned int pos); private: - static const unsigned int ItemsPerPage = 8; // should be calculated given font size and screen space, but good enough for testing + static const unsigned int ItemsPerPage = 9; // should be calculated given font size and screen space, but good enough for testing static unsigned int startingItem; static void drawItems(); From 360313b115b733aed03aeb674d90bfaf06832e5e Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 18:32:11 -0400 Subject: [PATCH 07/37] Create paged scroll mode for menu settings Not quite as pretty as filling the whole screen with options no matter where you are, but more efficient to redraw it once rather than every time the user pushes down. --- Code/Reflow_Master_v2/linked_list.h | 1 + Code/Reflow_Master_v2/menu_settings.cpp | 72 +++++++++++++++++++------ Code/Reflow_Master_v2/menu_settings.h | 8 +++ 3 files changed, 65 insertions(+), 16 deletions(-) diff --git a/Code/Reflow_Master_v2/linked_list.h b/Code/Reflow_Master_v2/linked_list.h index cad5640..6a737ab 100644 --- a/Code/Reflow_Master_v2/linked_list.h +++ b/Code/Reflow_Master_v2/linked_list.h @@ -8,6 +8,7 @@ class LinkedList { static T* getHead() { return head; } T* getNext() { return next; } + // indexed at 1 static size_t getCount() { size_t count = 0; T* ptr = head; diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 5780800..99d7787 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -120,13 +120,16 @@ void SettingsPage::drawCursor(unsigned int pos) { SettingsOption* ptr = SettingsOption::getIndex(pos); if (ptr == nullptr) return; // out of range + // Clear cursor + tft.fillRect(0, 20, 20, tft.height() - 20, BLACK); + // Find if we're offscreen and adjust items accordingly if (pos < startingItem) { - startingItem--; + updateScroll(-1); // decrement redraw(); } - startingItem++; else if (pos > startingItem + ItemsPerPage - 1) { // -1 for zero index + updateScroll(1); // increment redraw(); } @@ -135,7 +138,6 @@ void SettingsPage::drawCursor(unsigned int pos) { // Draw the actual cursor tft.setTextColor(BLUE, BLACK); tft.setTextSize(2); - tft.fillRect(0, 20, 20, tft.height() - 20, BLACK); tft.setCursor(5, SettingsOption::getYPosition(selectedPos)); tft.println(">"); @@ -153,23 +155,61 @@ void SettingsPage::changeOption(unsigned int pos) { } } +void SettingsPage::updateScroll(int dir) { + switch (Scroll) { + case(ScrollType::Smooth): + startingItem += dir; + break; + case(ScrollType::Paged): + startingItem += dir * ItemsPerPage; + break; + } +} + void SettingsPage::drawScrollIndicator() { if (SettingsOption::getCount() <= ItemsPerPage) return; // no scrolling = no scroll indicator - const unsigned int Width = 15; - const unsigned int Height = 3; - const unsigned int MarginY = 2; - - const unsigned int XPos = tft.width() - (Width*2); - const unsigned int YMin = buttonPosY[2] + buttonHeight + MarginY; // inside edge - const unsigned int YMax = buttonPosY[3] - MarginY; // outside edge - //const unsigned int MaxYSpace = YMax - YMin; + switch (Scroll) { + case(ScrollType::Smooth): + { + const unsigned int Width = 15; + const unsigned int Height = 3; + const unsigned int MarginY = 2; + + const unsigned int XPos = tft.width() - (Width * 2); + const unsigned int YMin = buttonPosY[2] + buttonHeight + MarginY; // inside edge + const unsigned int YMax = buttonPosY[3] - MarginY; // outside edge + + const unsigned int NumPositions = (SettingsOption::getCount() - 1) - ItemsPerPage; // -1 for zero index - const unsigned int NumPositions = (SettingsOption::getCount() - 1) - ItemsPerPage; // -1 for zero index + const unsigned int yPos = map(startingItem, 0, NumPositions, YMin, YMax); - const unsigned int yPos = map(startingItem, 0, NumPositions, YMin, YMax); + tft.fillRect(XPos, YMin, Width, YMax - YMin + Height, BLACK); // clear area + tft.fillRect(XPos + Width / 2, YMin, 1, YMax - YMin + Height, WHITE); // draw center line + tft.fillRect(XPos, yPos, Width, Height, BLUE); // draw indicator - tft.fillRect(XPos, YMin, Width, YMax - YMin + Height, BLACK); // clear area - tft.fillRect(XPos + Width / 2, YMin, 1, YMax - YMin + Height, WHITE); // draw center line - tft.fillRect(XPos, yPos, Width, Height, BLUE); // draw indicator + break; + } + case(ScrollType::Paged): + { + const unsigned int TextWidth = 31; + const unsigned int TextHeight = 8; // with text size '1' + const unsigned int XPos = tft.width() - TextWidth; + const unsigned int YPos = (buttonPosY[2] + buttonPosY[3]) / 2 + (TextHeight / 2); + + const unsigned int Page = (startingItem / ItemsPerPage) + 1; + const unsigned int NumItems = SettingsOption::getCount(); + const unsigned int NumPages = (NumItems / ItemsPerPage) + ((NumItems % ItemsPerPage != 0) ? 1 : 0); + + tft.fillRect(XPos, YPos, TextWidth, TextHeight, BLACK); // clear area + + tft.setTextColor(WHITE, BLACK); + tft.setTextSize(1); + tft.setCursor(XPos, YPos); + + tft.print(Page); + tft.print('/'); + tft.print(NumPages); + } + } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 1bf7860..efa22e6 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -70,6 +70,14 @@ class SettingsPage { static unsigned int startingItem; static void drawItems(); + + enum class ScrollType { + Smooth, // at the end of current page, moves all items up by one + Paged, // at the end of the current page, draws an entire new page of items + }; + static const ScrollType Scroll = ScrollType::Paged; + + static void updateScroll(int dir); }; From 3b42b336734a98e91d81e4f19df838aa23b112f7 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 18:50:57 -0400 Subject: [PATCH 08/37] Move scroll and page indicators to main file Because these work around the buttons and are not specific to the settings page, I'm moving them to the main file so they can (potentially) be called by other menu modes. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 40 ++++++++++++++++++++++ Code/Reflow_Master_v2/menu_settings.cpp | 37 ++++---------------- Code/Reflow_Master_v2/menu_settings.h | 4 +-- 3 files changed, 48 insertions(+), 33 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 96630d4..3383f71 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1306,6 +1306,46 @@ void ShowButtonOptions( bool clearAll ) } } +void ShowScrollIndicator(float pct, uint32_t color) +{ + if (pct < 0.0) pct = 0.0; + else if (pct > 1.0) pct = 1.0; + + const unsigned int Width = 15; // all values in pixels + const unsigned int Height = 3; + const unsigned int MarginY = 2; + + const unsigned int XPos = tft.width() - (Width * 2); + const unsigned int YMin = buttonPosY[2] + buttonHeight + MarginY; // inside edge + const unsigned int YMax = buttonPosY[3] - MarginY; // outside edge + + const unsigned int YRange = YMax - YMin; // total range + number of options + + const unsigned int yPos = (pct * (float) YRange) + YMin; // position of indicator + + tft.fillRect(XPos, YMin, Width, YMax - YMin + Height, BLACK); // clear area + tft.fillRect(XPos + Width / 2, YMin, 1, YMax - YMin + Height, WHITE); // draw center line + tft.fillRect(XPos, yPos, Width, Height, color); // draw indicator +} + +void ShowPageIndicator(unsigned int page, unsigned int numPages, uint32_t color) +{ + const unsigned int TextWidth = 31; // total width from right edge, ballpark + const unsigned int TextHeight = 8; // with text size '1' + const unsigned int XPos = tft.width() - TextWidth; // left edge + const unsigned int YPos = (buttonPosY[2] + buttonPosY[3]) / 2 + (TextHeight / 2); + + tft.fillRect(XPos, YPos, TextWidth, TextHeight, BLACK); // clear area + + tft.setTextColor(color, BLACK); + tft.setTextSize(1); + tft.setCursor(XPos, YPos); + + tft.print(page); + tft.print('/'); + tft.print(numPages); +} + void UpdateBakeMenu() { tft.setTextColor( YELLOW, BLACK ); diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 99d7787..acf9790 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -172,44 +172,19 @@ void SettingsPage::drawScrollIndicator() { switch (Scroll) { case(ScrollType::Smooth): { - const unsigned int Width = 15; - const unsigned int Height = 3; - const unsigned int MarginY = 2; - - const unsigned int XPos = tft.width() - (Width * 2); - const unsigned int YMin = buttonPosY[2] + buttonHeight + MarginY; // inside edge - const unsigned int YMax = buttonPosY[3] - MarginY; // outside edge - - const unsigned int NumPositions = (SettingsOption::getCount() - 1) - ItemsPerPage; // -1 for zero index - - const unsigned int yPos = map(startingItem, 0, NumPositions, YMin, YMax); - - tft.fillRect(XPos, YMin, Width, YMax - YMin + Height, BLACK); // clear area - tft.fillRect(XPos + Width / 2, YMin, 1, YMax - YMin + Height, WHITE); // draw center line - tft.fillRect(XPos, yPos, Width, Height, BLUE); // draw indicator - + const unsigned int NumPositions = SettingsOption::getCount() - ItemsPerPage; + const float value = (float) startingItem / (float) NumPositions; + + ShowScrollIndicator(value, BLUE); break; } case(ScrollType::Paged): { - const unsigned int TextWidth = 31; - const unsigned int TextHeight = 8; // with text size '1' - const unsigned int XPos = tft.width() - TextWidth; - const unsigned int YPos = (buttonPosY[2] + buttonPosY[3]) / 2 + (TextHeight / 2); - const unsigned int Page = (startingItem / ItemsPerPage) + 1; const unsigned int NumItems = SettingsOption::getCount(); const unsigned int NumPages = (NumItems / ItemsPerPage) + ((NumItems % ItemsPerPage != 0) ? 1 : 0); - - tft.fillRect(XPos, YPos, TextWidth, TextHeight, BLACK); // clear area - - tft.setTextColor(WHITE, BLACK); - tft.setTextSize(1); - tft.setCursor(XPos, YPos); - - tft.print(Page); - tft.print('/'); - tft.print(NumPages); + ShowPageIndicator(Page, NumPages, WHITE); + break; } } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index efa22e6..3588551 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -84,7 +84,7 @@ class SettingsPage { extern Settings set; extern Adafruit_ILI9341 tft; -extern int buttonPosY[]; -extern int buttonHeight; +void ShowScrollIndicator(float, uint32_t); +void ShowPageIndicator(unsigned int, unsigned int, uint32_t); void println_Center(Adafruit_ILI9341& d, String heading, int centerX, int centerY); From d7208cdf9aaac7d3ea399e8e23fef144e00ff1a2 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:01:56 -0400 Subject: [PATCH 09/37] Fix minor settings menu redraw issues Don't do a 'clear all' on the buttons to avoid clipping long menu items at the end of the list, and clear the description box on redraw for description text longer than the 'standard' items area. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 2 +- Code/Reflow_Master_v2/menu_settings.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 3383f71..0bb816a 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1142,7 +1142,7 @@ void ShowSettings() SettingsPage::drawPage(); - ShowButtonOptions( true ); + ShowButtonOptions( false ); SettingsPage::drawScrollIndicator(); // needs to be redrawn on top of buttons } diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index acf9790..3976111 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -96,6 +96,9 @@ void SettingsPage::drawPage() { void SettingsPage::redraw() { // drawing over *only* the items, rather than the entire page (title, cursor, button prompts) tft.fillRect(15, SettingsOption::getYPosition(0) - 5, 240, SettingsOption::getYPosition(ItemsPerPage), BLACK); + + // clear the description box as well + tft.fillRect(0, tft.height() - 20, tft.width(), 20, BLACK); drawItems(); drawScrollIndicator(); From 8b88ade109312ca2e08ebe00fce7740b5d6427da Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:02:47 -0400 Subject: [PATCH 10/37] Add menu option to disable the buzzer STOP. FREAKING. BEEPING. --- Code/Reflow_Master_v2/menu_settings_options.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index aa14c0a..1aa1a50 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -109,6 +109,20 @@ void changeBakeTempGap() { SettingsOption OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, higher for more mass", getBakeTempGap, changeBakeTempGap, true, OptionMode::Change); +// "Disable Buzzer" menu option +String getBeepSetting() { + return set.beep ? "OFF" : "ON"; // inverted, as the setting is to 'disable' +} + +void setBeepSetting() { + set.beep = !set.beep; +} + +SettingsOption OptionBeep("DISABLE BUZZER", "Disable the buzzer beep in all modes", getBeepSetting, setBeepSetting, true, OptionMode::Change); + + +// ############################################################################ + // "Reset to defaults" menu option String getResetToDefaults() { return ""; From 703f4952165e064ba814a14f391c11fa5bb0b6ac Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:08:03 -0400 Subject: [PATCH 11/37] Change struct values to match SetDefaults() --- Code/Reflow_Master_v2/menu_settings.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 3588551..dd9f2ea 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -5,13 +5,13 @@ // Save data struct typedef struct { - boolean valid = false; + boolean valid = true; boolean useFan = false; int fanTimeAfterReflow = 60; byte paste = 0; float power = 1; - int lookAhead = 6; - int lookAheadWarm = 1; + int lookAhead = 7; + int lookAheadWarm = 7; int tempOffset = 0; long bakeTime = 1200; // 20 mins float bakeTemp = 45; // Degrees C From fbdbab53eb6aae95b49a07a928f3b4f4f492849c Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:12:20 -0400 Subject: [PATCH 12/37] Replace SetDefaults with copy constructor All defaults are set in the struct definition itself. This avoids mixed messages about what settings are actually 'default'. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 0bb816a..e2f9775 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1618,20 +1618,8 @@ void EndReflow() void SetDefaults() { - // Default settings values - set.valid = true; - set.fanTimeAfterReflow = 60; - set.power = 1; - set.paste = 0; - set.useFan = false; - set.lookAhead = 7; - set.lookAheadWarm = 7; - set.startFullBlast = false; - set.tempOffset = 0; - set.beep = true; - set.bakeTime = 1200; - set.bakeTemp = 45; - set.bakeTempGap = 3; + // recreate struct using default constructor + set = Settings(); } void ResetSettingsToDefault() From fa5d932ecdb81f13ae4c180438efd2830df6b195 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:13:31 -0400 Subject: [PATCH 13/37] Reword buzzer disable settings option --- Code/Reflow_Master_v2/menu_settings_options.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index 1aa1a50..ecd63c7 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -110,15 +110,15 @@ SettingsOption OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, // "Disable Buzzer" menu option -String getBeepSetting() { +String getBuzzerSetting() { return set.beep ? "OFF" : "ON"; // inverted, as the setting is to 'disable' } -void setBeepSetting() { +void setBuzzerSetting() { set.beep = !set.beep; } -SettingsOption OptionBeep("DISABLE BUZZER", "Disable the buzzer beep in all modes", getBeepSetting, setBeepSetting, true, OptionMode::Change); +SettingsOption OptionBuzzer("DISABLE BUZZER", "Disable buzzer noise in ALL modes", getBuzzerSetting, setBuzzerSetting, true, OptionMode::Change); // ############################################################################ From d69d3236b0fb454e772f4e6e0d8e67e50e04e939 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:17:53 -0400 Subject: [PATCH 14/37] Add key tone option to settings menu To disable the buzzer, but ONLY when pressing buttons and not for functional purposes (e.g. opening the oven door at the end of reflow). --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 22 ++++++++++++------- Code/Reflow_Master_v2/menu_settings.h | 1 + .../menu_settings_options.cpp | 12 ++++++++++ 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index e2f9775..5bebaa3 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1747,6 +1747,12 @@ void ShowResetDefaults() Button press code here */ +void KeyTone(int hertz, int len) +{ + if (!set.keyTone) return; + Buzzer(hertz, len); +} + unsigned long nextButtonPress = 0; void button0Press() @@ -1754,7 +1760,7 @@ void button0Press() if ( nextButtonPress < millis() ) { nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); + KeyTone( 2000, 50 ); if ( state == MENU ) { @@ -1807,7 +1813,7 @@ void button1Press() if ( nextButtonPress < millis() ) { nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); + KeyTone( 2000, 50 ); if ( state == MENU ) { @@ -1845,7 +1851,7 @@ void button2Press() if ( nextButtonPress < millis() ) { nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); + KeyTone( 2000, 50 ); if ( state == MENU ) { @@ -1880,7 +1886,7 @@ void button3Press() if ( nextButtonPress < millis() ) { nextButtonPress = millis() + 20; - Buzzer( 2000, 50 ); + KeyTone( 2000, 50 ); if ( state == MENU ) { @@ -1918,9 +1924,9 @@ void button2LongPressStart() if ( nextButtonPress < millis() ) { nextButtonPress = millis() + 10; - Buzzer( 2000, 10 ); + KeyTone( 2000, 10 ); delay(50); - Buzzer( 2000, 10 ); + KeyTone( 2000, 10 ); } } @@ -1947,9 +1953,9 @@ void button3LongPressStart() if ( nextButtonPress < millis() ) { nextButtonPress = millis() + 20; - Buzzer( 2000, 10 ); + KeyTone( 2000, 10 ); delay(50); - Buzzer( 2000, 10 ); + KeyTone( 2000, 10 ); } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index dd9f2ea..9bf3469 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -18,6 +18,7 @@ typedef struct { int bakeTempGap = 3; // Aim for the desired temp minus this value to compensate for overrun bool startFullBlast = false; bool beep = true; + bool keyTone = true; } Settings; diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index ecd63c7..853488a 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -109,6 +109,18 @@ void changeBakeTempGap() { SettingsOption OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, higher for more mass", getBakeTempGap, changeBakeTempGap, true, OptionMode::Change); +// "Key Tone" menu option +String getKeyToneSetting() { + return set.keyTone ? "ON" : "OFF"; +} + +void setKeyToneSetting() { + set.keyTone = !set.keyTone; +} + +SettingsOption OptionKeyTone("KEY TONE", "Make a noise whenever a button is pressed", getKeyToneSetting, setKeyToneSetting, true, OptionMode::Change); + + // "Disable Buzzer" menu option String getBuzzerSetting() { return set.beep ? "OFF" : "ON"; // inverted, as the setting is to 'disable' From 401ae9e66ae603613328aafc9911980ecde5377d Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:44:33 -0400 Subject: [PATCH 15/37] Create DrawButton helper function --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 130 ++++++--------------- 1 file changed, 35 insertions(+), 95 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 5bebaa3..8637490 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -209,9 +209,9 @@ OneButton button2(BUTTON2, false); OneButton button3(BUTTON3, false); // UI button positions and sizes -int buttonPosY[] = { 19, 74, 129, 184 }; -int buttonHeight = 16; -int buttonWidth = 4; +const unsigned int buttonPosY[] = { 19, 74, 129, 184 }; +const unsigned int buttonHeight = 16; +const unsigned int buttonWidth = 4; // Initiliase a reference for the settings file that we store in flash storage Settings set; @@ -1185,12 +1185,14 @@ void ShowPaste() ShowButtonOptions( true ); } -void ShowButtonOptions( bool clearAll ) +void DrawButton(uint8_t index, const String& str, uint32_t color) { - // int buttonPosY[] = { 19, 74, 129, 184 }; - // int buttonHeight = 16; - // int buttonWidth = 4; + tft.fillRect(tft.width() - 5, buttonPosY[index], buttonWidth, buttonHeight, color); // box + println_Right(tft, str, tft.width() - 27, buttonPosY[index] + 9); // text +} +void ShowButtonOptions( bool clearAll ) +{ tft.setTextColor( WHITE, BLACK ); tft.setTextSize(2); @@ -1203,106 +1205,59 @@ void ShowButtonOptions( bool clearAll ) if ( state == MENU ) { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "REFLOW", tft.width() - 27, buttonPosY[0] + 9 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BAKE", tft.width() - 27, buttonPosY[1] + 9 ); - - // button 2 - tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); - println_Right( tft, "SETTINGS", tft.width() - 27, buttonPosY[2] + 9 ); - - // button 3 - tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); - println_Right( tft, "OVEN CHECK", tft.width() - 27, buttonPosY[3] + 9 ); + DrawButton(0, "REFLOW", GREEN); + DrawButton(1, "BAKE", RED); + DrawButton(2, "SETTINGS", BLUE); + DrawButton(3, "OVEN CHECK", YELLOW); } else if ( state == SETTINGS ) { - // button 0 - tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); + //tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); SettingsOption* ptr = SettingsOption::getIndex(settings_pointer); switch (ptr->Mode) { case(OptionMode::Select): - println_Right(tft, "SELECT", tft.width() - 27, buttonPosY[0] + 9); + DrawButton(0, "SELECT", GREEN); break; case(OptionMode::Change): - println_Right(tft, "CHANGE", tft.width() - 27, buttonPosY[0] + 9); + DrawButton(0, "CHANGE", GREEN); break; } - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 9 ); - - // button 2 - tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); - println_Right( tft, "/\\", tft.width() - 27, buttonPosY[2] + 9 ); - - // button 3 - tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); - println_Right( tft, "\\/", tft.width() - 27, buttonPosY[3] + 9 ); + DrawButton(1, "BACK", RED); + DrawButton(2, "/\\", BLUE); + DrawButton(3, "\\/", YELLOW); UpdateSettingsPointer(); } else if ( state == SETTINGS_PASTE ) { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "SELECT", tft.width() - 27, buttonPosY[0] + 9 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 9 ); - - // button 2 - tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); - println_Right( tft, "/\\", tft.width() - 27, buttonPosY[2] + 9 ); - - // button 3 - tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); - println_Right( tft, "\\/", tft.width() - 27, buttonPosY[3] + 9 ); + DrawButton(0, "SELECT", GREEN); + DrawButton(1, "BACK", RED); + DrawButton(2, "/\\", BLUE); + DrawButton(3, "\\/", YELLOW); UpdateSettingsPointer(); } else if ( state == SETTINGS_RESET ) // restore settings to default { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "YES", tft.width() - 27, buttonPosY[0] + 9 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "NO", tft.width() - 27, buttonPosY[1] + 9 ); + DrawButton(0, "YES", GREEN); + DrawButton(1, "NO", RED); } else if ( state == WARMUP || state == REFLOW || state == OVENCHECK_START ) // warmup, reflow, calibration { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "ABORT", tft.width() - 27, buttonPosY[0] + 9 ); + DrawButton(0, "ABORT", GREEN); } else if ( state == FINISHED ) // Finished { tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "MENU", tft.width() - 27, buttonPosY[0] + 9 ); + DrawButton(0, "MENU", GREEN); } else if ( state == OVENCHECK ) { - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "START", tft.width() - 27, buttonPosY[0] + 9 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 9 ); + DrawButton(0, "START", GREEN); + DrawButton(1, "BACK", RED); } } @@ -1378,22 +1333,11 @@ void ShowBakeMenu() tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - // button 0 - - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "START", tft.width() - 27, buttonPosY[0] + 9 ); - - // button 1 - tft.fillRect( tft.width() - 5, buttonPosY[1], buttonWidth, buttonHeight, RED ); - println_Right( tft, "BACK", tft.width() - 27, buttonPosY[1] + 9 ); - - // button 2 - tft.fillRect( tft.width() - 5, buttonPosY[2], buttonWidth, buttonHeight, BLUE ); - println_Right( tft, "+TEMP", tft.width() - 27, buttonPosY[2] + 9 ); - // button 3 - tft.fillRect( tft.width() - 5, buttonPosY[3], buttonWidth, buttonHeight, YELLOW ); - println_Right( tft, "+TIME", tft.width() - 27, buttonPosY[3] + 9 ); + DrawButton(0, "START", GREEN); + DrawButton(1, "BACK", RED); + DrawButton(2, "+TEMP", BLUE); + DrawButton(3, "+TIME", YELLOW); UpdateBakeMenu(); } @@ -1461,9 +1405,7 @@ void StartBake() tft.setCursor( 20, 135 ); tft.println( "TIME LEFT"); - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "ABORT", tft.width() - 27, buttonPosY[0] + 9 ); + DrawButton(0, "ABORT", GREEN); UpdateBake(); } @@ -1495,9 +1437,7 @@ void BakeDone() tft.setTextColor( WHITE, BLACK ); tft.setTextSize(2); - // button 0 - tft.fillRect( tft.width() - 5, buttonPosY[0], buttonWidth, buttonHeight, GREEN ); - println_Right( tft, "MENU", tft.width() - 27, buttonPosY[0] + 9 ); + DrawButton(0, "MENU", GREEN); delay(750); Buzzer( 2000, 500 ); From 5c8d4402316e7fe838fb86e9213394aa9b574d0e Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 19:55:40 -0400 Subject: [PATCH 16/37] Set button colors automatically Avoids having to repeat the colors everywhere, and makes it easier to change them. Can still be overridden if necessary. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 60 +++++++++++++--------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 8637490..686a133 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -85,6 +85,7 @@ #define FAN A5 // fan control // Just a bunch of re-defined colours +#define DEFAULT_COLOR 0xABCD0000 // magic value, not a real color #define BLUE 0x001F #define TEAL 0x0438 #define GREEN 0x07E0 @@ -212,6 +213,8 @@ OneButton button3(BUTTON3, false); const unsigned int buttonPosY[] = { 19, 74, 129, 184 }; const unsigned int buttonHeight = 16; const unsigned int buttonWidth = 4; +const uint32_t ButtonColor[] = { GREEN, RED, BLUE, YELLOW }; +const unsigned int NumButtons = ELEMENTS(buttonPosY); // Initiliase a reference for the settings file that we store in flash storage Settings set; @@ -1185,8 +1188,15 @@ void ShowPaste() ShowButtonOptions( true ); } +void DrawButton(uint8_t index, const String& str, uint32_t color = DEFAULT_COLOR); + void DrawButton(uint8_t index, const String& str, uint32_t color) { + if (index >= NumButtons) return; + + // if default, set colors based on button index + if (color == DEFAULT_COLOR) color = ButtonColor[index]; + tft.fillRect(tft.width() - 5, buttonPosY[index], buttonWidth, buttonHeight, color); // box println_Right(tft, str, tft.width() - 27, buttonPosY[index] + 9); // text } @@ -1205,10 +1215,10 @@ void ShowButtonOptions( bool clearAll ) if ( state == MENU ) { - DrawButton(0, "REFLOW", GREEN); - DrawButton(1, "BAKE", RED); - DrawButton(2, "SETTINGS", BLUE); - DrawButton(3, "OVEN CHECK", YELLOW); + DrawButton(0, "REFLOW"); + DrawButton(1, "BAKE"); + DrawButton(2, "SETTINGS"); + DrawButton(3, "OVEN CHECK"); } else if ( state == SETTINGS ) { @@ -1218,46 +1228,46 @@ void ShowButtonOptions( bool clearAll ) switch (ptr->Mode) { case(OptionMode::Select): - DrawButton(0, "SELECT", GREEN); + DrawButton(0, "SELECT"); break; case(OptionMode::Change): - DrawButton(0, "CHANGE", GREEN); + DrawButton(0, "CHANGE"); break; } - DrawButton(1, "BACK", RED); - DrawButton(2, "/\\", BLUE); - DrawButton(3, "\\/", YELLOW); + DrawButton(1, "BACK"); + DrawButton(2, "/\\"); + DrawButton(3, "\\/"); UpdateSettingsPointer(); } else if ( state == SETTINGS_PASTE ) { - DrawButton(0, "SELECT", GREEN); - DrawButton(1, "BACK", RED); - DrawButton(2, "/\\", BLUE); - DrawButton(3, "\\/", YELLOW); + DrawButton(0, "SELECT"); + DrawButton(1, "BACK"); + DrawButton(2, "/\\"); + DrawButton(3, "\\/"); UpdateSettingsPointer(); } else if ( state == SETTINGS_RESET ) // restore settings to default { - DrawButton(0, "YES", GREEN); - DrawButton(1, "NO", RED); + DrawButton(0, "YES"); + DrawButton(1, "NO"); } else if ( state == WARMUP || state == REFLOW || state == OVENCHECK_START ) // warmup, reflow, calibration { - DrawButton(0, "ABORT", GREEN); + DrawButton(0, "ABORT"); } else if ( state == FINISHED ) // Finished { tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - DrawButton(0, "MENU", GREEN); + DrawButton(0, "MENU"); } else if ( state == OVENCHECK ) { - DrawButton(0, "START", GREEN); - DrawButton(1, "BACK", RED); + DrawButton(0, "START"); + DrawButton(1, "BACK"); } } @@ -1334,10 +1344,10 @@ void ShowBakeMenu() tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - DrawButton(0, "START", GREEN); - DrawButton(1, "BACK", RED); - DrawButton(2, "+TEMP", BLUE); - DrawButton(3, "+TIME", YELLOW); + DrawButton(0, "START"); + DrawButton(1, "BACK"); + DrawButton(2, "+TEMP"); + DrawButton(3, "+TIME"); UpdateBakeMenu(); } @@ -1405,7 +1415,7 @@ void StartBake() tft.setCursor( 20, 135 ); tft.println( "TIME LEFT"); - DrawButton(0, "ABORT", GREEN); + DrawButton(0, "ABORT"); UpdateBake(); } @@ -1437,7 +1447,7 @@ void BakeDone() tft.setTextColor( WHITE, BLACK ); tft.setTextSize(2); - DrawButton(0, "MENU", GREEN); + DrawButton(0, "MENU"); delay(750); Buzzer( 2000, 500 ); From 234a9d20e1b4dfb924699840e316b5697ba73d6f Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 22 May 2021 23:14:30 -0400 Subject: [PATCH 17/37] Flash buttons when failing to enter mode Visual feedback that the mode can't be entered. Particularly useful when the buzzer is disabled. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 42 +++++++++++++++++----- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 686a133..463c00a 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -215,6 +215,7 @@ const unsigned int buttonHeight = 16; const unsigned int buttonWidth = 4; const uint32_t ButtonColor[] = { GREEN, RED, BLUE, YELLOW }; const unsigned int NumButtons = ELEMENTS(buttonPosY); +String buttonText[NumButtons]; // Initiliase a reference for the settings file that we store in flash storage Settings set; @@ -1188,16 +1189,20 @@ void ShowPaste() ShowButtonOptions( true ); } -void DrawButton(uint8_t index, const String& str, uint32_t color = DEFAULT_COLOR); +void DrawButton(uint8_t index, const String& str, uint32_t textColor = WHITE, uint32_t boxColor = DEFAULT_COLOR); -void DrawButton(uint8_t index, const String& str, uint32_t color) +void DrawButton(uint8_t index, const String& str, uint32_t textColor, uint32_t boxColor) { if (index >= NumButtons) return; // if default, set colors based on button index - if (color == DEFAULT_COLOR) color = ButtonColor[index]; + if (boxColor == DEFAULT_COLOR) boxColor = ButtonColor[index]; - tft.fillRect(tft.width() - 5, buttonPosY[index], buttonWidth, buttonHeight, color); // box + tft.setTextColor(textColor, BLACK); + tft.setTextSize(2); + + buttonText[index] = str; // save text for reference + tft.fillRect(tft.width() - 5, buttonPosY[index], buttonWidth, buttonHeight, boxColor); // box println_Right(tft, str, tft.width() - 27, buttonPosY[index] + 9); // text } @@ -1271,6 +1276,21 @@ void ShowButtonOptions( bool clearAll ) } } +void FlashButtonText(unsigned int index, uint32_t colorSteady = WHITE, uint32_t colorBlink = RED, unsigned int hertz = 5, unsigned int count = 2); + +void FlashButtonText(unsigned int index, uint32_t colorSteady, uint32_t colorBlink, unsigned int hertz, unsigned int count) +{ + if (index >= NumButtons) return; // out of range + const unsigned long period = 1000 / (hertz * 2); // in ms + + for (unsigned int i = 0; i < count; i++) { + DrawButton(index, buttonText[index], colorBlink); + delay(period); + DrawButton(index, buttonText[index], colorSteady); + if(i != count - 1) delay(period); // delay if not on last loop + } +} + void ShowScrollIndicator(float pct, uint32_t color) { if (pct < 0.0) pct = 0.0; @@ -1717,8 +1737,10 @@ void button0Press() // Only allow reflow start if there is no TC error if ( tcError == 0 ) StartWarmup(); - else - Buzzer( 100, 250 ); + else { + Buzzer(100, 250); + FlashButtonText(0); + } } else if ( state == BAKE_MENU ) { @@ -1770,8 +1792,10 @@ void button1Press() // Only allow reflow start if there is no TC error if ( tcError == 0 ) ShowBakeMenu(); - else + else { Buzzer( 100, 250 ); + FlashButtonText(1); + } } else if ( state == SETTINGS ) // leaving settings so save { @@ -1843,8 +1867,10 @@ void button3Press() // Only allow reflow start if there is no TC error if ( tcError == 0 ) ShowOvenCheck(); - else + else { Buzzer( 100, 250 ); + FlashButtonText(3); + } } else if ( state == BAKE_MENU ) { From be0d02282717145be97df9067a58073ebae25934 Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 26 May 2021 17:30:28 -0400 Subject: [PATCH 18/37] Loop settings menu pointer Allows the pointer to loop around from the bottom to the top and vice-versa. Helpful for long settings lists. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 21 ++++++++++++-- Code/Reflow_Master_v2/menu_settings.cpp | 32 ++++++++++++++-------- Code/Reflow_Master_v2/menu_settings.h | 6 +++- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 463c00a..f701c76 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1723,6 +1723,23 @@ void KeyTone(int hertz, int len) Buzzer(hertz, len); } +// returns the a value limited to the min and max ranges, rolling over +// values below and above the provided range as if it was continuous +int constrainLoop(int value, int min, int max) +{ + // rollover up + if (value > max) { + int diff = (value - max - 1) % (max - min + 1); + return constrain(min + diff, min, max); + } + // rollover down + else if (value < min) { + int diff = (value - min + 1) % (max - min + 1); + return constrain(max + diff, min, max); + } + return value; +} + unsigned long nextButtonPress = 0; void button0Press() @@ -1842,7 +1859,7 @@ void button2Press() } else if ( state == SETTINGS ) { - settings_pointer = constrain( settings_pointer - 1, 0, (int) SettingsOption::getCount() - 1 ); + settings_pointer = constrainLoop( settings_pointer - 1, 0, (int) SettingsOption::getCount() - 1 ); ShowButtonOptions( false ); UpdateSettingsPointer(); } @@ -1882,7 +1899,7 @@ void button3Press() } else if ( state == SETTINGS ) { - settings_pointer = constrain( settings_pointer + 1, 0, (int) SettingsOption::getCount() - 1); + settings_pointer = constrainLoop( settings_pointer + 1, 0, (int) SettingsOption::getCount() - 1); ShowButtonOptions( false ); UpdateSettingsPointer(); } diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 3976111..379e64c 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -126,14 +126,9 @@ void SettingsPage::drawCursor(unsigned int pos) { // Clear cursor tft.fillRect(0, 20, 20, tft.height() - 20, BLACK); - // Find if we're offscreen and adjust items accordingly - if (pos < startingItem) { - updateScroll(-1); // decrement - redraw(); - } - else if (pos > startingItem + ItemsPerPage - 1) { // -1 for zero index - updateScroll(1); // increment - redraw(); + // If the current selection is not on the page, we need to redraw the list accordingly + if (updateScroll(pos)) { + redraw(); // redraws those items on the screen } const unsigned int selectedPos = pos - startingItem; @@ -158,15 +153,30 @@ void SettingsPage::changeOption(unsigned int pos) { } } -void SettingsPage::updateScroll(int dir) { +bool SettingsPage::updateScroll(unsigned int pos) { + if (onPage(pos)) return false; // already on page, don't update + switch (Scroll) { case(ScrollType::Smooth): - startingItem += dir; + if (pos < startingItem) { + // 'decrement' to current as first + startingItem = pos; + } + else if (pos > lastItem()) { + // 'increment' to position as last + startingItem = pos - ItemsPerPage + 1; // +1 for 0 index + } break; case(ScrollType::Paged): - startingItem += dir * ItemsPerPage; + { + const unsigned int Page = (pos / ItemsPerPage); // page for this item + const unsigned int PageStart = Page * ItemsPerPage; // starting item for that page + startingItem = PageStart; break; } + } + + return true; } void SettingsPage::drawScrollIndicator() { diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 9bf3469..45db3bf 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -78,7 +78,11 @@ class SettingsPage { }; static const ScrollType Scroll = ScrollType::Paged; - static void updateScroll(int dir); + static bool updateScroll(unsigned int pos); + + static unsigned int lastItem() { return startingItem + ItemsPerPage - 1; } // indexed at 0 + static bool onPage(unsigned int item) { return item >= startingItem && item <= lastItem(); } + }; From ee537710d5c139ccb72226663031eb9be6200f86 Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 26 May 2021 17:49:15 -0400 Subject: [PATCH 19/37] Do not reset pointer on setting default cancel Small quality of life change, but if you cancel the "reset to default" menu option, the menu stays at that setting (and that page) instead of starting over at 0. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 10 +++++++--- Code/Reflow_Master_v2/menu_settings.cpp | 12 ++++++++---- Code/Reflow_Master_v2/menu_settings.h | 4 ++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index f701c76..25913be 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1144,7 +1144,7 @@ void ShowSettings() newSettings = false; - SettingsPage::drawPage(); + SettingsPage::drawPage(settings_pointer); ShowButtonOptions( false ); @@ -1820,11 +1820,15 @@ void button1Press() flash_store.write(set); ShowMenu(); } - else if ( state == SETTINGS_PASTE || state == SETTINGS_RESET ) + else if ( state == SETTINGS_PASTE) { - settings_pointer = 0; + settings_pointer = 0; // reset pointer so we stop at the top of the settings list ShowSettings(); } + else if (state == SETTINGS_RESET) // cancel settings reset + { + ShowSettings(); // do *not* reset pointer so we stay at the same menu item + } else if ( state == OVENCHECK ) // cancel oven check { ShowMenu(); diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 379e64c..c6da168 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -79,8 +79,9 @@ void SettingsOption::drawDescription() { } -void SettingsPage::drawPage() { - startingItem = 0; // reset scrolling for initial draw +void SettingsPage::drawPage(unsigned int pos) { + startingItem = 0; // reset pagination + updateScroll(pos); // recalculate pagination for current position tft.fillScreen(BLACK); @@ -93,12 +94,15 @@ void SettingsPage::drawPage() { // drawScrollIndicator(); // skipping this because it's drawn over by the button icons anyways } -void SettingsPage::redraw() { +void SettingsPage::redraw(unsigned int pos) { // drawing over *only* the items, rather than the entire page (title, cursor, button prompts) tft.fillRect(15, SettingsOption::getYPosition(0) - 5, 240, SettingsOption::getYPosition(ItemsPerPage), BLACK); // clear the description box as well tft.fillRect(0, tft.height() - 20, tft.width(), 20, BLACK); + + // recalculate pagination for current position (if necessary) + updateScroll(pos); drawItems(); drawScrollIndicator(); @@ -128,7 +132,7 @@ void SettingsPage::drawCursor(unsigned int pos) { // If the current selection is not on the page, we need to redraw the list accordingly if (updateScroll(pos)) { - redraw(); // redraws those items on the screen + redraw(pos); // redraws those items on the screen } const unsigned int selectedPos = pos - startingItem; diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 45db3bf..ecdb391 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -58,8 +58,8 @@ class SettingsOption : public LinkedList { class SettingsPage { public: - static void drawPage(); - static void redraw(); + static void drawPage(unsigned int pos); + static void redraw(unsigned int pos); static void drawCursor(unsigned int pos); static void drawScrollIndicator(); From 9529625476203ff11f58870614c0934b4c233a91 Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 26 May 2021 17:53:18 -0400 Subject: [PATCH 20/37] Refactor linked list 'geIIndex' to use 'ItemAt' Making it clear that we're returning the object rather than some reference to position --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 2 +- Code/Reflow_Master_v2/linked_list.h | 2 +- Code/Reflow_Master_v2/menu_settings.cpp | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 25913be..994c9e9 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1229,7 +1229,7 @@ void ShowButtonOptions( bool clearAll ) { //tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - SettingsOption* ptr = SettingsOption::getIndex(settings_pointer); + SettingsOption* ptr = SettingsOption::getItemAtIndex(settings_pointer); switch (ptr->Mode) { case(OptionMode::Select): diff --git a/Code/Reflow_Master_v2/linked_list.h b/Code/Reflow_Master_v2/linked_list.h index 6a737ab..ff70827 100644 --- a/Code/Reflow_Master_v2/linked_list.h +++ b/Code/Reflow_Master_v2/linked_list.h @@ -19,7 +19,7 @@ class LinkedList { return count; } - static T* getIndex(unsigned int i) { + static T* getItemAtIndex(unsigned int i) { T* ptr = head; while (ptr != nullptr && i != 0) { ptr = ptr->getNext(); diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index c6da168..d252551 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -124,7 +124,7 @@ void SettingsPage::drawItems() { } void SettingsPage::drawCursor(unsigned int pos) { - SettingsOption* ptr = SettingsOption::getIndex(pos); + SettingsOption* ptr = SettingsOption::getItemAtIndex(pos); if (ptr == nullptr) return; // out of range // Clear cursor @@ -147,7 +147,7 @@ void SettingsPage::drawCursor(unsigned int pos) { } void SettingsPage::changeOption(unsigned int pos) { - SettingsOption* ptr = SettingsOption::getIndex(pos); + SettingsOption* ptr = SettingsOption::getItemAtIndex(pos); if (ptr == nullptr) return; ptr->setFunction(); From 737a49212f88ba60573b32cc547d8ae4da5f66bc Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 26 May 2021 19:23:05 -0400 Subject: [PATCH 21/37] Redraw menu value separately from name Reduces flickering by only updating the menu item value rather than the name and value (at the expense of calculating the text bounds each call) --- Code/Reflow_Master_v2/menu_settings.cpp | 41 +++++++++++++++++++++++-- Code/Reflow_Master_v2/menu_settings.h | 4 +++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index d252551..713280f 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -53,17 +53,52 @@ unsigned long SettingsOption::getYPosition(unsigned int index) { } void SettingsOption::drawItem(unsigned int position) { + const unsigned int xPos = ItemStartX; const unsigned int yPos = getYPosition(position); - tft.fillRect(15, yPos - 5, 240, ItemHeight, BLACK); - tft.setCursor(20, yPos); + + int16_t clearX, clearY; + uint16_t clearWidth, clearHeight; tft.setTextSize(2); + tft.getTextBounds(ItemName + " ", xPos, yPos, &clearX, &clearY, &clearWidth, &clearHeight); + tft.fillRect(clearX, clearY, clearWidth, clearHeight, BLACK); // clear text area + + tft.setCursor(xPos, yPos); + tft.setTextColor(WHITE, BLACK); tft.print(ItemName); tft.print(' '); + this->drawValue(position); +} + +void SettingsOption::drawValue(unsigned int position) { + const unsigned int yPos = getYPosition(position); + + int16_t nameX, dummyY; + uint16_t nameWidth, dummyHeight; + + // Calculate size of item name to set cursor at end + tft.setTextSize(2); + tft.getTextBounds(ItemName + " ", ItemStartX, yPos, &nameX, &dummyY, &nameWidth, &dummyHeight); + + const unsigned int xPos = nameX + nameWidth; // start at the end of the item name + + // Note that we're not reusing the variables from above because the program seems to get + // confused and use the values from the first call rather than the second (potentially an optimization issue?) + int16_t clearX, clearY; + uint16_t clearWidth, clearHeight; + + // Calculate size of item description for clearing (using last value) + tft.setTextSize(2); + tft.getTextBounds(lastValue, xPos, yPos, &clearX, &clearY, &clearWidth, &clearHeight); + tft.fillRect(clearX, clearY, clearWidth, clearHeight, BLACK); // clear area + + tft.setCursor(xPos, yPos); tft.setTextColor(YELLOW, BLACK); tft.print(getFunction()); + + lastValue = getFunction(); // save value so we know how much to 'clear' for next call } void SettingsOption::drawDescription() { @@ -153,7 +188,7 @@ void SettingsPage::changeOption(unsigned int pos) { ptr->setFunction(); if (ptr->RefreshOnChange == true) { - ptr->drawItem(SettingsOption::getPositionOf(ptr) - startingItem); + ptr->drawValue(SettingsOption::getPositionOf(ptr) - startingItem); } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index ecdb391..c9ea9ac 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -49,11 +49,15 @@ class SettingsOption : public LinkedList { static unsigned long getYPosition(unsigned int index); void drawItem(unsigned int posY); + void drawValue(unsigned int posY); void drawDescription(); private: static const unsigned int ItemHeight = 19; + static const unsigned int ItemStartX = 20; static const unsigned int ItemStartY = 45; + + String lastValue; }; class SettingsPage { From f4aa336b26eb694fd6003f6d8f0f828810a7351c Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 26 May 2021 19:36:33 -0400 Subject: [PATCH 22/37] Move button text string option to class --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 14 +------------- Code/Reflow_Master_v2/menu_settings.cpp | 20 ++++++++++++++++++++ Code/Reflow_Master_v2/menu_settings.h | 3 +++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 994c9e9..ed7cafa 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1227,19 +1227,7 @@ void ShowButtonOptions( bool clearAll ) } else if ( state == SETTINGS ) { - //tft.fillRect( tft.width() - 100, buttonPosY[0] - 2, 100, buttonHeight + 4, BLACK ); - - SettingsOption* ptr = SettingsOption::getItemAtIndex(settings_pointer); - switch (ptr->Mode) - { - case(OptionMode::Select): - DrawButton(0, "SELECT"); - break; - case(OptionMode::Change): - DrawButton(0, "CHANGE"); - break; - } - + DrawButton(0, SettingsPage::getButtonText(settings_pointer)); DrawButton(1, "BACK"); DrawButton(2, "/\\"); DrawButton(3, "\\/"); diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 713280f..e4397c7 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -113,6 +113,19 @@ void SettingsOption::drawDescription() { println_Center(tft, this->ItemDescription, tft.width() / 2, textPosY); } +String SettingsOption::getModeString() const { + switch (Mode) + { + case(OptionMode::Select): + return "SELECT"; + break; + case(OptionMode::Change): + return "CHANGE"; + break; + } + return ""; // invalid +} + void SettingsPage::drawPage(unsigned int pos) { startingItem = 0; // reset pagination @@ -240,3 +253,10 @@ void SettingsPage::drawScrollIndicator() { } } } + +String SettingsPage::getButtonText(unsigned int pos) { + SettingsOption* ptr = SettingsOption::getItemAtIndex(pos); + if (ptr == nullptr) return ""; + return ptr->getModeString(); +} + diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index c9ea9ac..dd26f34 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -47,6 +47,7 @@ class SettingsOption : public LinkedList { ~SettingsOption(); static unsigned long getYPosition(unsigned int index); + String getModeString() const; void drawItem(unsigned int posY); void drawValue(unsigned int posY); @@ -70,6 +71,8 @@ class SettingsPage { static void changeOption(unsigned int pos); + static String getButtonText(unsigned int pos); + private: static const unsigned int ItemsPerPage = 9; // should be calculated given font size and screen space, but good enough for testing static unsigned int startingItem; From a2adf2a08ce7dfa58d4a2122756931942c025d80 Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 26 May 2021 19:43:37 -0400 Subject: [PATCH 23/37] Move settings pointer update out of buttons Otherwise this is called twice --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index ed7cafa..4b07e6a 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1147,6 +1147,7 @@ void ShowSettings() SettingsPage::drawPage(settings_pointer); ShowButtonOptions( false ); + UpdateSettingsPointer(); SettingsPage::drawScrollIndicator(); // needs to be redrawn on top of buttons } @@ -1231,8 +1232,6 @@ void ShowButtonOptions( bool clearAll ) DrawButton(1, "BACK"); DrawButton(2, "/\\"); DrawButton(3, "\\/"); - - UpdateSettingsPointer(); } else if ( state == SETTINGS_PASTE ) { From fa18b4072a01eddc76086d2195cee98784788e64 Mon Sep 17 00:00:00 2001 From: David Madison Date: Wed, 26 May 2021 19:45:16 -0400 Subject: [PATCH 24/37] Refactor UpdateSettingsPointer as 'Draw' Since this function isn't "updating" anything but the display, and the name makes me think it's doing calculations on the pointer value itself. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 4b07e6a..f9980f6 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1147,7 +1147,7 @@ void ShowSettings() SettingsPage::drawPage(settings_pointer); ShowButtonOptions( false ); - UpdateSettingsPointer(); + DrawSettingsPointer(); SettingsPage::drawScrollIndicator(); // needs to be redrawn on top of buttons } @@ -1240,7 +1240,7 @@ void ShowButtonOptions( bool clearAll ) DrawButton(2, "/\\"); DrawButton(3, "\\/"); - UpdateSettingsPointer(); + DrawSettingsPointer(); } else if ( state == SETTINGS_RESET ) // restore settings to default { @@ -1461,7 +1461,7 @@ void BakeDone() } -void UpdateSettingsPointer() +void DrawSettingsPointer() { if ( state == SETTINGS ) { @@ -1852,12 +1852,12 @@ void button2Press() { settings_pointer = constrainLoop( settings_pointer - 1, 0, (int) SettingsOption::getCount() - 1 ); ShowButtonOptions( false ); - UpdateSettingsPointer(); + DrawSettingsPointer(); } else if ( state == SETTINGS_PASTE ) { settings_pointer = constrain( settings_pointer - 1, 0, (int) ELEMENTS(solderPaste) - 1 ); - UpdateSettingsPointer(); + DrawSettingsPointer(); } } } @@ -1892,12 +1892,12 @@ void button3Press() { settings_pointer = constrainLoop( settings_pointer + 1, 0, (int) SettingsOption::getCount() - 1); ShowButtonOptions( false ); - UpdateSettingsPointer(); + DrawSettingsPointer(); } else if ( state == SETTINGS_PASTE ) { settings_pointer = constrain( settings_pointer + 1, 0, (int) ELEMENTS(solderPaste) - 1 ); - UpdateSettingsPointer(); + DrawSettingsPointer(); } } } From 9293aa29f2ad70631a0ed76bc425fd4e0265a524 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 27 May 2021 02:26:41 -0400 Subject: [PATCH 25/37] Remove 'refresh on change' setting parameter This is redundant, as all modes with "SELECT" are used to load new pages and do not need to refresh on change. --- Code/Reflow_Master_v2/menu_settings.cpp | 10 ++++++--- Code/Reflow_Master_v2/menu_settings.h | 3 +-- .../menu_settings_options.cpp | 22 +++++++++---------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index e4397c7..4ca9f7e 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -33,11 +33,10 @@ SettingsOption* LinkedList::head = nullptr; unsigned int SettingsPage::startingItem = 0; -SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, bool refresh, OptionMode m) +SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m) : ItemName(name), ItemDescription(desc), getFunction(get), setFunction(set), - RefreshOnChange(refresh), Mode(m) { LinkedList::add(this); @@ -200,8 +199,13 @@ void SettingsPage::changeOption(unsigned int pos) { ptr->setFunction(); - if (ptr->RefreshOnChange == true) { + switch (ptr->Mode) { + case(OptionMode::Select): + // do nothing here, we're loading a new menu instead + break; + case(OptionMode::Change): ptr->drawValue(SettingsOption::getPositionOf(ptr) - startingItem); + break; } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index dd26f34..d52edfc 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -40,10 +40,9 @@ class SettingsOption : public LinkedList { const MenuGetFunc getFunction; const MenuSetFunc setFunction; - const bool RefreshOnChange; const OptionMode Mode; - SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, bool refresh, OptionMode m); + SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m); ~SettingsOption(); static unsigned long getYPosition(unsigned int index); diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index 853488a..d0d7801 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -12,7 +12,7 @@ void changeSwitchPaste() { ShowPaste(); } -SettingsOption OptionPasteMenu("SWITCH PASTE", "Select which profile to reflow", getSwitchPaste, changeSwitchPaste, false, OptionMode::Select); +SettingsOption OptionPasteMenu("SWITCH PASTE", "Select which profile to reflow", getSwitchPaste, changeSwitchPaste, OptionMode::Select); // "Use Fan" menu option @@ -24,7 +24,7 @@ void changeUseFan() { set.useFan = !set.useFan; } -SettingsOption OptionUseFan("USE FAN", "Enable fan for end of reflow, requires 5V DC fan", getUseFan, changeUseFan, true, OptionMode::Change); +SettingsOption OptionUseFan("USE FAN", "Enable fan for end of reflow, requires 5V DC fan", getUseFan, changeUseFan, OptionMode::Change); // "Fan Countdown" menu option @@ -38,7 +38,7 @@ void changeFanCountdown() { set.fanTimeAfterReflow = 0; } -SettingsOption OptionFanCountdown("FAN COUNTDOWN", "Keep fan on for XXX sec after reflow", getFanCountdown, changeFanCountdown, true, OptionMode::Change); +SettingsOption OptionFanCountdown("FAN COUNTDOWN", "Keep fan on for XXX sec after reflow", getFanCountdown, changeFanCountdown, OptionMode::Change); // "Graph Look Ahead" menu option @@ -52,7 +52,7 @@ void changeGraphLookAhead() { set.lookAhead = 1; } -SettingsOption OptionGraphLookAhead("GRAPH LOOK AHEAD", "Soak and Reflow look ahead for rate change speed", getGraphLookAhead, changeGraphLookAhead, true, OptionMode::Change); +SettingsOption OptionGraphLookAhead("GRAPH LOOK AHEAD", "Soak and Reflow look ahead for rate change speed", getGraphLookAhead, changeGraphLookAhead, OptionMode::Change); // "Power" menu option @@ -66,7 +66,7 @@ void changePower() { set.power = 0.5; } -SettingsOption OptionPower("POWER", "Adjust the power boost", getPower, changePower, true, OptionMode::Change); +SettingsOption OptionPower("POWER", "Adjust the power boost", getPower, changePower, OptionMode::Change); // "Temp Offset" menu option @@ -80,7 +80,7 @@ void changeTempOffset() { set.tempOffset = -15; } -SettingsOption OptionTempOffset("TEMP OFFSET", "Adjust temp probe reading offset", getTempOffset, changeTempOffset, true, OptionMode::Change); +SettingsOption OptionTempOffset("TEMP OFFSET", "Adjust temp probe reading offset", getTempOffset, changeTempOffset, OptionMode::Change); // "Start Ramp 100%" menu option @@ -92,7 +92,7 @@ void changeStartFullBlast() { set.startFullBlast = !set.startFullBlast; } -SettingsOption OptionStartFullBlast("START RAMP 100%", "Force full power on initial ramp-up - be careful!", getStartFullBlast, changeStartFullBlast, true, OptionMode::Change); +SettingsOption OptionStartFullBlast("START RAMP 100%", "Force full power on initial ramp-up - be careful!", getStartFullBlast, changeStartFullBlast, OptionMode::Change); // "Bake Temp Gap" menu option @@ -106,7 +106,7 @@ void changeBakeTempGap() { set.bakeTempGap = 0; } -SettingsOption OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, higher for more mass", getBakeTempGap, changeBakeTempGap, true, OptionMode::Change); +SettingsOption OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, higher for more mass", getBakeTempGap, changeBakeTempGap, OptionMode::Change); // "Key Tone" menu option @@ -118,7 +118,7 @@ void setKeyToneSetting() { set.keyTone = !set.keyTone; } -SettingsOption OptionKeyTone("KEY TONE", "Make a noise whenever a button is pressed", getKeyToneSetting, setKeyToneSetting, true, OptionMode::Change); +SettingsOption OptionKeyTone("KEY TONE", "Make a noise whenever a button is pressed", getKeyToneSetting, setKeyToneSetting, OptionMode::Change); // "Disable Buzzer" menu option @@ -130,7 +130,7 @@ void setBuzzerSetting() { set.beep = !set.beep; } -SettingsOption OptionBuzzer("DISABLE BUZZER", "Disable buzzer noise in ALL modes", getBuzzerSetting, setBuzzerSetting, true, OptionMode::Change); +SettingsOption OptionBuzzer("DISABLE BUZZER", "Disable buzzer noise in ALL modes", getBuzzerSetting, setBuzzerSetting, OptionMode::Change); // ############################################################################ @@ -144,4 +144,4 @@ void goToResetDefaults() { ShowResetDefaults(); } -SettingsOption OptionResetToDefaults("RESET TO DEFAULTS", "Reset to default settings", getResetToDefaults, goToResetDefaults, false, OptionMode::Select); +SettingsOption OptionResetToDefaults("RESET TO DEFAULTS", "Reset to default settings", getResetToDefaults, goToResetDefaults, OptionMode::Select); From 103aa929930b044c438773a9a0941e90443a2366 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 12 Jun 2021 17:42:42 -0400 Subject: [PATCH 26/37] Move TFT include and colors to dedicated header --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 30 +----------------- Code/Reflow_Master_v2/menu_settings.cpp | 26 ---------------- Code/Reflow_Master_v2/menu_settings.h | 3 +- Code/Reflow_Master_v2/tft_display.h | 36 ++++++++++++++++++++++ 4 files changed, 38 insertions(+), 57 deletions(-) create mode 100644 Code/Reflow_Master_v2/tft_display.h diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index f9980f6..acd74f0 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -50,13 +50,12 @@ #include #include "spline.h" -#include "Adafruit_GFX.h" // Add from Library Manager -#include "Adafruit_ILI9341.h" // Add from Library Manager #include "MAX31855.h" #include "OneButton.h" // Add from Library Manager #include "ReflowMasterProfile.h" #include "FlashStorage.h" +#include "tft_display.h" #include "menu_settings.h" // used to obtain the size of an array of any type @@ -84,33 +83,6 @@ #define RELAY 5 // relay control #define FAN A5 // fan control -// Just a bunch of re-defined colours -#define DEFAULT_COLOR 0xABCD0000 // magic value, not a real color -#define BLUE 0x001F -#define TEAL 0x0438 -#define GREEN 0x07E0 -#define CYAN 0x07FF -#define RED 0xF800 -#define MAGENTA 0xF81F -#define YELLOW 0xFFE0 -#define ORANGE 0xFC00 -#define PINK 0xF81F -#define PURPLE 0x8010 -#define GREY 0xC618 -#define WHITE 0xFFFF -#define BLACK 0x0000 -#define DKBLUE 0x000D -#define DKTEAL 0x020C -#define DKGREEN 0x03E0 -#define DKCYAN 0x03EF -#define DKRED 0x6000 -#define DKMAGENTA 0x8008 -#define DKYELLOW 0x8400 -#define DKORANGE 0x8200 -#define DKPINK 0x9009 -#define DKPURPLE 0x4010 -#define DKGREY 0x4A49 - // UI and runtime states enum states { BOOT = 0, diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 4ca9f7e..5587b7c 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -1,31 +1,5 @@ #include "menu_settings.h" -// Just a bunch of re-defined colours -#define BLUE 0x001F -#define TEAL 0x0438 -#define GREEN 0x07E0 -#define CYAN 0x07FF -#define RED 0xF800 -#define MAGENTA 0xF81F -#define YELLOW 0xFFE0 -#define ORANGE 0xFC00 -#define PINK 0xF81F -#define PURPLE 0x8010 -#define GREY 0xC618 -#define WHITE 0xFFFF -#define BLACK 0x0000 -#define DKBLUE 0x000D -#define DKTEAL 0x020C -#define DKGREEN 0x03E0 -#define DKCYAN 0x03EF -#define DKRED 0x6000 -#define DKMAGENTA 0x8008 -#define DKYELLOW 0x8400 -#define DKORANGE 0x8200 -#define DKPINK 0x9009 -#define DKPURPLE 0x4010 -#define DKGREY 0x4A49 - template<> SettingsOption* LinkedList::head = nullptr; diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index d52edfc..5902406 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -1,6 +1,6 @@ #include -#include // for TFT drawing +#include "tft_display.h" #include "linked_list.h" // Save data struct @@ -93,7 +93,6 @@ class SettingsPage { extern Settings set; -extern Adafruit_ILI9341 tft; void ShowScrollIndicator(float, uint32_t); void ShowPageIndicator(unsigned int, unsigned int, uint32_t); diff --git a/Code/Reflow_Master_v2/tft_display.h b/Code/Reflow_Master_v2/tft_display.h new file mode 100644 index 0000000..16f6272 --- /dev/null +++ b/Code/Reflow_Master_v2/tft_display.h @@ -0,0 +1,36 @@ +#ifndef TFT_DISPLAY_H +#define TFT_DISPLAY_H + +#include // Add from Library Manager +#include // Add from Library Manager + +// Just a bunch of pre-defined colours +#define DEFAULT_COLOR 0xABCD0000 // magic value, not a real color +#define BLUE 0x001F +#define TEAL 0x0438 +#define GREEN 0x07E0 +#define CYAN 0x07FF +#define RED 0xF800 +#define MAGENTA 0xF81F +#define YELLOW 0xFFE0 +#define ORANGE 0xFC00 +#define PINK 0xF81F +#define PURPLE 0x8010 +#define GREY 0xC618 +#define WHITE 0xFFFF +#define BLACK 0x0000 +#define DKBLUE 0x000D +#define DKTEAL 0x020C +#define DKGREEN 0x03E0 +#define DKCYAN 0x03EF +#define DKRED 0x6000 +#define DKMAGENTA 0x8008 +#define DKYELLOW 0x8400 +#define DKORANGE 0x8200 +#define DKPINK 0x9009 +#define DKPURPLE 0x4010 +#define DKGREY 0x4A49 + +extern Adafruit_ILI9341 tft; + +#endif From e1876d726cd0ba03b082ec82478dba05c3901481 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 12 Jun 2021 18:34:34 -0400 Subject: [PATCH 27/37] Refactor indicator functions from 'Show' to 'Draw' --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 4 ++-- Code/Reflow_Master_v2/menu_settings.cpp | 4 ++-- Code/Reflow_Master_v2/menu_settings.h | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index acd74f0..892ad7c 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1250,7 +1250,7 @@ void FlashButtonText(unsigned int index, uint32_t colorSteady, uint32_t colorBli } } -void ShowScrollIndicator(float pct, uint32_t color) +void DrawScrollIndicator(float pct, uint32_t color) { if (pct < 0.0) pct = 0.0; else if (pct > 1.0) pct = 1.0; @@ -1272,7 +1272,7 @@ void ShowScrollIndicator(float pct, uint32_t color) tft.fillRect(XPos, yPos, Width, Height, color); // draw indicator } -void ShowPageIndicator(unsigned int page, unsigned int numPages, uint32_t color) +void DrawPageIndicator(unsigned int page, unsigned int numPages, uint32_t color) { const unsigned int TextWidth = 31; // total width from right edge, ballpark const unsigned int TextHeight = 8; // with text size '1' diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 5587b7c..eace0e5 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -218,7 +218,7 @@ void SettingsPage::drawScrollIndicator() { const unsigned int NumPositions = SettingsOption::getCount() - ItemsPerPage; const float value = (float) startingItem / (float) NumPositions; - ShowScrollIndicator(value, BLUE); + DrawScrollIndicator(value, BLUE); break; } case(ScrollType::Paged): @@ -226,7 +226,7 @@ void SettingsPage::drawScrollIndicator() { const unsigned int Page = (startingItem / ItemsPerPage) + 1; const unsigned int NumItems = SettingsOption::getCount(); const unsigned int NumPages = (NumItems / ItemsPerPage) + ((NumItems % ItemsPerPage != 0) ? 1 : 0); - ShowPageIndicator(Page, NumPages, WHITE); + DrawPageIndicator(Page, NumPages, WHITE); break; } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 5902406..66c6864 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -94,7 +94,7 @@ class SettingsPage { extern Settings set; -void ShowScrollIndicator(float, uint32_t); -void ShowPageIndicator(unsigned int, unsigned int, uint32_t); +void DrawScrollIndicator(float, uint32_t); +void DrawPageIndicator(unsigned int, unsigned int, uint32_t); void println_Center(Adafruit_ILI9341& d, String heading, int centerX, int centerY); From 2d6ccd76f9476b90fec9da7bc19d02133171ca49 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 12 Jun 2021 18:37:00 -0400 Subject: [PATCH 28/37] Move settings button functionality to class Allowing the class to override these buttons as-needed. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 20 +++++++------- Code/Reflow_Master_v2/menu_settings.cpp | 31 ++++++++++++++++++++++ Code/Reflow_Master_v2/menu_settings.h | 10 +++++++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 892ad7c..6874ade 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1124,6 +1124,12 @@ void ShowSettings() SettingsPage::drawScrollIndicator(); // needs to be redrawn on top of buttons } +void ExitSettings() +{ + flash_store.write(set); + ShowMenu(); +} + void ShowPaste() { state = SETTINGS_PASTE; @@ -1734,7 +1740,7 @@ void button0Press() } else if ( state == SETTINGS ) { - SettingsPage::changeOption(settings_pointer); + SettingsPage::pressButton(0); } else if ( state == SETTINGS_PASTE ) { @@ -1775,9 +1781,7 @@ void button1Press() } else if ( state == SETTINGS ) // leaving settings so save { - // save data in flash - flash_store.write(set); - ShowMenu(); + SettingsPage::pressButton(1); } else if ( state == SETTINGS_PASTE) { @@ -1822,9 +1826,7 @@ void button2Press() } else if ( state == SETTINGS ) { - settings_pointer = constrainLoop( settings_pointer - 1, 0, (int) SettingsOption::getCount() - 1 ); - ShowButtonOptions( false ); - DrawSettingsPointer(); + SettingsPage::pressButton(2); } else if ( state == SETTINGS_PASTE ) { @@ -1862,9 +1864,7 @@ void button3Press() } else if ( state == SETTINGS ) { - settings_pointer = constrainLoop( settings_pointer + 1, 0, (int) SettingsOption::getCount() - 1); - ShowButtonOptions( false ); - DrawSettingsPointer(); + SettingsPage::pressButton(3); } else if ( state == SETTINGS_PASTE ) { diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index eace0e5..7f69581 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -100,6 +100,37 @@ String SettingsOption::getModeString() const { } +void SettingsPage::pressButton(unsigned int num) { + switch (num) { + + // Select + case(0): + changeOption(settings_pointer); + break; + + // Back + case(1): + // save data in flash + ExitSettings(); + break; + + // Up List + case(2): + settings_pointer = constrainLoop(settings_pointer - 1, 0, (int)SettingsOption::getCount() - 1); + ShowButtonOptions(false); + DrawSettingsPointer(); + break; + + // Down List + case(3): + settings_pointer = constrainLoop(settings_pointer + 1, 0, (int)SettingsOption::getCount() - 1); + ShowButtonOptions(false); + DrawSettingsPointer(); + break; + } +} + + void SettingsPage::drawPage(unsigned int pos) { startingItem = 0; // reset pagination updateScroll(pos); // recalculate pagination for current position diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 66c6864..6b7e431 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -62,6 +62,8 @@ class SettingsOption : public LinkedList { class SettingsPage { public: + static void pressButton(unsigned int num); + static void drawPage(unsigned int pos); static void redraw(unsigned int pos); @@ -93,8 +95,16 @@ class SettingsPage { extern Settings set; +extern int settings_pointer; + +int constrainLoop(int value, int min, int max); +void ExitSettings(); + +void DrawSettingsPointer(); void DrawScrollIndicator(float, uint32_t); void DrawPageIndicator(unsigned int, unsigned int, uint32_t); +void ShowButtonOptions(bool clearAll); + void println_Center(Adafruit_ILI9341& d, String heading, int centerX, int centerY); From 995fbfae6ae55c5b73137214896a2aac16b34967 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 12 Jun 2021 19:02:06 -0400 Subject: [PATCH 29/37] Create dedicated selection var for settings class Not strictly necessary, but increases encapsulation and avoids any weirdness with modifying the global selection value when switching between menus. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 13 +++--- Code/Reflow_Master_v2/menu_settings.cpp | 47 ++++++++++++---------- Code/Reflow_Master_v2/menu_settings.h | 14 +++---- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 6874ade..a579382 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1109,14 +1109,16 @@ void ShowMenu() ShowButtonOptions( true ); } -void ShowSettings() +void ShowSettings(bool resetSelection = true); + +void ShowSettings(bool resetSelection) { state = SETTINGS; SetRelayFrequency( 0 ); newSettings = false; - SettingsPage::drawPage(settings_pointer); + SettingsPage::drawPage(resetSelection); ShowButtonOptions( false ); DrawSettingsPointer(); @@ -1206,7 +1208,7 @@ void ShowButtonOptions( bool clearAll ) } else if ( state == SETTINGS ) { - DrawButton(0, SettingsPage::getButtonText(settings_pointer)); + DrawButton(0, SettingsPage::getButtonText()); DrawButton(1, "BACK"); DrawButton(2, "/\\"); DrawButton(3, "\\/"); @@ -1443,7 +1445,7 @@ void DrawSettingsPointer() { if ( state == SETTINGS ) { - SettingsPage::drawCursor(settings_pointer); + SettingsPage::drawCursor(); } else if ( state == SETTINGS_PASTE ) { @@ -1567,7 +1569,6 @@ void ResetSettingsToDefault() SetCurrentGraph( set.paste ); // show settings - settings_pointer = 0; ShowSettings(); } @@ -1790,7 +1791,7 @@ void button1Press() } else if (state == SETTINGS_RESET) // cancel settings reset { - ShowSettings(); // do *not* reset pointer so we stay at the same menu item + ShowSettings(false); // do *not* reset pagination } else if ( state == OVENCHECK ) // cancel oven check { diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 7f69581..e3134cc 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -5,6 +5,7 @@ template<> SettingsOption* LinkedList::head = nullptr; unsigned int SettingsPage::startingItem = 0; +unsigned int SettingsPage::selectedItem = 0; SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m) @@ -105,7 +106,7 @@ void SettingsPage::pressButton(unsigned int num) { // Select case(0): - changeOption(settings_pointer); + changeOption(selectedItem); break; // Back @@ -116,14 +117,14 @@ void SettingsPage::pressButton(unsigned int num) { // Up List case(2): - settings_pointer = constrainLoop(settings_pointer - 1, 0, (int)SettingsOption::getCount() - 1); + selectedItem = constrainLoop(selectedItem - 1, 0, (int)SettingsOption::getCount() - 1); ShowButtonOptions(false); DrawSettingsPointer(); break; // Down List case(3): - settings_pointer = constrainLoop(settings_pointer + 1, 0, (int)SettingsOption::getCount() - 1); + selectedItem = constrainLoop(selectedItem + 1, 0, (int)SettingsOption::getCount() - 1); ShowButtonOptions(false); DrawSettingsPointer(); break; @@ -131,9 +132,11 @@ void SettingsPage::pressButton(unsigned int num) { } -void SettingsPage::drawPage(unsigned int pos) { - startingItem = 0; // reset pagination - updateScroll(pos); // recalculate pagination for current position +void SettingsPage::drawPage(bool resetSelection) { + if (resetSelection) { + selectedItem = startingItem = 0; // reset pagination + } + updateScroll(); // recalculate pagination for current position tft.fillScreen(BLACK); @@ -146,7 +149,7 @@ void SettingsPage::drawPage(unsigned int pos) { // drawScrollIndicator(); // skipping this because it's drawn over by the button icons anyways } -void SettingsPage::redraw(unsigned int pos) { +void SettingsPage::redraw() { // drawing over *only* the items, rather than the entire page (title, cursor, button prompts) tft.fillRect(15, SettingsOption::getYPosition(0) - 5, 240, SettingsOption::getYPosition(ItemsPerPage), BLACK); @@ -154,7 +157,7 @@ void SettingsPage::redraw(unsigned int pos) { tft.fillRect(0, tft.height() - 20, tft.width(), 20, BLACK); // recalculate pagination for current position (if necessary) - updateScroll(pos); + updateScroll(); drawItems(); drawScrollIndicator(); @@ -175,19 +178,19 @@ void SettingsPage::drawItems() { } } -void SettingsPage::drawCursor(unsigned int pos) { - SettingsOption* ptr = SettingsOption::getItemAtIndex(pos); +void SettingsPage::drawCursor() { + SettingsOption* ptr = SettingsOption::getItemAtIndex(selectedItem); if (ptr == nullptr) return; // out of range // Clear cursor tft.fillRect(0, 20, 20, tft.height() - 20, BLACK); // If the current selection is not on the page, we need to redraw the list accordingly - if (updateScroll(pos)) { - redraw(pos); // redraws those items on the screen + if (updateScroll()) { + redraw(); // redraws those items on the screen } - const unsigned int selectedPos = pos - startingItem; + const unsigned int selectedPos = selectedItem - startingItem; // Draw the actual cursor tft.setTextColor(BLUE, BLACK); @@ -214,23 +217,23 @@ void SettingsPage::changeOption(unsigned int pos) { } } -bool SettingsPage::updateScroll(unsigned int pos) { - if (onPage(pos)) return false; // already on page, don't update +bool SettingsPage::updateScroll() { + if (onPage(selectedItem)) return false; // already on page, don't update switch (Scroll) { case(ScrollType::Smooth): - if (pos < startingItem) { + if (selectedItem < startingItem) { // 'decrement' to current as first - startingItem = pos; + startingItem = selectedItem; } - else if (pos > lastItem()) { + else if (selectedItem > lastItem()) { // 'increment' to position as last - startingItem = pos - ItemsPerPage + 1; // +1 for 0 index + startingItem = selectedItem - ItemsPerPage + 1; // +1 for 0 index } break; case(ScrollType::Paged): { - const unsigned int Page = (pos / ItemsPerPage); // page for this item + const unsigned int Page = (selectedItem / ItemsPerPage); // page for this item const unsigned int PageStart = Page * ItemsPerPage; // starting item for that page startingItem = PageStart; break; @@ -263,8 +266,8 @@ void SettingsPage::drawScrollIndicator() { } } -String SettingsPage::getButtonText(unsigned int pos) { - SettingsOption* ptr = SettingsOption::getItemAtIndex(pos); +String SettingsPage::getButtonText() { + SettingsOption* ptr = SettingsOption::getItemAtIndex(selectedItem); if (ptr == nullptr) return ""; return ptr->getModeString(); } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 6b7e431..5093610 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -64,19 +64,20 @@ class SettingsPage { public: static void pressButton(unsigned int num); - static void drawPage(unsigned int pos); - static void redraw(unsigned int pos); + static void drawPage(bool resetSelection = true); + static void redraw(); - static void drawCursor(unsigned int pos); + static void drawCursor(); static void drawScrollIndicator(); static void changeOption(unsigned int pos); - static String getButtonText(unsigned int pos); + static String getButtonText(); private: static const unsigned int ItemsPerPage = 9; // should be calculated given font size and screen space, but good enough for testing - static unsigned int startingItem; + static unsigned int startingItem; // first item on the page (indexed at 0) + static unsigned int selectedItem; // currently selected item in the list (indexed at 0) static void drawItems(); @@ -86,7 +87,7 @@ class SettingsPage { }; static const ScrollType Scroll = ScrollType::Paged; - static bool updateScroll(unsigned int pos); + static bool updateScroll(); static unsigned int lastItem() { return startingItem + ItemsPerPage - 1; } // indexed at 0 static bool onPage(unsigned int item) { return item >= startingItem && item <= lastItem(); } @@ -95,7 +96,6 @@ class SettingsPage { extern Settings set; -extern int settings_pointer; int constrainLoop(int value, int min, int max); From 5f9953dde9fcf0ead03b4ab0f4ce9cc157246b92 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 12 Jun 2021 19:07:24 -0400 Subject: [PATCH 30/37] Move related settings 'draw' functions to member This way the entire page is drawn with a call to 'draw' (something something encapsulation). --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 11 +---------- Code/Reflow_Master_v2/menu_settings.cpp | 9 ++++++--- Code/Reflow_Master_v2/menu_settings.h | 1 - 3 files changed, 7 insertions(+), 14 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index a579382..6a7c079 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1119,11 +1119,6 @@ void ShowSettings(bool resetSelection) newSettings = false; SettingsPage::drawPage(resetSelection); - - ShowButtonOptions( false ); - DrawSettingsPointer(); - - SettingsPage::drawScrollIndicator(); // needs to be redrawn on top of buttons } void ExitSettings() @@ -1443,11 +1438,7 @@ void BakeDone() void DrawSettingsPointer() { - if ( state == SETTINGS ) - { - SettingsPage::drawCursor(); - } - else if ( state == SETTINGS_PASTE ) + if ( state == SETTINGS_PASTE ) { tft.setTextColor( BLUE, BLACK ); tft.setTextSize(2); diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index e3134cc..12f848e 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -119,14 +119,14 @@ void SettingsPage::pressButton(unsigned int num) { case(2): selectedItem = constrainLoop(selectedItem - 1, 0, (int)SettingsOption::getCount() - 1); ShowButtonOptions(false); - DrawSettingsPointer(); + drawCursor(); break; // Down List case(3): selectedItem = constrainLoop(selectedItem + 1, 0, (int)SettingsOption::getCount() - 1); ShowButtonOptions(false); - DrawSettingsPointer(); + drawCursor(); break; } } @@ -146,7 +146,10 @@ void SettingsPage::drawPage(bool resetSelection) { tft.println("SETTINGS"); drawItems(); - // drawScrollIndicator(); // skipping this because it's drawn over by the button icons anyways + + ShowButtonOptions(false); + drawCursor(); + drawScrollIndicator(); // needs to be redrawn on top of buttons } void SettingsPage::redraw() { diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 5093610..ccb9db4 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -101,7 +101,6 @@ int constrainLoop(int value, int min, int max); void ExitSettings(); -void DrawSettingsPointer(); void DrawScrollIndicator(float, uint32_t); void DrawPageIndicator(unsigned int, unsigned int, uint32_t); From 7382147baca3aaaca36c39a9acf18c0d00c88853 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 12 Jun 2021 19:36:11 -0400 Subject: [PATCH 31/37] Privatize addl. exposed settings menu functions --- Code/Reflow_Master_v2/menu_settings.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index ccb9db4..bdf4996 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -65,13 +65,6 @@ class SettingsPage { static void pressButton(unsigned int num); static void drawPage(bool resetSelection = true); - static void redraw(); - - static void drawCursor(); - static void drawScrollIndicator(); - - static void changeOption(unsigned int pos); - static String getButtonText(); private: @@ -79,6 +72,13 @@ class SettingsPage { static unsigned int startingItem; // first item on the page (indexed at 0) static unsigned int selectedItem; // currently selected item in the list (indexed at 0) + static void redraw(); + + static void drawCursor(); + static void drawScrollIndicator(); + + static void changeOption(unsigned int pos); + static void drawItems(); enum class ScrollType { @@ -91,7 +91,6 @@ class SettingsPage { static unsigned int lastItem() { return startingItem + ItemsPerPage - 1; } // indexed at 0 static bool onPage(unsigned int item) { return item >= startingItem && item <= lastItem(); } - }; From 7bdfdde4a26b112a49bf7d21cafe689d9f8bf437 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 12 Jun 2021 20:55:55 -0400 Subject: [PATCH 32/37] Create ClearButton function For overwriting the button text exactly, rather than bulk clearing an area. --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 25 ++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 6a7c079..8c9499f 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1177,9 +1177,25 @@ void DrawButton(uint8_t index, const String& str, uint32_t textColor, uint32_t b tft.setTextColor(textColor, BLACK); tft.setTextSize(2); + const int XPos = tft.width() - 27; + const int YPos = buttonPosY[index] + 9; + buttonText[index] = str; // save text for reference - tft.fillRect(tft.width() - 5, buttonPosY[index], buttonWidth, buttonHeight, boxColor); // box - println_Right(tft, str, tft.width() - 27, buttonPosY[index] + 9); // text + tft.fillRect(tft.width() - 5, buttonPosY[index], buttonWidth, buttonHeight, boxColor); // color box + println_Right(tft, str, XPos, YPos); // text +} + +void ClearButton(uint8_t index, uint32_t color = BLACK); + +void ClearButton(uint8_t index, uint32_t color) +{ + tft.setTextSize(2); + tft.setTextColor(color); + + const int XPos = tft.width() - 27; + const int YPos = buttonPosY[index] + 9; + + println_Right(tft, buttonText[index], XPos, YPos); } void ShowButtonOptions( bool clearAll ) @@ -1190,8 +1206,9 @@ void ShowButtonOptions( bool clearAll ) if ( clearAll ) { // Clear All - for ( int i = 0; i < 4; i++ ) - tft.fillRect( tft.width() - 95, buttonPosY[i] - 2, 95, buttonHeight + 4, BLACK ); + for ( uint8_t i = 0; i < NumButtons; i++ ) + //tft.fillRect( tft.width() - 95, buttonPosY[i] - 2, 95, buttonHeight + 4, BLACK ); + ClearButton(i); // overwrite text exactly } if ( state == MENU ) From 4cc0ecd4ebb2c4fcb3879c282965a6c7d6d5acb2 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 21 Aug 2021 03:19:52 -0400 Subject: [PATCH 33/37] Change menu page from class to namespace These functions were all static anyways, and this better fits with the mostly functional programming at use elsewhere. --- Code/Reflow_Master_v2/menu_settings.cpp | 31 +++++++++++-- Code/Reflow_Master_v2/menu_settings.h | 59 +++++++------------------ 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 12f848e..136df17 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -4,10 +4,6 @@ template<> SettingsOption* LinkedList::head = nullptr; -unsigned int SettingsPage::startingItem = 0; -unsigned int SettingsPage::selectedItem = 0; - - SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m) : ItemName(name), ItemDescription(desc), @@ -100,6 +96,33 @@ String SettingsOption::getModeString() const { return ""; // invalid } +namespace SettingsPage { + enum class ScrollType { + Smooth, // at the end of current page, moves all items up by one + Paged, // at the end of the current page, draws an entire new page of items + }; + + static const unsigned int ItemsPerPage = 9; // should be calculated given font size and screen space, but good enough for now + static unsigned int startingItem = 0; // first item on the page (indexed at 0) + static unsigned int selectedItem = 0; // currently selected item in the list (indexed at 0) + + static const ScrollType Scroll = ScrollType::Paged; + + unsigned int lastItem() { return startingItem + ItemsPerPage - 1; } // index of the last item in the list, indexed at 0 + bool onPage(unsigned int item) { return item >= startingItem && item <= lastItem(); } // returns 'true' if an item (index N) is on the page + + void redraw(); // redraw the current page after a selection update + + void drawCursor(); // draws the '>' cursor, and redraws the page / description if necessary + void drawScrollIndicator(); // draw the scroll indicator between buttons 3/4 + + void changeOption(unsigned int pos); // runs the "change this option" function for the selected option + + void drawItems(); // draw the item names and values across the page + + bool updateScroll(); // recalculate scroll position and items on the screen +} + void SettingsPage::pressButton(unsigned int num) { switch (num) { diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index bdf4996..12cca28 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -3,7 +3,19 @@ #include "tft_display.h" #include "linked_list.h" -// Save data struct +// Forward-declare functions used in the menu +int constrainLoop(int value, int min, int max); + +void ExitSettings(); + +void DrawScrollIndicator(float, uint32_t); +void DrawPageIndicator(unsigned int, unsigned int, uint32_t); + +void ShowButtonOptions(bool clearAll); + +void println_Center(Adafruit_ILI9341& d, String heading, int centerX, int centerY); + +// define settings data struct typedef struct { boolean valid = true; boolean useFan = false; @@ -60,49 +72,12 @@ class SettingsOption : public LinkedList { String lastValue; }; -class SettingsPage { -public: - static void pressButton(unsigned int num); - - static void drawPage(bool resetSelection = true); - static String getButtonText(); - -private: - static const unsigned int ItemsPerPage = 9; // should be calculated given font size and screen space, but good enough for testing - static unsigned int startingItem; // first item on the page (indexed at 0) - static unsigned int selectedItem; // currently selected item in the list (indexed at 0) - - static void redraw(); +namespace SettingsPage { + void pressButton(unsigned int num); // record a button press on the settings page - static void drawCursor(); - static void drawScrollIndicator(); - - static void changeOption(unsigned int pos); - - static void drawItems(); - - enum class ScrollType { - Smooth, // at the end of current page, moves all items up by one - Paged, // at the end of the current page, draws an entire new page of items - }; - static const ScrollType Scroll = ScrollType::Paged; - - static bool updateScroll(); - - static unsigned int lastItem() { return startingItem + ItemsPerPage - 1; } // indexed at 0 - static bool onPage(unsigned int item) { return item >= startingItem && item <= lastItem(); } + void drawPage(bool resetSelection = true); // draw the Settings page in its entirety + String getButtonText(); // get the string of text to describe button 0 }; extern Settings set; - -int constrainLoop(int value, int min, int max); - -void ExitSettings(); - -void DrawScrollIndicator(float, uint32_t); -void DrawPageIndicator(unsigned int, unsigned int, uint32_t); - -void ShowButtonOptions(bool clearAll); - -void println_Center(Adafruit_ILI9341& d, String heading, int centerX, int centerY); From f22c4eb3b08c715a002861cd733ac2a764be5e13 Mon Sep 17 00:00:00 2001 From: David Madison Date: Sat, 21 Aug 2021 03:30:13 -0400 Subject: [PATCH 34/37] Move SettingsOption variables to private Better encapsulation yada yada --- Code/Reflow_Master_v2/menu_settings.cpp | 20 ++++++------- Code/Reflow_Master_v2/menu_settings.h | 28 ++++++++++--------- .../menu_settings_options.cpp | 2 ++ 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 136df17..3bd5b01 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -6,9 +6,9 @@ SettingsOption* LinkedList::head = nullptr; SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m) : + Mode(m), ItemName(name), ItemDescription(desc), - getFunction(get), setFunction(set), - Mode(m) + getFunction(get), setFunction(set) { LinkedList::add(this); } @@ -18,6 +18,13 @@ SettingsOption::~SettingsOption() LinkedList::remove(this); } +bool SettingsOption::changeValue() { + if (this->setFunction != nullptr) { + this->setFunction(); + } + return (Mode == OptionMode::Change); // 'true' if we're changing and want to redraw this element +} + unsigned long SettingsOption::getYPosition(unsigned int index) { return (ItemHeight * index) + ItemStartY; // y coordinate on center } @@ -231,15 +238,8 @@ void SettingsPage::changeOption(unsigned int pos) { SettingsOption* ptr = SettingsOption::getItemAtIndex(pos); if (ptr == nullptr) return; - ptr->setFunction(); - - switch (ptr->Mode) { - case(OptionMode::Select): - // do nothing here, we're loading a new menu instead - break; - case(OptionMode::Change): + if (ptr->changeValue()) { ptr->drawValue(SettingsOption::getPositionOf(ptr) - startingItem); - break; } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 12cca28..2ed9566 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -34,29 +34,23 @@ typedef struct { } Settings; -enum class OptionMode { - Select, - Change, -}; - class SettingsOption : public LinkedList { public: + enum class OptionMode { + Select, + Change, + }; + friend LinkedList; typedef String(*MenuGetFunc)(); typedef void (*MenuSetFunc)(); - const String ItemName; - const String ItemDescription; - - const MenuGetFunc getFunction; - const MenuSetFunc setFunction; - - const OptionMode Mode; - SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m); ~SettingsOption(); + bool changeValue(); // returns 'true' if we need to redraw + static unsigned long getYPosition(unsigned int index); String getModeString() const; @@ -69,6 +63,14 @@ class SettingsOption : public LinkedList { static const unsigned int ItemStartX = 20; static const unsigned int ItemStartY = 45; + const OptionMode Mode; + + const String ItemName; + const String ItemDescription; + + const MenuGetFunc getFunction; + const MenuSetFunc setFunction; + String lastValue; }; diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index d0d7801..a1e67c8 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -3,6 +3,8 @@ void ShowPaste(); void ShowResetDefaults(); +using OptionMode = SettingsOption::OptionMode; + // "Switch Paste" menu option String getSwitchPaste() { return ""; From 06ba614cbdfcefd5c61255ec370db25628e2fe39 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 21 Oct 2021 04:00:05 -0400 Subject: [PATCH 35/37] Use polymorphism for setting option types --- Code/Reflow_Master_v2/menu_settings.cpp | 22 ++------- Code/Reflow_Master_v2/menu_settings.h | 45 ++++++++++++++----- .../menu_settings_options.cpp | 24 +++++----- 3 files changed, 49 insertions(+), 42 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 3bd5b01..8fe43e8 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -4,9 +4,8 @@ template<> SettingsOption* LinkedList::head = nullptr; -SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m) +SettingsOption::SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set) : - Mode(m), ItemName(name), ItemDescription(desc), getFunction(get), setFunction(set) { @@ -18,11 +17,11 @@ SettingsOption::~SettingsOption() LinkedList::remove(this); } -bool SettingsOption::changeValue() { +bool SettingsOption::modify() { if (this->setFunction != nullptr) { this->setFunction(); } - return (Mode == OptionMode::Change); // 'true' if we're changing and want to redraw this element + return refreshOnModify(); } unsigned long SettingsOption::getYPosition(unsigned int index) { @@ -90,19 +89,6 @@ void SettingsOption::drawDescription() { println_Center(tft, this->ItemDescription, tft.width() / 2, textPosY); } -String SettingsOption::getModeString() const { - switch (Mode) - { - case(OptionMode::Select): - return "SELECT"; - break; - case(OptionMode::Change): - return "CHANGE"; - break; - } - return ""; // invalid -} - namespace SettingsPage { enum class ScrollType { Smooth, // at the end of current page, moves all items up by one @@ -238,7 +224,7 @@ void SettingsPage::changeOption(unsigned int pos) { SettingsOption* ptr = SettingsOption::getItemAtIndex(pos); if (ptr == nullptr) return; - if (ptr->changeValue()) { + if (ptr->modify()) { ptr->drawValue(SettingsOption::getPositionOf(ptr) - startingItem); } } diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 2ed9566..59016f1 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -36,35 +36,30 @@ typedef struct { class SettingsOption : public LinkedList { public: - enum class OptionMode { - Select, - Change, - }; - friend LinkedList; typedef String(*MenuGetFunc)(); typedef void (*MenuSetFunc)(); - SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set, OptionMode m); - ~SettingsOption(); + SettingsOption(const String& name, const String& desc, MenuGetFunc get, MenuSetFunc set); + virtual ~SettingsOption(); - bool changeValue(); // returns 'true' if we need to redraw + bool modify(); static unsigned long getYPosition(unsigned int index); - String getModeString() const; + virtual String getModeString() const = 0; void drawItem(unsigned int posY); void drawValue(unsigned int posY); void drawDescription(); private: + virtual bool refreshOnModify() { return true; } + static const unsigned int ItemHeight = 19; static const unsigned int ItemStartX = 20; static const unsigned int ItemStartY = 45; - const OptionMode Mode; - const String ItemName; const String ItemDescription; @@ -74,6 +69,34 @@ class SettingsOption : public LinkedList { String lastValue; }; + +class SettingsOptionLink : public SettingsOption { +public: + using SettingsOption::SettingsOption; + + String getModeString() const { return "SELECT"; } + +private: + // don't refresh the menu page on modify because we're + // moving to a different page entirely + bool refreshOnModify() { return false; } +}; + +class SettingsOptionAdjust : public SettingsOption { +public: + using SettingsOption::SettingsOption; + + String getModeString() const { return "CHANGE"; } +}; + +class SettingsOptionToggle : public SettingsOption { +public: + using SettingsOption::SettingsOption; + + String getModeString() const { return "TOGGLE"; } +}; + + namespace SettingsPage { void pressButton(unsigned int num); // record a button press on the settings page diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index a1e67c8..3994d21 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -3,8 +3,6 @@ void ShowPaste(); void ShowResetDefaults(); -using OptionMode = SettingsOption::OptionMode; - // "Switch Paste" menu option String getSwitchPaste() { return ""; @@ -14,7 +12,7 @@ void changeSwitchPaste() { ShowPaste(); } -SettingsOption OptionPasteMenu("SWITCH PASTE", "Select which profile to reflow", getSwitchPaste, changeSwitchPaste, OptionMode::Select); +SettingsOptionLink OptionPasteMenu("SWITCH PASTE", "Select which profile to reflow", getSwitchPaste, changeSwitchPaste); // "Use Fan" menu option @@ -26,7 +24,7 @@ void changeUseFan() { set.useFan = !set.useFan; } -SettingsOption OptionUseFan("USE FAN", "Enable fan for end of reflow, requires 5V DC fan", getUseFan, changeUseFan, OptionMode::Change); +SettingsOptionToggle OptionUseFan("USE FAN", "Enable fan for end of reflow, requires 5V DC fan", getUseFan, changeUseFan); // "Fan Countdown" menu option @@ -40,7 +38,7 @@ void changeFanCountdown() { set.fanTimeAfterReflow = 0; } -SettingsOption OptionFanCountdown("FAN COUNTDOWN", "Keep fan on for XXX sec after reflow", getFanCountdown, changeFanCountdown, OptionMode::Change); +SettingsOptionAdjust OptionFanCountdown("FAN COUNTDOWN", "Keep fan on for XXX sec after reflow", getFanCountdown, changeFanCountdown); // "Graph Look Ahead" menu option @@ -54,7 +52,7 @@ void changeGraphLookAhead() { set.lookAhead = 1; } -SettingsOption OptionGraphLookAhead("GRAPH LOOK AHEAD", "Soak and Reflow look ahead for rate change speed", getGraphLookAhead, changeGraphLookAhead, OptionMode::Change); +SettingsOptionAdjust OptionGraphLookAhead("GRAPH LOOK AHEAD", "Soak and Reflow look ahead for rate change speed", getGraphLookAhead, changeGraphLookAhead); // "Power" menu option @@ -68,7 +66,7 @@ void changePower() { set.power = 0.5; } -SettingsOption OptionPower("POWER", "Adjust the power boost", getPower, changePower, OptionMode::Change); +SettingsOptionAdjust OptionPower("POWER", "Adjust the power boost", getPower, changePower); // "Temp Offset" menu option @@ -82,7 +80,7 @@ void changeTempOffset() { set.tempOffset = -15; } -SettingsOption OptionTempOffset("TEMP OFFSET", "Adjust temp probe reading offset", getTempOffset, changeTempOffset, OptionMode::Change); +SettingsOptionAdjust OptionTempOffset("TEMP OFFSET", "Adjust temp probe reading offset", getTempOffset, changeTempOffset); // "Start Ramp 100%" menu option @@ -94,7 +92,7 @@ void changeStartFullBlast() { set.startFullBlast = !set.startFullBlast; } -SettingsOption OptionStartFullBlast("START RAMP 100%", "Force full power on initial ramp-up - be careful!", getStartFullBlast, changeStartFullBlast, OptionMode::Change); +SettingsOptionToggle OptionStartFullBlast("START RAMP 100%", "Force full power on initial ramp-up - be careful!", getStartFullBlast, changeStartFullBlast); // "Bake Temp Gap" menu option @@ -108,7 +106,7 @@ void changeBakeTempGap() { set.bakeTempGap = 0; } -SettingsOption OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, higher for more mass", getBakeTempGap, changeBakeTempGap, OptionMode::Change); +SettingsOptionAdjust OptionBakeTempGap("BAKE TEMP GAP", "Bake thermal mass adjustment, higher for more mass", getBakeTempGap, changeBakeTempGap); // "Key Tone" menu option @@ -120,7 +118,7 @@ void setKeyToneSetting() { set.keyTone = !set.keyTone; } -SettingsOption OptionKeyTone("KEY TONE", "Make a noise whenever a button is pressed", getKeyToneSetting, setKeyToneSetting, OptionMode::Change); +SettingsOptionToggle OptionKeyTone("KEY TONE", "Make a noise whenever a button is pressed", getKeyToneSetting, setKeyToneSetting); // "Disable Buzzer" menu option @@ -132,7 +130,7 @@ void setBuzzerSetting() { set.beep = !set.beep; } -SettingsOption OptionBuzzer("DISABLE BUZZER", "Disable buzzer noise in ALL modes", getBuzzerSetting, setBuzzerSetting, OptionMode::Change); +SettingsOptionToggle OptionBuzzer("DISABLE BUZZER", "Disable buzzer noise in ALL modes", getBuzzerSetting, setBuzzerSetting); // ############################################################################ @@ -146,4 +144,4 @@ void goToResetDefaults() { ShowResetDefaults(); } -SettingsOption OptionResetToDefaults("RESET TO DEFAULTS", "Reset to default settings", getResetToDefaults, goToResetDefaults, OptionMode::Select); +SettingsOptionLink OptionResetToDefaults("RESET TO DEFAULTS", "Reset to default settings", getResetToDefaults, goToResetDefaults); From ce358a09926e85d034e69c939be0e169c6cc2a12 Mon Sep 17 00:00:00 2001 From: David Madison Date: Thu, 21 Oct 2021 04:38:05 -0400 Subject: [PATCH 36/37] Add startup tune option (on by default) --- Code/Reflow_Master_v2/Reflow_Master_v2.ino | 1 + Code/Reflow_Master_v2/menu_settings.h | 1 + Code/Reflow_Master_v2/menu_settings_options.cpp | 12 ++++++++++++ 3 files changed, 14 insertions(+) diff --git a/Code/Reflow_Master_v2/Reflow_Master_v2.ino b/Code/Reflow_Master_v2/Reflow_Master_v2.ino index 8c9499f..1d86570 100644 --- a/Code/Reflow_Master_v2/Reflow_Master_v2.ino +++ b/Code/Reflow_Master_v2/Reflow_Master_v2.ino @@ -1021,6 +1021,7 @@ void Buzzer( int hertz, int len ) // Startup Tune void BuzzerStart() { + if (!set.startupTune) return; tone( BUZZER, 262, 200); delay(210); tone( BUZZER, 523, 100); diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 59016f1..49c93b4 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -31,6 +31,7 @@ typedef struct { bool startFullBlast = false; bool beep = true; bool keyTone = true; + bool startupTune = true; } Settings; diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index 3994d21..7d4bfe6 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -133,6 +133,18 @@ void setBuzzerSetting() { SettingsOptionToggle OptionBuzzer("DISABLE BUZZER", "Disable buzzer noise in ALL modes", getBuzzerSetting, setBuzzerSetting); +// "Startup Tone" menu option +String getStartupTuneSetting() { + return set.startupTune ? "ON" : "OFF"; +} + +void setStartupTuneSetting() { + set.startupTune = !set.startupTune; +} + +SettingsOptionToggle OptionStartupTune("STARTUP TUNE", "Play a little song on startup", getStartupTuneSetting, setStartupTuneSetting); + + // ############################################################################ // "Reset to defaults" menu option From bb97bbba109e2171e8752c7ba3fd14acfd42f7a1 Mon Sep 17 00:00:00 2001 From: David Madison Date: Mon, 25 Oct 2021 04:22:57 -0400 Subject: [PATCH 37/37] Remove redundant functions for option links Handling nullptr for the 'get' function, and going directly to the 'show' pages rather than using a helper. --- Code/Reflow_Master_v2/menu_settings.cpp | 8 ++++++++ Code/Reflow_Master_v2/menu_settings.h | 2 +- .../menu_settings_options.cpp | 20 ++----------------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/Code/Reflow_Master_v2/menu_settings.cpp b/Code/Reflow_Master_v2/menu_settings.cpp index 8fe43e8..664e8ff 100644 --- a/Code/Reflow_Master_v2/menu_settings.cpp +++ b/Code/Reflow_Master_v2/menu_settings.cpp @@ -49,6 +49,8 @@ void SettingsOption::drawItem(unsigned int position) { } void SettingsOption::drawValue(unsigned int position) { + if (getFunction == nullptr) return; // no string, so no need to draw it + const unsigned int yPos = getYPosition(position); int16_t nameX, dummyY; @@ -89,6 +91,12 @@ void SettingsOption::drawDescription() { println_Center(tft, this->ItemDescription, tft.width() / 2, textPosY); } + +SettingsOptionLink::SettingsOptionLink(const String& name, const String& desc, MenuSetFunc set) + // skipping over the 'get' function + : SettingsOption(name, desc, nullptr, set) {} + + namespace SettingsPage { enum class ScrollType { Smooth, // at the end of current page, moves all items up by one diff --git a/Code/Reflow_Master_v2/menu_settings.h b/Code/Reflow_Master_v2/menu_settings.h index 49c93b4..cb364b6 100644 --- a/Code/Reflow_Master_v2/menu_settings.h +++ b/Code/Reflow_Master_v2/menu_settings.h @@ -73,7 +73,7 @@ class SettingsOption : public LinkedList { class SettingsOptionLink : public SettingsOption { public: - using SettingsOption::SettingsOption; + SettingsOptionLink(const String& name, const String& desc, MenuSetFunc set); String getModeString() const { return "SELECT"; } diff --git a/Code/Reflow_Master_v2/menu_settings_options.cpp b/Code/Reflow_Master_v2/menu_settings_options.cpp index 7d4bfe6..85a383a 100644 --- a/Code/Reflow_Master_v2/menu_settings_options.cpp +++ b/Code/Reflow_Master_v2/menu_settings_options.cpp @@ -4,15 +4,7 @@ void ShowPaste(); void ShowResetDefaults(); // "Switch Paste" menu option -String getSwitchPaste() { - return ""; -} - -void changeSwitchPaste() { - ShowPaste(); -} - -SettingsOptionLink OptionPasteMenu("SWITCH PASTE", "Select which profile to reflow", getSwitchPaste, changeSwitchPaste); +SettingsOptionLink OptionPasteMenu("SWITCH PASTE", "Select which profile to reflow", ShowPaste); // "Use Fan" menu option @@ -148,12 +140,4 @@ SettingsOptionToggle OptionStartupTune("STARTUP TUNE", "Play a little song on st // ############################################################################ // "Reset to defaults" menu option -String getResetToDefaults() { - return ""; -} - -void goToResetDefaults() { - ShowResetDefaults(); -} - -SettingsOptionLink OptionResetToDefaults("RESET TO DEFAULTS", "Reset to default settings", getResetToDefaults, goToResetDefaults); +SettingsOptionLink OptionResetToDefaults("RESET TO DEFAULTS", "Reset to default settings", ShowResetDefaults);