forked from wirtz/BALibrary
parent
5c4be4bc2a
commit
10818bcd78
@ -0,0 +1,67 @@ |
|||||||
|
#define TGA_PRO_REVB |
||||||
|
#define TGA_PRO_EXPAND_REV2 |
||||||
|
|
||||||
|
#include "BAGuitar.h" |
||||||
|
|
||||||
|
using namespace BALibrary; |
||||||
|
|
||||||
|
// Create physical controls for Expansion Board, 2 switches, 3 pots, 0 encoders, 2 LEDs
|
||||||
|
BAPhysicalControls controls(BA_EXPAND_NUM_SW, BA_EXPAND_NUM_POT, 0, BA_EXPAND_NUM_LED); |
||||||
|
|
||||||
|
void setup() { |
||||||
|
delay(100); |
||||||
|
Serial.begin(57600); |
||||||
|
delay(500); // long delay to wait for Serial to init
|
||||||
|
|
||||||
|
// put your setup code here, to run once:
|
||||||
|
Serial.println("Calibrating POT1"); |
||||||
|
Potentiometer::Calib pot1Calib = Potentiometer::calibrate(BA_EXPAND_POT1_PIN); |
||||||
|
if (pot1Calib.min == pot1Calib.max) { Serial.println("\n!!! The knob didn't appear to move. Are you SURE you're turning the right knob? !!!"); } |
||||||
|
|
||||||
|
Serial.println("\nCalibrating POT2"); |
||||||
|
Potentiometer::Calib pot2Calib = Potentiometer::calibrate(BA_EXPAND_POT2_PIN); |
||||||
|
if (pot2Calib.min == pot2Calib.max) { Serial.println("\n!!! The knob didn't appear to move. Are you SURE you're turning the right knob? !!!"); } |
||||||
|
|
||||||
|
Serial.println("\nCalibrating POT3"); |
||||||
|
Potentiometer::Calib pot3Calib = Potentiometer::calibrate(BA_EXPAND_POT3_PIN); |
||||||
|
if (pot3Calib.min == pot3Calib.max) { Serial.println("\n!!! The knob didn't appear to move. Are you SURE you're turning the right knob? !!!"); } |
||||||
|
|
||||||
|
// Create the controls using the calib values
|
||||||
|
controls.addPot(BA_EXPAND_POT1_PIN, pot1Calib.min, pot1Calib.max, pot1Calib.swap); |
||||||
|
controls.addPot(BA_EXPAND_POT2_PIN, pot2Calib.min, pot2Calib.max, pot2Calib.swap); |
||||||
|
controls.addPot(BA_EXPAND_POT3_PIN, pot3Calib.min, pot3Calib.max, pot3Calib.swap); |
||||||
|
|
||||||
|
// Add the pushbuttons
|
||||||
|
controls.addSwitch(BA_EXPAND_SW1_PIN); |
||||||
|
controls.addSwitch(BA_EXPAND_SW2_PIN); |
||||||
|
|
||||||
|
// Setup the LEDs
|
||||||
|
controls.addOutput(BA_EXPAND_LED1_PIN); |
||||||
|
controls.setOutput(BA_EXPAND_LED1_PIN, 0); |
||||||
|
controls.addOutput(BA_EXPAND_LED2_PIN); |
||||||
|
controls.setOutput(BA_EXPAND_LED2_PIN, 0); |
||||||
|
|
||||||
|
Serial.println("DONE SETUP! Try turning knobs and pushing buttons!\n"); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
void loop() { |
||||||
|
// put your main code here, to run repeatedly:
|
||||||
|
float value; |
||||||
|
for (unsigned i=0; i<BA_EXPAND_NUM_POT; i++) { |
||||||
|
if (controls.checkPotValue(i, value)) { |
||||||
|
Serial.println(String("POT") + (i+1) + String(" new value: ") + value); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Check pushbuttons
|
||||||
|
for (unsigned i=0; i<BA_EXPAND_NUM_SW; i++) { |
||||||
|
if (controls.isSwitchToggled(i)) { |
||||||
|
Serial.println(String("Button") + (i+1) + String(" pushed!")); |
||||||
|
controls.toggleOutput(i); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
delay(10); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,113 @@ |
|||||||
|
#include <MIDI.h> |
||||||
|
|
||||||
|
#define TGA_PRO_REVB |
||||||
|
#define TGA_PRO_EXPAND_REV2 |
||||||
|
|
||||||
|
#include "BAGuitar.h" |
||||||
|
|
||||||
|
using namespace midi; |
||||||
|
using namespace BAEffects; |
||||||
|
using namespace BALibrary; |
||||||
|
|
||||||
|
AudioInputI2S i2sIn; |
||||||
|
AudioOutputI2S i2sOut; |
||||||
|
BAAudioControlWM8731 codec; |
||||||
|
|
||||||
|
//#define USE_EXT // uncomment this line to use External MEM0
|
||||||
|
|
||||||
|
#ifdef USE_EXT |
||||||
|
// If using external SPI memory, we will instantiance an SRAM
|
||||||
|
// manager and create an external memory slot to use as the memory
|
||||||
|
// for our audio delay
|
||||||
|
ExternalSramManager externalSram; |
||||||
|
ExtMemSlot delaySlot; // Declare an external memory slot.
|
||||||
|
|
||||||
|
// Instantiate the AudioEffectAnalogDelay to use external memory by
|
||||||
|
/// passing it the delay slot.
|
||||||
|
AudioEffectAnalogDelay analogDelay(&delaySlot); |
||||||
|
#else |
||||||
|
// If using internal memory, we will instantiate the AudioEffectAnalogDelay
|
||||||
|
// by passing it the maximum amount of delay we will use in millseconds. Note that
|
||||||
|
// audio delay lengths are very limited when using internal memory due to limited
|
||||||
|
// internal RAM size.
|
||||||
|
AudioEffectAnalogDelay analogDelay(200.0f); // max delay of 200 ms.
|
||||||
|
#endif |
||||||
|
|
||||||
|
AudioFilterBiquad cabFilter; // We'll want something to cut out the highs and smooth the tone, just like a guitar cab.
|
||||||
|
|
||||||
|
// Simply connect the input to the delay, and the output
|
||||||
|
// to both i2s channels
|
||||||
|
AudioConnection input(i2sIn,0, analogDelay,0); |
||||||
|
AudioConnection delayOut(analogDelay, 0, cabFilter, 0); |
||||||
|
AudioConnection leftOut(cabFilter,0, i2sOut, 0); |
||||||
|
AudioConnection rightOut(cabFilter,0, i2sOut, 1); |
||||||
|
|
||||||
|
//////////////////////////////////////////
|
||||||
|
// SETUP PHYSICAL CONTROLS
|
||||||
|
//////////////////////////////////////////
|
||||||
|
BAPhysicalControls controls(BA_EXPAND_NUM_SW, BA_EXPAND_NUM_POT, 0); |
||||||
|
|
||||||
|
int loopCount = 0; |
||||||
|
|
||||||
|
void setup() { |
||||||
|
delay(100); |
||||||
|
Serial.begin(57600); // Start the serial port
|
||||||
|
delay(100); |
||||||
|
|
||||||
|
// Setup the controls
|
||||||
|
controls.addSwitch(BA_EXPAND_SW1_PIN); |
||||||
|
controls.addSwitch(BA_EXPAND_SW2_PIN); |
||||||
|
controls.addPot(BA_EXPAND_POT1_PIN,
|
||||||
|
|
||||||
|
// Disable the codec first
|
||||||
|
codec.disable(); |
||||||
|
AudioMemory(128); |
||||||
|
|
||||||
|
// Enable the codec
|
||||||
|
Serial.println("Enabling codec...\n"); |
||||||
|
codec.enable(); |
||||||
|
|
||||||
|
// If using external memory request request memory from the manager
|
||||||
|
// for the slot
|
||||||
|
#ifdef USE_EXT |
||||||
|
Serial.println("Using EXTERNAL memory"); |
||||||
|
// We have to request memory be allocated to our slot.
|
||||||
|
externalSram.requestMemory(&delaySlot, 500.0f, MemSelect::MEM0, true); |
||||||
|
#else |
||||||
|
Serial.println("Using INTERNAL memory"); |
||||||
|
#endif |
||||||
|
|
||||||
|
// Besure to enable the delay. When disabled, audio is is completely blocked
|
||||||
|
// to minimize resources to nearly zero.
|
||||||
|
analogDelay.enable();
|
||||||
|
|
||||||
|
// Set some default values.
|
||||||
|
// These can be changed using the controls on the Blackaddr Audio Expansion Board
|
||||||
|
analogDelay.bypass(false); |
||||||
|
analogDelay.mix(0.5f); |
||||||
|
analogDelay.feedback(0.0f); |
||||||
|
|
||||||
|
//////////////////////////////////
|
||||||
|
// AnalogDelay filter selection //
|
||||||
|
// Uncomment to tryout the 3 different built-in filters.
|
||||||
|
//analogDelay.setFilter(AudioEffectAnalogDelay::Filter::DM3); // The default filter. Naturally bright echo (highs stay, lows fade away)
|
||||||
|
//analogDelay.setFilter(AudioEffectAnalogDelay::Filter::WARM); // A warm filter with a smooth frequency rolloff above 2Khz
|
||||||
|
//analogDelay.setFilter(AudioEffectAnalogDelay::Filter::DARK); // A very dark filter, with a sharp rolloff above 1Khz
|
||||||
|
|
||||||
|
// Setup 2-stages of LPF, cutoff 4500 Hz, Q-factor 0.7071 (a 'normal' Q-factor)
|
||||||
|
cabFilter.setLowpass(0, 4500, .7071); |
||||||
|
cabFilter.setLowpass(1, 4500, .7071); |
||||||
|
} |
||||||
|
|
||||||
|
void loop() { |
||||||
|
|
||||||
|
if (loopCount % 524288 == 0) { |
||||||
|
Serial.print("Processor Usage, Total: "); Serial.print(AudioProcessorUsage()); |
||||||
|
Serial.print("% "); |
||||||
|
Serial.print(" analogDelay: "); Serial.print(analogDelay.processorUsage()); |
||||||
|
Serial.println("%"); |
||||||
|
} |
||||||
|
loopCount++; |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,19 @@ |
|||||||
|
// To give your project a unique name, this code must be
|
||||||
|
// placed into a .c file (its own tab). It can not be in
|
||||||
|
// a .cpp file or your main sketch (the .ino file).
|
||||||
|
|
||||||
|
#include "usb_names.h" |
||||||
|
|
||||||
|
// Edit these lines to create your own name. The length must
|
||||||
|
// match the number of characters in your custom name.
|
||||||
|
|
||||||
|
#define MIDI_NAME {'B','l','a','c','k','a','d','d','r',' ','A','u','d','i','o',' ','T','G','A',' ','P','r','o'} |
||||||
|
#define MIDI_NAME_LEN 23 |
||||||
|
|
||||||
|
// Do not change this part. This exact format is required by USB.
|
||||||
|
|
||||||
|
struct usb_string_descriptor_struct usb_string_product_name = { |
||||||
|
2 + MIDI_NAME_LEN * 2, |
||||||
|
3, |
||||||
|
MIDI_NAME |
||||||
|
}; |
@ -0,0 +1,148 @@ |
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file |
||||||
|
* @author Steve Lascos |
||||||
|
* @company Blackaddr Audio |
||||||
|
* |
||||||
|
* BAPhysicalControls is a general purpose class for handling an array of |
||||||
|
* pots and switches. |
||||||
|
* |
||||||
|
* @copyright This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version.* |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*****************************************************************************/ |
||||||
|
#ifndef __BAPHYSICALCONTROLS_H |
||||||
|
#define __BAPHYSICALCONTROLS_H |
||||||
|
|
||||||
|
#include <vector> |
||||||
|
#include <Encoder.h> |
||||||
|
#include <Bounce.h> |
||||||
|
|
||||||
|
namespace BALibrary { |
||||||
|
|
||||||
|
class DigitalOutput { |
||||||
|
public: |
||||||
|
DigitalOutput(uint8_t pin) : m_pin(pin) {} |
||||||
|
void set(int val); |
||||||
|
void toggle(void); |
||||||
|
|
||||||
|
private: |
||||||
|
uint8_t m_pin; |
||||||
|
int m_val = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
class Potentiometer { |
||||||
|
public: |
||||||
|
struct Calib { |
||||||
|
unsigned min; |
||||||
|
unsigned max; |
||||||
|
bool swap; |
||||||
|
}; |
||||||
|
Potentiometer(uint8_t pin, unsigned minCalibration, unsigned maxCalibration) |
||||||
|
: m_pin(pin), m_swapDirection(false), m_minCalibration(minCalibration), m_maxCalibration(maxCalibration) {} |
||||||
|
|
||||||
|
Potentiometer(uint8_t pin, unsigned minCalibration, unsigned maxCalibration, bool swapDirection) |
||||||
|
: m_pin(pin), m_swapDirection(swapDirection), m_minCalibration(minCalibration), m_maxCalibration(maxCalibration) {} |
||||||
|
|
||||||
|
bool getValue(float &value); |
||||||
|
int getRawValue(); |
||||||
|
void adjustCalibrationThreshold(float thresholdFactor); |
||||||
|
static Calib calibrate(uint8_t pin); |
||||||
|
|
||||||
|
private: |
||||||
|
uint8_t m_pin; |
||||||
|
bool m_swapDirection; |
||||||
|
unsigned m_minCalibration; |
||||||
|
unsigned m_maxCalibration; |
||||||
|
unsigned m_lastValue = 0; |
||||||
|
unsigned m_lastValue2 = 0; |
||||||
|
}; |
||||||
|
|
||||||
|
constexpr bool ENCODER_SWAP = true; |
||||||
|
constexpr bool ENCODER_NOSWAP = false; |
||||||
|
|
||||||
|
class RotaryEncoder : public Encoder { |
||||||
|
public: |
||||||
|
RotaryEncoder(uint8_t pin1, uint8_t pin2, bool swapDirection = false, int divider = 1) : Encoder(pin1,pin2), m_swapDirection(swapDirection), m_divider(divider) {} |
||||||
|
|
||||||
|
int getChange(); |
||||||
|
void setDivider(int divider); |
||||||
|
|
||||||
|
private: |
||||||
|
bool m_swapDirection; |
||||||
|
int32_t m_lastPosition = 0; |
||||||
|
int32_t m_divider; |
||||||
|
}; |
||||||
|
|
||||||
|
/// Specifies the type of control
|
||||||
|
enum class ControlType : unsigned { |
||||||
|
SWITCH_MOMENTARY = 0, ///< a momentary switch, which is only on when pressed.
|
||||||
|
SWITCH_LATCHING = 1, ///< a latching switch, which toggles between on and off with each press and release
|
||||||
|
ROTARY_KNOB = 2, ///< a rotary encoder knob
|
||||||
|
POT = 3, ///< an analog potentiometer
|
||||||
|
UNDEFINED = 255 ///< undefined or uninitialized
|
||||||
|
}; |
||||||
|
|
||||||
|
class BAPhysicalControls { |
||||||
|
public: |
||||||
|
BAPhysicalControls() = delete; |
||||||
|
BAPhysicalControls(unsigned numSwitches, unsigned numPots, unsigned numEncoders = 0, unsigned numOutputs = 0); |
||||||
|
~BAPhysicalControls() {} |
||||||
|
|
||||||
|
/// add a rotary encoders to the controls
|
||||||
|
/// @param pin1 the pin number corresponding to 'A' on the encoder
|
||||||
|
/// @param pin2 the pin number corresponding to 'B' on the encoder
|
||||||
|
/// @param swapDirection When true, reverses which rotation direction is positive, and which is negative
|
||||||
|
/// @param divider optional, for encoders with high resolution this divides down the rotation measurement.
|
||||||
|
/// @returns the index in the encoder vector the new encoder was placed at.
|
||||||
|
unsigned addRotary(uint8_t pin1, uint8_t pin2, bool swapDirection = false, int divider = 1); |
||||||
|
|
||||||
|
/// add a switch to the controls
|
||||||
|
/// @param pin the pin number connected to the switch
|
||||||
|
/// @param intervalMilliseconds, optional, specifies the filtering time to debounce a switch
|
||||||
|
/// @returns the index in the switch vector the new switch was placed at.
|
||||||
|
unsigned addSwitch(uint8_t pin, unsigned long intervalMilliseconds = 10); |
||||||
|
|
||||||
|
/// add a pot to the controls
|
||||||
|
/// @param pin the pin number connected to the wiper of the pot
|
||||||
|
/// @param minCalibration the value corresponding to lowest pot setting
|
||||||
|
/// @param maxCalibration the value corresponding to the highest pot setting
|
||||||
|
unsigned addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration); |
||||||
|
|
||||||
|
/// add a pot to the controls
|
||||||
|
/// @param pin the pin number connected to the wiper of the pot
|
||||||
|
/// @param minCalibration the value corresponding to lowest pot setting
|
||||||
|
/// @param maxCalibration the value corresponding to the highest pot setting
|
||||||
|
/// @param swapDirection reverses the which direction is considered pot minimum value
|
||||||
|
/// @param range the pot raw value will be mapped into a range of 0 to range
|
||||||
|
unsigned addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration, bool swapDirection); |
||||||
|
unsigned addOutput(uint8_t pin); |
||||||
|
void setOutput(unsigned index, int val); |
||||||
|
void toggleOutput(unsigned index); |
||||||
|
int getRotaryAdjustUnit(unsigned index); |
||||||
|
bool checkPotValue(unsigned index, float &value); |
||||||
|
bool isSwitchToggled(unsigned index); |
||||||
|
|
||||||
|
private: |
||||||
|
std::vector<Potentiometer> m_pots; |
||||||
|
std::vector<RotaryEncoder> m_encoders; |
||||||
|
std::vector<Bounce> m_switches; |
||||||
|
std::vector<DigitalOutput> m_outputs; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // BALibrary
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __BAPHYSICALCONTROLS_H */ |
@ -0,0 +1,220 @@ |
|||||||
|
/*
|
||||||
|
* BAPhysicalControls.cpp |
||||||
|
* |
||||||
|
* This file provides a class for handling physical controls such as |
||||||
|
* switches, pots and rotary encoders. |
||||||
|
* |
||||||
|
* This program is free software: you can redistribute it and/or modify |
||||||
|
* it under the terms of the GNU General Public License as published by |
||||||
|
* the Free Software Foundation, either version 3 of the License, or |
||||||
|
* (at your option) any later version.* |
||||||
|
* |
||||||
|
* This program is distributed in the hope that it will be useful, |
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
* GNU General Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License |
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/ |
||||||
|
#include "BAPhysicalControls.h" |
||||||
|
|
||||||
|
// These calls must be define in order to get vector to work on arduino
|
||||||
|
namespace std { |
||||||
|
void __throw_bad_alloc() { |
||||||
|
Serial.println("Unable to allocate memory"); |
||||||
|
abort(); |
||||||
|
} |
||||||
|
void __throw_length_error( char const*e ) { |
||||||
|
Serial.print("Length Error :"); Serial.println(e); |
||||||
|
abort(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
namespace BALibrary { |
||||||
|
|
||||||
|
BAPhysicalControls::BAPhysicalControls(unsigned numSwitches, unsigned numPots, unsigned numEncoders, unsigned numOutputs) { |
||||||
|
if (numSwitches > 0) { |
||||||
|
m_switches.reserve(numSwitches); |
||||||
|
} |
||||||
|
if (numPots > 0) { |
||||||
|
m_pots.reserve(numPots); |
||||||
|
} |
||||||
|
if (numEncoders > 0) { |
||||||
|
m_encoders.reserve(numEncoders); |
||||||
|
} |
||||||
|
if (numOutputs > 0) { |
||||||
|
m_outputs.reserve(numOutputs); |
||||||
|
} |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
unsigned BAPhysicalControls::addRotary(uint8_t pin1, uint8_t pin2, bool swapDirection, int divider) { |
||||||
|
m_encoders.emplace_back(pin1, pin2, swapDirection, divider); |
||||||
|
pinMode(pin1, INPUT); |
||||||
|
pinMode(pin2, INPUT); |
||||||
|
return m_encoders.size()-1; |
||||||
|
} |
||||||
|
|
||||||
|
unsigned BAPhysicalControls::addSwitch(uint8_t pin, unsigned long intervalMilliseconds) { |
||||||
|
m_switches.emplace_back(pin, intervalMilliseconds); |
||||||
|
pinMode(pin, INPUT); |
||||||
|
return m_switches.size()-1; |
||||||
|
} |
||||||
|
|
||||||
|
unsigned BAPhysicalControls::addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration) { |
||||||
|
m_pots.emplace_back(pin, minCalibration, maxCalibration); |
||||||
|
return m_pots.size()-1; |
||||||
|
} |
||||||
|
|
||||||
|
unsigned BAPhysicalControls::addPot(uint8_t pin, unsigned minCalibration, unsigned maxCalibration, bool swapDirection) { |
||||||
|
m_pots.emplace_back(pin, minCalibration, maxCalibration, swapDirection); |
||||||
|
return m_pots.size()-1; |
||||||
|
} |
||||||
|
|
||||||
|
unsigned BAPhysicalControls::addOutput(uint8_t pin) { |
||||||
|
m_outputs.emplace_back(pin); |
||||||
|
pinMode(pin, OUTPUT); |
||||||
|
return m_outputs.size()-1; |
||||||
|
} |
||||||
|
|
||||||
|
void BAPhysicalControls::setOutput(unsigned index, int val) { |
||||||
|
if (index >= m_outputs.size()) { return; } |
||||||
|
m_outputs[index].set(val); |
||||||
|
} |
||||||
|
|
||||||
|
void BAPhysicalControls::toggleOutput(unsigned index) { |
||||||
|
if (index >= m_outputs.size()) { return; } |
||||||
|
m_outputs[index].toggle(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int BAPhysicalControls::getRotaryAdjustUnit(unsigned index) { |
||||||
|
if (index >= m_encoders.size()) { return 0; } // index is greater than number of encoders
|
||||||
|
|
||||||
|
int encoderAdjust = m_encoders[index].getChange(); |
||||||
|
if (encoderAdjust != 0) { |
||||||
|
// clip the adjust to maximum abs value of 1.
|
||||||
|
int encoderAdjust = (encoderAdjust > 0) ? 1 : -1; |
||||||
|
} |
||||||
|
|
||||||
|
return encoderAdjust; |
||||||
|
} |
||||||
|
|
||||||
|
bool BAPhysicalControls::checkPotValue(unsigned index, float &value) { |
||||||
|
if (index >= m_pots.size()) { return false;} // index is greater than number of pots
|
||||||
|
return m_pots[index].getValue(value); |
||||||
|
} |
||||||
|
|
||||||
|
bool BAPhysicalControls::isSwitchToggled(unsigned index) { |
||||||
|
if (index >= m_switches.size()) { return 0; } // index is greater than number of switches
|
||||||
|
Bounce &sw = m_switches[index]; |
||||||
|
|
||||||
|
if (sw.update() && sw.fallingEdge()) { |
||||||
|
return true; |
||||||
|
} else { |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
///////////////////////////
|
||||||
|
|
||||||
|
void DigitalOutput::set(int val) { |
||||||
|
m_val = val; |
||||||
|
digitalWriteFast(m_pin, m_val); |
||||||
|
} |
||||||
|
|
||||||
|
void DigitalOutput::toggle(void) { |
||||||
|
m_val = !m_val; |
||||||
|
digitalWriteFast(m_pin, m_val); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool Potentiometer::getValue(float &value) { |
||||||
|
|
||||||
|
unsigned val = analogRead(m_pin); // read the raw value
|
||||||
|
// Return false if the value is the same as the last sample, or 2 samples ago. The second check is to
|
||||||
|
// prevent oscillating between two values.
|
||||||
|
if ((val == m_lastValue) || (val == m_lastValue2)) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
// Otherwise update the last value
|
||||||
|
m_lastValue = val; |
||||||
|
// constrain it within the calibration values, them map it to the desired range.
|
||||||
|
val = constrain(val, m_minCalibration, m_maxCalibration); |
||||||
|
value = static_cast<float>(val - m_minCalibration) / static_cast<float>(m_maxCalibration); |
||||||
|
if (m_swapDirection) { |
||||||
|
value = 1.0f - value; |
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
int Potentiometer::getRawValue() { |
||||||
|
return analogRead(m_pin); |
||||||
|
} |
||||||
|
|
||||||
|
void Potentiometer::adjustCalibrationThreshold(float thresholdFactor) |
||||||
|
{ |
||||||
|
float threshold = m_maxCalibration * thresholdFactor; |
||||||
|
m_maxCalibration -= static_cast<unsigned>(threshold); |
||||||
|
m_minCalibration += static_cast<unsigned>(threshold); |
||||||
|
} |
||||||
|
|
||||||
|
Potentiometer::Calib Potentiometer::calibrate(uint8_t pin) { |
||||||
|
Calib calib; |
||||||
|
|
||||||
|
Serial.print("Calibration pin "); Serial.println(pin); |
||||||
|
Serial.println("Move the pot fully counter-clockwise to the minimum setting and press any key then ENTER"); |
||||||
|
while (true) { |
||||||
|
delay(100); |
||||||
|
if (Serial.available() > 0) { |
||||||
|
calib.min = analogRead(pin); |
||||||
|
while (Serial.available()) { Serial.read(); } |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
Serial.println("Move the pot fully clockwise to the maximum setting and press any key then ENTER"); |
||||||
|
while (true) { |
||||||
|
delay(100); |
||||||
|
if (Serial.available() > 0) { |
||||||
|
calib.max = analogRead(pin); |
||||||
|
while (Serial.available()) { Serial.read(); } |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (calib.min > calib.max) { |
||||||
|
unsigned tmp = calib.max; |
||||||
|
calib.max = calib.min; |
||||||
|
calib.min = tmp; |
||||||
|
calib.swap = true; |
||||||
|
} |
||||||
|
|
||||||
|
Serial.print("The calibration for pin "); Serial.print(pin); |
||||||
|
Serial.print(" is min:"); Serial.print(calib.min); |
||||||
|
Serial.print(" max:"); Serial.print(calib.max); |
||||||
|
Serial.print(" swap: "); Serial.println(calib.swap); |
||||||
|
|
||||||
|
return calib; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
int RotaryEncoder::getChange() { |
||||||
|
int32_t newPosition = read(); |
||||||
|
int delta = newPosition - m_lastPosition; |
||||||
|
m_lastPosition = newPosition; |
||||||
|
if (m_swapDirection) { delta = -delta; } |
||||||
|
return delta/m_divider; |
||||||
|
} |
||||||
|
|
||||||
|
void RotaryEncoder::setDivider(int divider) { |
||||||
|
m_divider = divider; |
||||||
|
} |
||||||
|
|
||||||
|
} // BALibrary
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in new issue