mirror of
https://github.com/Ikatono/stream_pad_arduino.git
synced 2025-10-29 04:55:39 -05:00
large update
This commit is contained in:
6
src/200hz300hz_sr10khz_dur8sec.hpp
Normal file
6
src/200hz300hz_sr10khz_dur8sec.hpp
Normal file
File diff suppressed because one or more lines are too long
14
src/ActionId.hpp
Normal file
14
src/ActionId.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef H_C91B532FD0D0486EAE4B48A326F9CA8C
|
||||
#define H_C91B532FD0D0486EAE4B48A326F9CA8C
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
struct ActionId
|
||||
{
|
||||
uint32_t value;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //H_C91B532FD0D0486EAE4B48A326F9CA8C
|
||||
30
src/Audio.cpp
Normal file
30
src/Audio.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "Audio.hpp"
|
||||
|
||||
//extern "C"
|
||||
void audio_interrupt_handler()
|
||||
{
|
||||
//api seems to require I check channels 1 at a time
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
if (dma_irqn_get_channel_status(_BaseAudio::IRQ_NUM, i))
|
||||
{
|
||||
auto aud = _BaseAudio::audio_callback_items[i];
|
||||
if (aud)
|
||||
aud->perform_interrupt();
|
||||
dma_irqn_acknowledge_channel(_BaseAudio::IRQ_NUM, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _BaseAudio::enable_handler()
|
||||
{
|
||||
static bool handler_enabled = false;
|
||||
if (!handler_enabled)
|
||||
{
|
||||
handler_enabled = true;
|
||||
irq_add_shared_handler(IRQ_NUM, audio_interrupt_handler, 200);
|
||||
irq_set_enabled(IRQ_NUM, true);
|
||||
}
|
||||
}
|
||||
|
||||
std::array<_BaseAudio*, 12> _BaseAudio::audio_callback_items;
|
||||
165
src/Audio.hpp
Normal file
165
src/Audio.hpp
Normal file
@@ -0,0 +1,165 @@
|
||||
#ifndef H_DB5EAFBD40EE4ACDADB973F02E1A4AF1
|
||||
#define H_DB5EAFBD40EE4ACDADB973F02E1A4AF1
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <hardware/dma.h>
|
||||
#include <hardware/irq.h>
|
||||
|
||||
//extern "C"
|
||||
void audio_interrupt_handler();
|
||||
|
||||
//allows audio classes of different sizes to share interrupt
|
||||
class _BaseAudio
|
||||
{
|
||||
public:
|
||||
using interrupt_t = void(*)(uint8_t* write_to, uint8_t* dont_write_to, size_t size);
|
||||
static constexpr float sys_tick_freq = 133'000'000;
|
||||
static constexpr unsigned int IRQ_NUM = DMA_IRQ_1;
|
||||
virtual void perform_interrupt() = 0;
|
||||
static std::array<_BaseAudio*, 12> audio_callback_items;
|
||||
|
||||
protected:
|
||||
friend void audio_interrupt_handler();
|
||||
static void enable_handler();
|
||||
};
|
||||
|
||||
template <std::size_t buffer_size>
|
||||
class Audio : public _BaseAudio
|
||||
{
|
||||
public:
|
||||
//claims and configures dma resources
|
||||
bool init(void* write_address)
|
||||
{
|
||||
deinit();
|
||||
dma_channel_a = dma_claim_unused_channel(false);
|
||||
if (dma_channel_a < 0)
|
||||
return false;
|
||||
audio_callback_items[dma_channel_a] = this;
|
||||
dma_channel_b = dma_claim_unused_channel(false);
|
||||
if (dma_channel_b < 0)
|
||||
{
|
||||
dma_channel_unclaim(dma_channel_a);
|
||||
audio_callback_items[dma_channel_a] = nullptr;
|
||||
dma_channel_a = -1;
|
||||
return false;
|
||||
}
|
||||
audio_callback_items[dma_channel_b] = this;
|
||||
|
||||
dma_channel_config dconf;
|
||||
channel_config_set_read_increment(&dconf, true);
|
||||
channel_config_set_write_increment(&dconf, false);
|
||||
timer = dma_claim_unused_timer(false);
|
||||
if (timer < 0)
|
||||
{
|
||||
dma_channel_unclaim(dma_channel_a);
|
||||
dma_channel_unclaim(dma_channel_b);
|
||||
audio_callback_items[dma_channel_a] = audio_callback_items[dma_channel_b] = nullptr;
|
||||
dma_channel_a = dma_channel_b = -1;
|
||||
return false;
|
||||
}
|
||||
channel_config_set_dreq(&dconf, dma_get_timer_dreq(timer));
|
||||
channel_config_set_transfer_data_size(&dconf, DMA_SIZE_8);
|
||||
|
||||
//create a second config so the triggers can point to each other
|
||||
dma_channel_config dconf_b = dconf;
|
||||
channel_config_set_chain_to(&dconf, dma_channel_b);
|
||||
channel_config_set_chain_to(&dconf, dma_channel_a);
|
||||
|
||||
dma_channel_configure(dma_channel_a, &dconf, write_address, bankA.data(), buffer_size, false);
|
||||
dma_channel_configure(dma_channel_b, &dconf_b, write_address, bankB.data(), buffer_size, false);
|
||||
|
||||
enable_handler();
|
||||
dma_irqn_set_channel_enabled(IRQ_NUM, dma_channel_a, true);
|
||||
dma_irqn_set_channel_enabled(IRQ_NUM, dma_channel_b, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
void deinit()
|
||||
{
|
||||
if (dma_channel_a >= 0)
|
||||
{
|
||||
dma_channel_cleanup(dma_channel_a);
|
||||
dma_channel_unclaim(dma_channel_a);
|
||||
dma_irqn_set_channel_enabled(IRQ_NUM, dma_channel_a, false);
|
||||
audio_callback_items[dma_channel_a] = nullptr;
|
||||
dma_channel_a = -1;
|
||||
}
|
||||
if (dma_channel_b >= 0)
|
||||
{
|
||||
dma_channel_cleanup(dma_channel_b);
|
||||
dma_channel_unclaim(dma_channel_b);
|
||||
dma_irqn_set_channel_enabled(IRQ_NUM, dma_channel_a, false);
|
||||
audio_callback_items[dma_channel_b] = nullptr;
|
||||
dma_channel_b = -1;
|
||||
}
|
||||
if (timer >= 0)
|
||||
{
|
||||
dma_timer_unclaim(timer);
|
||||
timer = -1;
|
||||
}
|
||||
}
|
||||
bool is_initialized() const
|
||||
{
|
||||
return dma_channel_a >= 0 && dma_channel_b >= 0;
|
||||
}
|
||||
std::array<uint8_t, buffer_size>& get_inactive_buffer()
|
||||
{
|
||||
return bankA_active ? bankB : bankA;
|
||||
}
|
||||
std::array<uint8_t, buffer_size>& get_active_buffer()
|
||||
{
|
||||
return bankA_active ? bankA : bankB;
|
||||
}
|
||||
//this callback is responsible for loading data into the unused buffer
|
||||
//(or triggering it to happen outside of interrupt context)
|
||||
void set_callback(interrupt_t new_callback)
|
||||
{
|
||||
callback = new_callback;
|
||||
}
|
||||
//need an algorithm for this
|
||||
// void set_sample_rate(float sample_rate)
|
||||
// {
|
||||
// float ratio = sys_tick_freq / sample_rate;
|
||||
|
||||
// }
|
||||
void set_sample_fraction(uint16_t num, uint16_t den)
|
||||
{
|
||||
if (timer >= 0)
|
||||
dma_timer_set_fraction(timer, num, den);
|
||||
}
|
||||
void start()
|
||||
{
|
||||
dma_channel_start(dma_channel_a);
|
||||
}
|
||||
|
||||
protected:
|
||||
int get_active_channel() const
|
||||
{
|
||||
return bankA_active ? dma_channel_a : dma_channel_b;
|
||||
}
|
||||
int get_inactive_channel() const
|
||||
{
|
||||
return bankA_active ? dma_channel_b : dma_channel_a;
|
||||
}
|
||||
void perform_interrupt() override
|
||||
{
|
||||
bankA_active = !bankA_active;
|
||||
dma_channel_set_read_addr(get_inactive_channel(), get_inactive_buffer().data(), false);
|
||||
auto& just_finished = get_inactive_buffer();
|
||||
auto& now_active = get_active_buffer();
|
||||
if (callback)
|
||||
callback(just_finished.data(), now_active.data(), buffer_size);
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<uint8_t, buffer_size> bankA;
|
||||
std::array<uint8_t, buffer_size> bankB;
|
||||
int dma_channel_a = -1;
|
||||
int dma_channel_b = -1;
|
||||
int timer = -1;
|
||||
bool bankA_active = true;
|
||||
interrupt_t callback;
|
||||
};
|
||||
|
||||
#endif //H_DB5EAFBD40EE4ACDADB973F02E1A4AF1
|
||||
66
src/Button.hpp
Normal file
66
src/Button.hpp
Normal file
@@ -0,0 +1,66 @@
|
||||
#ifndef H_B4D7EE1A3D57466AA444F3FC912641B9
|
||||
#define H_B4D7EE1A3D57466AA444F3FC912641B9
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include "Pixel.hpp"
|
||||
#include "ActionId.hpp"
|
||||
#include "ConfigError.hpp"
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
class Page;
|
||||
|
||||
class Button
|
||||
{
|
||||
friend class Page;
|
||||
|
||||
//text on screen when holding the button
|
||||
std::string hold_text;
|
||||
//series of keycodes pressed in order then all released
|
||||
std::vector<uint8_t> keycodes;
|
||||
//color of this button
|
||||
Pixel color;
|
||||
//if set, make this page active after press
|
||||
Page *goto_page;
|
||||
//for custom actions, this tells the host what to do
|
||||
ActionId action_id;
|
||||
public:
|
||||
inline Button()
|
||||
{
|
||||
|
||||
}
|
||||
inline Button(const Button& other)
|
||||
{
|
||||
hold_text = other.hold_text;
|
||||
keycodes = other.keycodes;
|
||||
color = other.color;
|
||||
goto_page = other.goto_page;
|
||||
action_id = other.action_id;
|
||||
}
|
||||
inline Button& operator=(const Button& other)
|
||||
{
|
||||
hold_text = other.hold_text;
|
||||
keycodes = other.keycodes;
|
||||
color = other.color;
|
||||
goto_page = other.goto_page;
|
||||
action_id = other.action_id;
|
||||
return *this;
|
||||
}
|
||||
inline Button(Button&& other)
|
||||
{
|
||||
hold_text = std::move(other.hold_text);
|
||||
keycodes = std::move(other.keycodes);
|
||||
color = other.color;
|
||||
goto_page = other.goto_page;
|
||||
action_id = other.action_id;
|
||||
}
|
||||
inline ConfigError load()
|
||||
{
|
||||
return ConfigError::None;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //H_B4D7EE1A3D57466AA444F3FC912641B9
|
||||
9
src/Config.cpp
Normal file
9
src/Config.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "Config.hpp"
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
void Config::append(const Page& new_page)
|
||||
{
|
||||
pages.push_back(new_page);
|
||||
}
|
||||
}
|
||||
26
src/Config.hpp
Normal file
26
src/Config.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef H_AE095F749CEA4FC29AC38902BC5FD5D1
|
||||
#define H_AE095F749CEA4FC29AC38902BC5FD5D1
|
||||
|
||||
#include <vector>
|
||||
#include <ArduinoJson.h>
|
||||
#include "Page.hpp"
|
||||
#include "ConfigError.hpp"
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
|
||||
class Config
|
||||
{
|
||||
std::vector<Page> pages;
|
||||
public:
|
||||
Page& page(size_t index)
|
||||
{
|
||||
return pages[index];
|
||||
}
|
||||
void append(const Page& new_page);
|
||||
ConfigError load(JsonDocument);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif //H_AE095F749CEA4FC29AC38902BC5FD5D1
|
||||
16
src/ConfigError.hpp
Normal file
16
src/ConfigError.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef H_BA0C3ED91D9B4CAAB2D8C6FBCD1A1C07
|
||||
#define H_BA0C3ED91D9B4CAAB2D8C6FBCD1A1C07
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
enum class ConfigError
|
||||
{
|
||||
None = 0,
|
||||
deserialization_error = 1,
|
||||
serialization_error = 2,
|
||||
};
|
||||
//prefered over using error = ConfigError::None directly in case other non-error values are added
|
||||
bool is_error(ConfigError error);
|
||||
}
|
||||
|
||||
#endif //H_BA0C3ED91D9B4CAAB2D8C6FBCD1A1C07
|
||||
12
src/Page.cpp
Normal file
12
src/Page.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "Page.hpp"
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
std::array<Pixel, 12> Page::led_rgb;
|
||||
|
||||
void Page::update_leds()
|
||||
{
|
||||
for (int i = 0; i < 12; i++)
|
||||
led_rgb[i] = buttons[i].color;
|
||||
}
|
||||
}
|
||||
32
src/Page.hpp
Normal file
32
src/Page.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef H_1AAB801F01BA49D0BB2AAB917C307E50
|
||||
#define H_1AAB801F01BA49D0BB2AAB917C307E50
|
||||
|
||||
#include <array>
|
||||
#include "Button.hpp"
|
||||
#include "ConfigError.hpp"
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
class Page
|
||||
{
|
||||
static std::array<Pixel, 12> led_rgb;
|
||||
std::array<Button, 12> buttons;
|
||||
std::string display_text;
|
||||
public:
|
||||
inline Page() { }
|
||||
inline Page(const Page& other)
|
||||
{
|
||||
buttons = other.buttons;
|
||||
display_text = other.display_text;
|
||||
}
|
||||
inline Page(Page&& other) : buttons(std::move(other.buttons)) { }
|
||||
ConfigError load();
|
||||
void update_leds();
|
||||
inline Button& button(std::size_t index)
|
||||
{
|
||||
return buttons[index];
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif //H_1AAB801F01BA49D0BB2AAB917C307E50
|
||||
27
src/Pixel.hpp
Normal file
27
src/Pixel.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef H_FF2FF9A6BC114C719F44441B6FD238C2
|
||||
#define H_FF2FF9A6BC114C719F44441B6FD238C2
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace Configuration
|
||||
{
|
||||
struct Pixel
|
||||
{
|
||||
uint32_t value;
|
||||
//should check for endianness I think
|
||||
//but there is no fully compliant way to test at compile time
|
||||
#if defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
|
||||
uint8_t& green() { return *(reinterpret_cast<uint8_t*>(value)+0); }
|
||||
uint8_t& red() { return *(reinterpret_cast<uint8_t*>(value)+1); }
|
||||
uint8_t& blue() { return *(reinterpret_cast<uint8_t*>(value)+2); }
|
||||
uint8_t& white() { return *(reinterpret_cast<uint8_t*>(value)+3); }
|
||||
#else
|
||||
uint8_t& green() { return *(reinterpret_cast<uint8_t*>(value)+3); }
|
||||
uint8_t& red() { return *(reinterpret_cast<uint8_t*>(value)+2); }
|
||||
uint8_t& blue() { return *(reinterpret_cast<uint8_t*>(value)+1); }
|
||||
uint8_t& white() { return *(reinterpret_cast<uint8_t*>(value)+0); }
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
#endif //H_FF2FF9A6BC114C719F44441B6FD238C2
|
||||
31
src/pwm.pio
Normal file
31
src/pwm.pio
Normal file
@@ -0,0 +1,31 @@
|
||||
;
|
||||
; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||
;
|
||||
; SPDX-License-Identifier: BSD-3-Clause
|
||||
;
|
||||
|
||||
; Side-set pin 0 is used for PWM output
|
||||
|
||||
.program pwm
|
||||
.side_set 1 opt
|
||||
|
||||
pull noblock side 0 ; Pull from FIFO to OSR if available, else copy X to OSR.
|
||||
mov x, osr ; Copy most-recently-pulled value back to scratch X
|
||||
mov y, isr ; ISR contains PWM period. Y used as counter.
|
||||
countloop:
|
||||
jmp x!=y noset ; Set pin high if X == Y, keep the two paths length matched
|
||||
jmp skip side 1
|
||||
noset:
|
||||
nop ; Single dummy cycle to keep the two paths the same length
|
||||
skip:
|
||||
jmp y-- countloop ; Loop until Y hits 0, then pull a fresh PWM value from FIFO
|
||||
|
||||
% c-sdk {
|
||||
static inline void pwm_program_init(PIO pio, uint sm, uint offset, uint pin) {
|
||||
pio_gpio_init(pio, pin);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
|
||||
pio_sm_config c = pwm_program_get_default_config(offset);
|
||||
sm_config_set_sideset_pins(&c, pin);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
}
|
||||
%}
|
||||
3
src/sine_8khz.hpp
Normal file
3
src/sine_8khz.hpp
Normal file
File diff suppressed because one or more lines are too long
@@ -1,11 +1,150 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <event_groups.h>
|
||||
#include <Adafruit_SH110X.h>
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include <RotaryEncoder.h>
|
||||
#include <hardware/pwm.h>
|
||||
#include <hardware/gpio.h>
|
||||
#include <hardware/regs/pwm.h>
|
||||
#include "src/Config.hpp"
|
||||
#include "src/Audio.hpp"
|
||||
#include <limits>
|
||||
|
||||
void setup() {
|
||||
// put your setup code here, to run once:
|
||||
#include "src/sine_8khz.hpp"
|
||||
#include "src/200hz300hz_sr10khz_dur8sec.hpp"
|
||||
|
||||
constexpr float MIDDLE_C = 261.63;
|
||||
|
||||
inline int modulo(int a, int b) {
|
||||
if (b < 0)
|
||||
return modulo(-a, -b);
|
||||
const int result = a % b;
|
||||
return result >= 0 ? result : result + b;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// put your main code here, to run repeatedly:
|
||||
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUM_NEOPIXEL, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &SPI1, OLED_DC, OLED_RST, OLED_CS);
|
||||
|
||||
StaticSemaphore_t encoder_semaphore_buffer;
|
||||
SemaphoreHandle_t encoder_semaphore;
|
||||
|
||||
// Create the rotary encoder
|
||||
RotaryEncoder encoder(PIN_ROTA, PIN_ROTB, RotaryEncoder::LatchMode::FOUR3);
|
||||
void checkPosition()
|
||||
{
|
||||
encoder.tick();
|
||||
xSemaphoreGiveFromISR(encoder_semaphore, nullptr);
|
||||
} // just call tick() to check the state.
|
||||
// our encoder position state
|
||||
int encoder_pos = 0;
|
||||
|
||||
// Audio<2000> audioPlayer;
|
||||
|
||||
// struct audio_task_params
|
||||
// {
|
||||
// size_t size;
|
||||
// const uint8_t* data;
|
||||
// };
|
||||
|
||||
// audio_task_params params;
|
||||
// TaskHandle_t audio_task_handle;
|
||||
|
||||
// void audio_interrupt_func(uint8_t* inactive, uint8_t* active, size_t buffer_size)
|
||||
// {
|
||||
// vTaskNotifyGiveFromISR(audio_task_handle, nullptr);
|
||||
// }
|
||||
|
||||
// void audio_task_func(void* task_parameters)
|
||||
// {
|
||||
// auto& params = *reinterpret_cast<audio_task_params*>(task_parameters);
|
||||
// int offset = 0;
|
||||
// const uint8_t* end = params.data + params.size;
|
||||
// auto& first = audioPlayer.get_active_buffer();
|
||||
// auto& second = audioPlayer.get_inactive_buffer();
|
||||
// audioPlayer.set_callback(audio_interrupt_func);
|
||||
// memcpy(first.data(), params.data, first.size());
|
||||
// params.data += first.size();
|
||||
// memcpy(second.data(), params.data, second.size());
|
||||
// params.data += second.size();
|
||||
// pwm_set_enabled(pwm_gpio_to_slice_num(PIN_SPEAKER), true);
|
||||
// audioPlayer.start();
|
||||
// while(params.data + first.size() < end)
|
||||
// {
|
||||
// ulTaskNotifyTake(pdTRUE, std::numeric_limits<TickType_t>::max());
|
||||
// auto& inactive = audioPlayer.get_inactive_buffer();
|
||||
// memcpy(inactive.data(), params.data, inactive.size());
|
||||
// params.data += first.size();
|
||||
// }
|
||||
// while (1);
|
||||
// }
|
||||
|
||||
void setup()
|
||||
{
|
||||
encoder_semaphore = xSemaphoreCreateBinaryStatic(&encoder_semaphore_buffer);
|
||||
Serial.begin(115200);
|
||||
pixels.begin();
|
||||
pixels.setBrightness(255);
|
||||
pixels.show();
|
||||
// pixels.setPixelColor(3, 0xFFBF00);
|
||||
// pixels.show();
|
||||
pinMode(PIN_LED, OUTPUT);
|
||||
digitalWrite(PIN_LED, LOW);
|
||||
|
||||
// set rotary encoder inputs and interrupts
|
||||
pinMode(PIN_ROTA, INPUT_PULLUP);
|
||||
pinMode(PIN_ROTB, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(PIN_ROTA), checkPosition, CHANGE);
|
||||
attachInterrupt(digitalPinToInterrupt(PIN_ROTB), checkPosition, CHANGE);
|
||||
|
||||
// Start OLED
|
||||
display.begin(0, true); // we dont use the i2c address but we will reset!
|
||||
//display.display();
|
||||
display.clearDisplay();
|
||||
// text display tests
|
||||
display.setTextSize(1);
|
||||
display.setTextWrap(false);
|
||||
display.setTextColor(SH110X_WHITE, SH110X_BLACK); // white text, black background
|
||||
|
||||
// pinMode(PIN_SPEAKER_ENABLE, OUTPUT);
|
||||
// digitalWrite(PIN_SPEAKER_ENABLE, HIGH);
|
||||
// gpio_set_function(PIN_SPEAKER, GPIO_FUNC_PWM);
|
||||
// auto slice = pwm_gpio_to_slice_num(PIN_SPEAKER);
|
||||
// auto channel = pwm_gpio_to_channel(PIN_SPEAKER);
|
||||
// pwm_config conf;
|
||||
// pwm_config_set_output_polarity(&conf, false, false);
|
||||
// pwm_config_set_phase_correct(&conf, false);
|
||||
// pwm_config_set_clkdiv_mode(&conf, PWM_DIV_FREE_RUNNING);
|
||||
// pwm_config_set_wrap(&conf, 255);
|
||||
// pwm_init(slice, &conf, false);
|
||||
// pwm_set_chan_level(slice, channel, 128);
|
||||
// // if (!audioPlayer.init((void*)
|
||||
// // (PWM_BASE + (slice * (PWM_CH1_CTR_OFFSET - PWM_CH0_CTR_OFFSET)
|
||||
// // + PWM_CH0_CC_OFFSET + (channel ? 2 : 0)))))
|
||||
// if (!audioPlayer.init((void*)PWM_BASE + PWM_CH0_CC_OFFSET))
|
||||
// digitalWrite(PIN_LED, HIGH);
|
||||
// audioPlayer.set_sample_fraction(1, 13300);
|
||||
// params.data = wave_200hz300hz_sr10khz_dur8sec;
|
||||
// params.size = sizeof(wave_200hz300hz_sr10khz_dur8sec);
|
||||
// auto result = xTaskCreate(audio_task_func, "Audio Task",
|
||||
// 1024, ¶ms, 10, &audio_task_handle);
|
||||
|
||||
// tone(PIN_SPEAKER, 400, 500);
|
||||
// pwm_set_enabled(pwm_gpio_to_slice_num(PIN_SPEAKER), true);
|
||||
|
||||
// display.drawCircle(50, 50, 20, SH110X_WHITE);
|
||||
// display.display();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// display.printf("%d", random(9));
|
||||
// display.display();
|
||||
// delay(100);
|
||||
|
||||
for (int i = 0; i < 12; i++)
|
||||
pixels.setPixelColor(i, (modulo(encoder.getPosition(), 12) == i) ? 0xFF0000 : 0);
|
||||
pixels.show();
|
||||
delay(50);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user