Skip to content

Add Arduino Micro compatibility fixes#65

Open
WRH2000 wants to merge 1 commit intoVail-CW:masterfrom
WRH2000:Vail-adapter-for-Arduino-Micro
Open

Add Arduino Micro compatibility fixes#65
WRH2000 wants to merge 1 commit intoVail-CW:masterfrom
WRH2000:Vail-adapter-for-Arduino-Micro

Conversation

@WRH2000
Copy link
Copy Markdown

@WRH2000 WRH2000 commented Apr 14, 2026

This PR adds Arduino Micro compatibility changes for the Vail Adapter sketch.

Changes include:

  • disabled capacitive touch for AVR/ATmega32U4 builds
  • replaced SAMD-specific dependencies where needed
  • adjusted buzzer behavior for Arduino Micro testing
  • reduced memory usage to fit Arduino Micro limits
  • updated config for Arduino Micro pin assignments

Notes:

  • capacitive touch is disabled on Arduino Micro
  • this target is memory-constrained and may still have limitations compared to SAMD21 boards

Summary by Sourcery

Add Arduino Micro–specific configuration and memory optimizations, replacing SAMD-only features and adapting audio, touch, and keyer timing to work on AVR/ATmega32U4.

New Features:

  • Introduce an Arduino Micro hardware profile with dedicated pin mappings and board name.

Bug Fixes:

  • Ensure keyer timing and Tick interfaces use unsigned long millis to match Arduino millis() semantics and avoid overflow-related issues on AVR.

Enhancements:

  • Store equal temperament frequency table in PROGMEM and access it via a macro to reduce SRAM usage on AVR boards.
  • Simplify PolyBuzzer to a single tone slot and adjust its behavior and logging for Arduino Micro constraints.
  • Guard capacitive-touch support behind a NO_CAPACITIVE_TOUCH flag so it is excluded for boards like Arduino Micro.
  • Replace SAMD-specific FlashStorage usage with standard Arduino EEPROM APIs for settings and memory storage.
  • Use PROGMEM-safe accessors for all tone-generation paths so audio features work correctly with the new frequency storage.
  • Clean up configuration macros, comments, and includes for better portability across board types without unused variants.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 14, 2026

Reviewer's Guide

This PR adds Arduino Micro (AVR/ATmega32U4) compatibility by moving note tables into PROGMEM, switching from SAMD FlashStorage to AVR EEPROM, simplifying the buzzer to a single tone slot, disabling capacitive touch for this target, and introducing an Arduino-Micro-specific config with adjusted pin/LED behavior and timing types.

Sequence diagram for saving settings to EEPROM on Arduino Micro

sequenceDiagram
  actor User
  participant VailAdapter
  participant SettingsEEPROM as settings_eeprom
  participant EEPROMLib as EEPROM

  User->>VailAdapter: Change configuration (keyer type, dit duration, tx note)
  VailAdapter->>SettingsEEPROM: saveSettingsToEEPROM(keyerType, ditDuration, txNote)
  SettingsEEPROM->>EEPROMLib: EEPROM.write(EEPROM_KEYER_TYPE_ADDR, keyerType)
  SettingsEEPROM->>EEPROMLib: EEPROM.put(EEPROM_DIT_DURATION_ADDR, ditDuration)
  SettingsEEPROM->>EEPROMLib: EEPROM.write(EEPROM_TX_NOTE_ADDR, txNote)
  SettingsEEPROM->>EEPROMLib: EEPROM.write(EEPROM_VALID_FLAG_ADDR, EEPROM_VALID_VALUE)
  Note over SettingsEEPROM,EEPROMLib: No EEPROM.commit call on AVR
  SettingsEEPROM-->>VailAdapter: return
  VailAdapter-->>User: Settings persisted across reset
Loading

Class diagram for updated PolyBuzzer and keyer timing

