bxparks / AceButton

An adjustable, compact, event-driven button library for Arduino that debounces and dispatches events to a user-defined event handler.
MIT License
385 stars 37 forks source link

Possible conflict with TC3 library on SAMD21 architecture ? #101

Closed Sercurio closed 1 year ago

Sercurio commented 1 year ago

Hi, I'm trying to work with the DAC and your library on seeduino XIAO controller. Events are not handled when uncommenting these lines, but work when commented.

    TIMER.initialize(TIMER_TIME);
    TIMER.attachInterrupt(GenerateAudioStream);
    pinMode(DAC_PIN, OUTPUT);
    analogReadResolution(5);
    analogWriteResolution(8);

Full code

#include <Arduino.h>
#include <AceButton.h>
using namespace ace_button;

#include <TimerTC3.h>
#define USE_TIMER_TC3  // use TimerTc3
#define TIMER_TIME 125 // 1/8000 Hz = 125 micro seconds
#define TIMER TimerTc3
#define DAC_PIN 0 // pin of the XIAO DAC

#define PIN_ANALOG_1 A1

// Create 4 AceButton objects, with their virtual pin number 0 to 3. The number
// of buttons does not need to be identical to the number of analog levels. You
// can choose to define only a subset of buttons here.
//
// Use the 4-parameter `AceButton()` constructor with the `buttonConfig`
// parameter explicitly to `nullptr` to prevent the automatic creation of the
// default SystemButtonConfig, saving about 30 bytes of flash and 26 bytes of
// RAM on an AVR processor.
static const uint8_t NUM_BUTTONS = 7;
static AceButton b0(nullptr, 0);
static AceButton b1(nullptr, 1);
static AceButton b2(nullptr, 2);
static AceButton b3(nullptr, 3);
static AceButton b4(nullptr, 4);
static AceButton b5(nullptr, 5);
static AceButton b6(nullptr, 6);
static AceButton *const BUTTONS[NUM_BUTTONS] = {
    &b0, &b1, &b2, &b3, &b4, &b5, &b6};

// Define the ADC voltage levels for each button.
// For 4 buttons, we need 5 levels.
static const uint8_t NUM_LEVELS = NUM_BUTTONS + 1;
static const uint16_t LEVELS[NUM_LEVELS] = {
    0,
    132,
    264,
    363,
    429,
    528,
    594,
    1023};

// The LadderButtonConfig constructor binds the AceButton to the
// LadderButtonConfig.
static LadderButtonConfig buttonConfig(
    PIN_ANALOG_1, NUM_LEVELS, LEVELS, NUM_BUTTONS, BUTTONS);

// The event handler for the button.
void handleEvent(AceButton *button, uint8_t eventType, uint8_t buttonState)
{
    // Print out a message for all events.
    Serial.print(F("handleEvent(): "));
    Serial.print(F("virtualPin: "));
    Serial.print(button->getPin());
    Serial.print(F("; eventType: "));
    Serial.print(eventType);
    Serial.print(F("; buttonState: "));
    Serial.println(buttonState);
}

// The buttonConfig.checkButtons() should be called every 4-5ms or faster, if
// the debouncing time is ~20ms. On ESP8266, analogRead() must be called *no*
// faster than 4-5ms to avoid a bug which disconnects the WiFi connection.
void checkButtons()
{
    static unsigned long prev = millis();

    // DO NOT USE delay(5) to do this.
    unsigned long now = millis();
    if (now - prev > 5)
    {
        buttonConfig.checkButtons();
        prev = now;
    }
}

void GenerateAudioStream()
{
    static int t = 0;
    t++;

    analogWrite(DAC_PIN, (uint32_t)t / 16);
}

void compareTinyExprAndNativeEvaluation();

void setup()
{
    Serial.begin(115200);
    while (!Serial)
        ;

    pinMode(PIN_ANALOG_1, INPUT);
    interrupts();
    // Configure the ButtonConfig with the event handler, and enable all higher
    // level events.
    buttonConfig.setEventHandler(handleEvent);
    buttonConfig.setFeature(ButtonConfig::kFeatureClick);
    buttonConfig.setFeature(ButtonConfig::kFeatureDoubleClick);
    buttonConfig.setFeature(ButtonConfig::kFeatureLongPress);
    buttonConfig.setFeature(ButtonConfig::kFeatureRepeatPress);

    TIMER.initialize(TIMER_TIME);
    TIMER.attachInterrupt(GenerateAudioStream);
    pinMode(DAC_PIN, OUTPUT);
    analogReadResolution(5);
    analogWriteResolution(8);
}

void loop()
{
    checkButtons();
}

More over, when trying to do analogRead without the library and the DAC, the analogRead works