classDiagram
  class PolyBuzzer {
    +unsigned int tones[POLYBUZZER_MAX_TONES]
    +unsigned int playing
    +uint8_t pin
    +PolyBuzzer(uint8_t pin)
    +void update()
    +void Tone(int slot, unsigned int frequency)
    +void Note(int slot, uint8_t note)
    +void NoTone(int slot)
  }

  class TouchBounce {
    +void attach(int pin, int pressThreshold, int releaseThreshold)
    +bool readCurrentState()
    +Adafruit_FreeTouch qt
    +bool lastState
    +int pressThreshold
    +int releaseThreshold
  }

  class Bounce {
  }

  class Transmitter {
    +virtual void BeginTx()
    +virtual void EndTx()
    +virtual void BeginTx(int relay)
    +virtual void EndTx(int relay)
  }

  class Keyer {
    +Transmitter* output
    +virtual void Tx(int relay, bool closed)
    +virtual void Key(Paddle key, bool pressed)
    +virtual void Tick(unsigned long millis)
  }

  class StraightKeyer {
    +virtual void Key(Paddle key, bool pressed)
    +virtual void Tick(unsigned long millis)
  }

  class BugKeyer {
    +unsigned long nextPulse
    +bool keyPressed[2]
    +virtual void Key(Paddle key, bool pressed)
    +virtual void Tick(unsigned long millis)
    +virtual void pulse(unsigned long millis)
  }

  class ElBugKeyer {
    +virtual void pulse(unsigned long millis)
  }

  class VailAdapter {
    +void Tick(unsigned long currentMillis)
    +void DisableBuzzer()
    +bool ditIsHeld
    +unsigned long ditHoldStartTime
    +bool buzzerEnabled
  }

  Bounce <|-- TouchBounce
  Transmitter <|-- VailAdapter
  Keyer <|-- StraightKeyer
  StraightKeyer <|-- BugKeyer
  BugKeyer <|-- ElBugKeyer
  VailAdapter --> PolyBuzzer

  class EqualTemperamentTable {
    +static const uint16_t equalTemperamentNote[128]
    +uint16_t GET_EQUAL_TEMPERAMENT_NOTE(uint8_t n)
  }
Loading

Class diagram for TouchBounce conditional compilation and thresholds

classDiagram
  class TouchBounce {
    +void attach(int pin, int pressThreshold, int releaseThreshold)
    +bool readCurrentState()
    +Adafruit_FreeTouch qt
    +bool lastState
    +int pressThreshold
    +int releaseThreshold
  }

  class Bounce {
  }

  class ConfigMacros {
    +#define NO_CAPACITIVE_TOUCH
    +#define QT_DIT_THRESHOLD_PRESS 450
    +#define QT_DIT_THRESHOLD_RELEASE 360
    +#define QT_DAH_THRESHOLD_PRESS 450
    +#define QT_DAH_THRESHOLD_RELEASE 360
  }

  Bounce <|-- TouchBounce
  ConfigMacros ..> TouchBounce
Loading

Class diagram for EEPROM-based settings storage

classDiagram
  class VailAdapter {
    +uint8_t getKeyerType()
    +uint16_t getDitDuration()
    +uint8_t getTxNote()
    +bool getRadioKeyerMode()
  }

  class SettingsEEPROM {
    +void saveSettingsToEEPROM(uint8_t keyerType, uint16_t ditDuration, uint8_t txNote)
    +void saveRadioKeyerModeToEEPROM(bool radioKeyerMode)
    +void loadSettingsFromEEPROM(VailAdapter& adapter)
    +void saveMemoryToEEPROM(uint8_t slotNumber, const CWMemory& memory)
    +void clearMemoryInEEPROM(uint8_t slotNumber)
  }

  class EEPROMLib {
    +uint8_t read(int address)
    +void write(int address, uint8_t value)
    +template<typename T> void put(int address, const T& value)
  }

  class CWMemory {
    +uint16_t transitionCount
    +uint16_t transitions[64]
  }

  VailAdapter --> SettingsEEPROM
  SettingsEEPROM --> EEPROMLib
  SettingsEEPROM --> CWMemory
Loading

File-Level Changes

Change Details Files
Store equal temperament frequency table in flash and expose a macro for safe access on AVR
  • Replace large RAM-resident equalTemperamentNote int array with a compact uint16_t PROGMEM array
  • Include Arduino.h and avr/pgmspace.h to support PROGMEM on AVR
  • Add GET_EQUAL_TEMPERAMENT_NOTE(n) macro using pgm_read_word for reading from program memory
equal_temperament.h
Introduce Arduino Micro-specific configuration and simplify global config for this target
  • Remove multi-board config switches and define a fixed Arduino Micro configuration with DIT/DAH/KEY/PIEZO pin assignments
  • Define NO_CAPACITIVE_TOUCH and NO_LED flags appropriate for the Arduino Micro build, plus BOARD_NAME
  • Retain optional RADIO_* pin definitions behind comments and keep RADIO_KEYING_ACTIVE_LOW semantics
config.h
Simplify PolyBuzzer to a monophonic, single-slot implementation suitable for AVR
  • Reduce POLYBUZZER_MAX_TONES from 2 to 1 and remove debug print helper to save memory
  • Update PolyBuzzer::update, Tone, Note, and NoTone to operate only on slot 0, ignoring other slots
  • Use GET_EQUAL_TEMPERAMENT_NOTE instead of indexing the raw array, and wrap debug strings in F() for flash storage
polybuzzer.h
polybuzzer.cpp
equal_temperament.h
Disable capacitive touch on AVR builds while keeping existing touch behavior behind a guard
  • Include config.h and wrap TouchBounce class and implementation with #ifndef NO_CAPACITIVE_TOUCH so it is omitted for Arduino Micro
  • Preserve FreeTouch hysteresis thresholds with slightly cleaned-up defines
touchbounce.h
touchbounce.cpp
vail-adapter.ino
Replace SAMD FlashStorage-based settings persistence with AVR EEPROM and remove unnecessary commits
  • Swap FlashStorage_SAMD include for Arduino.h and EEPROM.h
  • Use EEPROM.get/put/read/write APIs for settings and memory slot persistence
  • Comment out EEPROM.commit() calls, which are not needed on AVR EEPROM
settings_eeprom.cpp
Use PROGMEM-backed frequency lookup macro throughout audio code
  • Replace equalTemperamentNote[...] access with GET_EQUAL_TEMPERAMENT_NOTE(...) in morse_audio tone-generating functions
  • Propagate frequency via local variable before calling tone() for clarity
morse_audio.cpp
Make timing-related APIs use unsigned long millis() to match Arduino core and avoid overflow issues
  • Change Tick method signatures in Keyer, StraightKeyer, BugKeyer, ElBugKeyer, and VailAdapter from unsigned int to unsigned long
  • Update nextPulse/nextRepeat time-keeping members to unsigned long
  • Update loop() to use unsigned long currentTime = millis()
keyers.h
keyers.cpp
adapter.h
adapter.cpp
vail-adapter.ino
Minor AVR-oriented cleanups and compatibility fixes
  • Include config.h in touchbounce to share NO_CAPACITIVE_TOUCH flag and other config
  • Replace with <stddef.h> for better AVR toolchain compatibility
  • Comment out Adafruit_FreeTouch include in the main sketch since it is unused when NO_CAPACITIVE_TOUCH is set
touchbounce.cpp
touchbounce.h
adapter.cpp
vail-adapter.ino

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues, and left some high level feedback:

  • The change to POLYBUZZER_MAX_TONES = 1 and ignoring slots other than 0 in PolyBuzzer applies globally; if you still want polyphonic/prioritized tones on non-AVR targets, consider wrapping the single-slot behavior in an #ifdef (e.g., #ifdef ARDUINO_AVR_MICRO) rather than changing the class semantics for all boards.
  • In config.h the previous board-specific configurations have been replaced by an Arduino Micro–only setup; if you intend to keep supporting the earlier QT Py / PCB variants, it might be cleaner to introduce a dedicated ARDUINO_MICRO config branch instead of removing the existing ones outright.
  • The call to DisableBuzzer() in VailAdapter::Tick is now commented out, which changes long-press behavior on all platforms; consider using a compile-time flag (e.g., #ifdef ARDUINO_AVR_MICRO) or a runtime setting so memory-constrained boards can opt out without altering behavior for other targets.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The change to `POLYBUZZER_MAX_TONES` = 1 and ignoring slots other than 0 in `PolyBuzzer` applies globally; if you still want polyphonic/prioritized tones on non-AVR targets, consider wrapping the single-slot behavior in an `#ifdef` (e.g., `#ifdef ARDUINO_AVR_MICRO`) rather than changing the class semantics for all boards.
- In `config.h` the previous board-specific configurations have been replaced by an Arduino Micro–only setup; if you intend to keep supporting the earlier QT Py / PCB variants, it might be cleaner to introduce a dedicated `ARDUINO_MICRO` config branch instead of removing the existing ones outright.
- The call to `DisableBuzzer()` in `VailAdapter::Tick` is now commented out, which changes long-press behavior on all platforms; consider using a compile-time flag (e.g., `#ifdef ARDUINO_AVR_MICRO`) or a runtime setting so memory-constrained boards can opt out without altering behavior for other targets.

## Individual Comments

### Comment 1
<location path="equal_temperament.h" line_range="5" />
<code_context>
-    11181, // 125
-    11845, // 126
-    12550, // 127
+static const uint16_t equalTemperamentNote[] PROGMEM = {
+  8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,
+  20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,49,
</code_context>
<issue_to_address>
**suggestion (performance):** Using `static` in the header will duplicate the lookup table into every translation unit

Declaring this table as `static const` in the header gives each including `.cpp` its own flash/PROGMEM copy, which is wasteful on small AVR devices. Instead, declare it `extern` in the header and define it once in a `.cpp`:

```c++
// equal_temperament.h
extern const uint16_t equalTemperamentNote[] PROGMEM;

// equal_temperament.cpp
#include <Arduino.h>
#include <avr/pgmspace.h>
const uint16_t equalTemperamentNote[] PROGMEM = { ... };
```

`GET_EQUAL_TEMPERAMENT_NOTE` will still work unchanged with the `extern` declaration.

Suggested implementation:

```c
extern const uint16_t equalTemperamentNote[] PROGMEM;

#define GET_EQUAL_TEMPERAMENT_NOTE(n) pgm_read_word(&equalTemperamentNote[(n)])

```

` since that file isn't shown).

Here are the edits to `equal_temperament.h`:

```xml
<file_operations>
<file_operation operation="edit" file_path="equal_temperament.h">
<<<<<<< SEARCH
static const uint16_t equalTemperamentNote[] PROGMEM = {
  8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,
  20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,49,
  51,55,58,61,65,69,73,77,82,87,92,98,103,110,116,123,
  130,138,146,155,164,174,185,196,207,220,233,247,261,277,293,311,
  329,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,
  831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1662,1760,1865,1976,
  2094,2218,2350,2490,2638,2795,2961,3137,3324,3521,3731,3953,4188,4437,4701,4980,
  5276,5590,5922,6275,6648,7043,7462,7906,8376,8874,9402,9961,10553,11181,11845,12550
};

#define GET_EQUAL_TEMPERAMENT_NOTE(n) pgm_read_word(&equalTemperamentNote[(n)])
=======
extern const uint16_t equalTemperamentNote[] PROGMEM;

#define GET_EQUAL_TEMPERAMENT_NOTE(n) pgm_read_word(&equalTemperamentNote[(n)])
>>>>>>> REPLACE
</file_operation>
</file_operations>
```

<additional_changes>
1. Add a new implementation file `equal_temperament.cpp` with the single definition of the lookup table:

```c++
#include <Arduino.h>
#include <avr/pgmspace.h>
#include "equal_temperament.h"

const uint16_t equalTemperamentNote[] PROGMEM = {
  8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,
  20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,49,
  51,55,58,61,65,69,73,77,82,87,92,98,103,110,116,123,
  130,138,146,155,164,174,185,196,207,220,233,247,261,277,293,311,
  329,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,
  831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1662,1760,1865,1976,
  2094,2218,2350,2490,2638,2795,2961,3137,3324,3521,3731,3953,4188,4437,4701,4980,
  5276,5590,5922,6275,6648,7043,7462,7906,8376,8874,9402,9961,10553,11181,11845,12550
};
```

2. Ensure `equal_temperament.cpp` is compiled/linked as part of the project so the `equalTemperamentNote` symbol is available to all translation units that include `equal_temperament.h`.
</issue_to_address>

### Comment 2
<location path="polybuzzer.cpp" line_range="31" />
<code_context>
-    
-    this->tones[slot] = frequency;
-    this->update();
+  if (slot != 0) return;  // ignore extra slots on Micro
+
+  Serial.print(F("Setting tone in slot "));
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Silently ignoring `slot != 0` can hide logic bugs at call sites

Calls with `slot != 0` effectively do nothing while still appearing to succeed, which can be confusing for callers that expect multiple slots. Consider either clamping `slot` to 0 or adding a debug-only warning (and then clamping) so that misuse is visible during development instead of silently dropping tones.

Suggested implementation:

```cpp
void PolyBuzzer::Tone(int slot, unsigned int frequency) {
  int clampedSlot = slot;
  if (slot != 0) {
#ifdef DEBUG
    Serial.print(F("PolyBuzzer::Tone: requested slot "));
    Serial.print(slot);
    Serial.println(F(" not supported on Micro; clamping to slot 0"));
#endif
    clampedSlot = 0;
  }

  Serial.print(F("Setting tone in slot "));
  Serial.print(clampedSlot);
  Serial.print(F(" to frequency: "));
  Serial.println(frequency);

  this->tones[clampedSlot] = frequency;
  this->update();
}

```

1. Ensure that `DEBUG` (or whatever debug macro is appropriate for this project) is defined in your build system or a common header to enable the warning during development.
2. If the project uses a different debug macro (e.g. `DEBUG_POLYBUZZER`, `SERIAL_DEBUG`, etc.), replace `#ifdef DEBUG` with the project-standard macro for conditional debug logging.
</issue_to_address>

### Comment 3
<location path="adapter.cpp" line_range="835" />
<code_context>
         Serial.print("Dit held for ");
         Serial.print(holdTime);
         Serial.println("ms - disabling buzzer");
-        this->DisableBuzzer();
+        //this->DisableBuzzer();
         this->ditIsHeld = false; // Reset to prevent re-triggering
     } else if (holdTime % 1000 == 0) {
</code_context>
<issue_to_address>
**issue (bug_risk):** Disabling the buzzer auto-shutoff logic may reintroduce long-hold edge cases

With `DisableBuzzer()` commented out, `ditIsHeld` is cleared but the buzzer stays on, so any logic that relied on long-hold auto-shutoff may now see an indefinite tone.

If this behavioral change is intentional for the Micro, consider either:
- Removing this long-hold block entirely (to avoid misleading "disabling buzzer" logs), or
- Guarding the auto-shutoff with a board-specific flag (e.g. `#ifdef DISABLE_BUZZER_AUTOSHUTOFF`) so the change is explicit and configuration-driven.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread equal_temperament.h
11181, // 125
11845, // 126
12550, // 127
static const uint16_t equalTemperamentNote[] PROGMEM = {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (performance): Using static in the header will duplicate the lookup table into every translation unit

Declaring this table as static const in the header gives each including .cpp its own flash/PROGMEM copy, which is wasteful on small AVR devices. Instead, declare it extern in the header and define it once in a .cpp:

// equal_temperament.h
extern const uint16_t equalTemperamentNote[] PROGMEM;

// equal_temperament.cpp
#include <Arduino.h>
#include <avr/pgmspace.h>
const uint16_t equalTemperamentNote[] PROGMEM = { ... };

GET_EQUAL_TEMPERAMENT_NOTE will still work unchanged with the extern declaration.

Suggested implementation:

extern const uint16_t equalTemperamentNote[] PROGMEM;

#define GET_EQUAL_TEMPERAMENT_NOTE(n) pgm_read_word(&equalTemperamentNote[(n)])

` since that file isn't shown).

Here are the edits to equal_temperament.h:

<file_operations>
<file_operation operation="edit" file_path="equal_temperament.h">
<<<<<<< SEARCH
static const uint16_t equalTemperamentNote[] PROGMEM = {
  8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,
  20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,49,
  51,55,58,61,65,69,73,77,82,87,92,98,103,110,116,123,
  130,138,146,155,164,174,185,196,207,220,233,247,261,277,293,311,
  329,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,
  831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1662,1760,1865,1976,
  2094,2218,2350,2490,2638,2795,2961,3137,3324,3521,3731,3953,4188,4437,4701,4980,
  5276,5590,5922,6275,6648,7043,7462,7906,8376,8874,9402,9961,10553,11181,11845,12550
};

#define GET_EQUAL_TEMPERAMENT_NOTE(n) pgm_read_word(&equalTemperamentNote[(n)])
=======
extern const uint16_t equalTemperamentNote[] PROGMEM;

#define GET_EQUAL_TEMPERAMENT_NOTE(n) pgm_read_word(&equalTemperamentNote[(n)])
>>>>>>> REPLACE
</file_operation>
</file_operations>

<additional_changes>

  1. Add a new implementation file equal_temperament.cpp with the single definition of the lookup table:
#include <Arduino.h>
#include <avr/pgmspace.h>
#include "equal_temperament.h"

const uint16_t equalTemperamentNote[] PROGMEM = {
  8,8,9,9,10,10,11,12,12,13,14,15,16,17,18,19,
  20,21,23,24,25,27,29,30,32,34,36,38,41,43,46,49,
  51,55,58,61,65,69,73,77,82,87,92,98,103,110,116,123,
  130,138,146,155,164,174,185,196,207,220,233,247,261,277,293,311,
  329,349,370,392,415,440,466,494,523,554,587,622,659,698,740,784,
  831,880,932,988,1047,1109,1175,1245,1319,1397,1480,1568,1662,1760,1865,1976,
  2094,2218,2350,2490,2638,2795,2961,3137,3324,3521,3731,3953,4188,4437,4701,4980,
  5276,5590,5922,6275,6648,7043,7462,7906,8376,8874,9402,9961,10553,11181,11845,12550
};
  1. Ensure equal_temperament.cpp is compiled/linked as part of the project so the equalTemperamentNote symbol is available to all translation units that include equal_temperament.h.

Comment thread polybuzzer.cpp

this->tones[slot] = frequency;
this->update();
if (slot != 0) return; // ignore extra slots on Micro
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (bug_risk): Silently ignoring slot != 0 can hide logic bugs at call sites

Calls with slot != 0 effectively do nothing while still appearing to succeed, which can be confusing for callers that expect multiple slots. Consider either clamping slot to 0 or adding a debug-only warning (and then clamping) so that misuse is visible during development instead of silently dropping tones.

Suggested implementation:

void PolyBuzzer::Tone(int slot, unsigned int frequency) {
  int clampedSlot = slot;
  if (slot != 0) {
#ifdef DEBUG
    Serial.print(F("PolyBuzzer::Tone: requested slot "));
    Serial.print(slot);
    Serial.println(F(" not supported on Micro; clamping to slot 0"));
#endif
    clampedSlot = 0;
  }

  Serial.print(F("Setting tone in slot "));
  Serial.print(clampedSlot);
  Serial.print(F(" to frequency: "));
  Serial.println(frequency);

  this->tones[clampedSlot] = frequency;
  this->update();
}
  1. Ensure that DEBUG (or whatever debug macro is appropriate for this project) is defined in your build system or a common header to enable the warning during development.
  2. If the project uses a different debug macro (e.g. DEBUG_POLYBUZZER, SERIAL_DEBUG, etc.), replace #ifdef DEBUG with the project-standard macro for conditional debug logging.

Comment thread adapter.cpp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant