Compare commits

..

No commits in common. "d4f8c94cd462aea83981605b5378da56a379cb04" and "e317595cdd7739fcc7850d8999264e9a62bfa444" have entirely different histories.

7 changed files with 74 additions and 252 deletions

View file

@ -1,34 +0,0 @@
cmake_minimum_required(VERSION 3.13)
# 1. Generate the map for your Neovim clangd linter
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Include the SDK's CMake entry point
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(clock C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
pico_sdk_init()
include_directories(include)
add_executable(clock
src/main.cpp
src/Gate.cpp
)
# Enable USB output (useful for later printf debugging)
pico_enable_stdio_usb(clock 1)
pico_enable_stdio_uart(clock 0)
# Pull in standard library and hardware abstraction
target_link_libraries(clock
pico_stdlib
hardware_gpio
hardware_i2c
)
# Create the .uf2 file
pico_add_extra_outputs(clock)

View file

@ -1,13 +1,11 @@
// Gate.cpp
#include "pico/stdlib.h"
#include "Gate.h"
// Out.cpp
#include "Arduino.h"
#include "Out.h"
#include "globals.h"
#include <string>
#include <cstdlib>
Gate::Gate(uint8_t pin) {
Out::Out(byte pin) {
this->pin = pin;
state = 0;
state = LOW;
divideMode = 1; // 1 divison | 0 multiplication
modifier = 1; // divide mode modifier (4x, /32, etc)
@ -20,55 +18,58 @@ Gate::Gate(uint8_t pin) {
len = 0; // max len a pulse can be on, as determined by width
p = 100; // probability of a pulse
pinMode(pin, OUTPUT);
}
bool Gate::getState() {
int Out::getState() {
return state;
}
void Gate::setLen(uint32_t currentPeriod) {
len = (uint32_t)((double)currentPeriod * (width / 100.0) / 1000.0);
void Out::setLen(unsigned long currentPeriod) {
len = (unsigned long)((double)currentPeriod * (width / 100.0) / 1000.0);
}
void Gate::setDiv(uint16_t modifier, uint8_t divide) {
void Out::setDiv(int modifier, byte divide = 1) {
if (divide == 1) {
div = ppqn * modifier;
divString = "/" + std::to_string(modifier);
divString = "/" + modifier;
} else {
div = ppqn / modifier;
divString = "x" + std::to_string(modifier);
divString = "x" + modifier;
}
divideMode = divide;
this->modifier = modifier;
};
void Gate::setWidth(uint16_t newWidth) {
void Out::setWidth(int newWidth) {
width = newWidth;
if (divideMode == 1) {
len = (uint32_t)((double)(minute / BPM) * (width / 100.0) / 1000.0);
len = (unsigned long)((double)(minute / BPM) * (width / 100.0) / 1000.0);
} else {
len = (uint32_t)((double)(minute / BPM / modifier) * (width / 100.0) / 1000.0);
len = (unsigned long)((double)(minute / BPM / modifier) * (width / 100.0) / 1000.0);
}
};
void Gate::setP(uint16_t prob) {
void Out::setP(int prob) {
this->p = prob;
}
void Gate::turnOn() {
void Out::turnOn() {
cycle += 1;
uint8_t pRes = 1;
byte pRes = 1;
if (cycle == div) {
if (p < 100) {
uint32_t r = (rand() % 100) + 1;
long r = random(1, 101);
if (r > p) {
pRes = 0;
}
}
if (pRes == 1) {
state = 1;
state = HIGH;
digitalWrite(pin, state);
dur = millis();
}
@ -76,9 +77,9 @@ void Gate::turnOn() {
};
}
void Gate::turnOff() {
if (state == 1 && millis() - dur >= len) {
state = 0;
void Out::turnOff() {
if (state == HIGH && millis() - dur >= len) {
state = LOW;
digitalWrite(pin, state);
dur = 0;
};

33
Out.h Normal file
View file

@ -0,0 +1,33 @@
// Out.h
#ifndef Out_h
#define Out_h
#include <Arduino.h>
class Out {
private:
byte pin;
unsigned char state;
int cycle;
unsigned long dur;
unsigned long len;
byte width;
byte divideMode;
int div;
int modifier;
String divString;
int p;
public:
Out(byte pin);
void turnOn();
void turnOff();
void setLen(unsigned long currentPeriod);
void setDiv(int newDiv, byte divide = 1);
void setWidth(int newWidth);
void setP(int prob);
int getState();
};
#endif

View file

@ -1,8 +1,12 @@
#ifndef GLOBALS_H
#define GLOBALS_H
#include <cstdint>
#include <Arduino.h>
extern byte BPM;
extern unsigned long minute;
extern unsigned long period;
extern byte ppqn;
#endif // GLOBALS_H
/*

View file

@ -1,36 +0,0 @@
// Gate.h
#ifndef Gate_h
#define Gate_h
#include <cstdint>
#include <string>
class Gate {
private:
bool state;
int16_t cycle;
uint32_t dur;
uint32_t len;
uint8_t width;
uint8_t divideMode;
uint16_t div;
uint16_t modifier;
std::string divString;
uint8_t p;
public:
Gate(uint8_t pin);
uint8_t pin;
void turnOn();
void turnOff();
void setLen(uint32_t currentPeriod);
void setDiv(uint16_t newDiv, uint8_t divide = 1);
void setWidth(uint16_t newWidth);
void setP(uint16_t prob);
bool getState();
};
#endif

View file

@ -45,10 +45,6 @@ unsigned long screenLastUpdate = 0;
const unsigned long screenThrottle = 200;
byte forceScreenUpdate = 1;
byte currentScreen = 0;
byte editMode = 0;
int mainScreenCursorPos = 0;
byte maxMainScreenPos = 8;
void setup() {
Serial.begin(9600);
@ -62,7 +58,6 @@ void setup() {
// screen setup
u8g2.begin();
u8g2.setFontMode(1);
// display.clearDisplay();
// display.setTextSize(2);
@ -155,39 +150,16 @@ void updateScreen() {
if (currentTime - screenLastUpdate >= screenThrottle && forceScreenUpdate == 1) {
screenLastUpdate = currentTime;
forceScreenUpdate = 0;
// The firstPage()/nextPage() loop manages where the drawing commands go
u8g2.firstPage();
do {
// 12px - nonbold
if (mainScreenCursorPos == 0) {
u8g2.setFont(u8g2_font_7x14B_mf);
} else {
u8g2.setFont(u8g2_font_7x14_mf);
}
u8g2.setCursor(0, 15);
// --- Drawing Commands for the CURRENT Page ---
// All drawing commands must live INSIDE this do/while loop.
u8g2.setFont(u8g2_font_helvR08_tf);
u8g2.setCursor(0, 10);
u8g2.print(F("BPM: "));
u8g2.print(BPM);
u8g2.print(BPM); // Example of dynamic data
u8g2.setFont(u8g2_font_7x14_mf);
u8g2.setCursor(0, 45);
char buffer[5];
for (byte i = 1; i < 9; i++) {
if (i == 5) {
u8g2.setCursor(0, 60);
}
if (mainScreenCursorPos == i) {
u8g2.setFont(u8g2_font_7x14B_mf);
}
sprintf(buffer, "[%d] ", i);
u8g2.print(buffer);
if (mainScreenCursorPos == i) {
u8g2.setFont(u8g2_font_7x14_mf);
}
};
} while (u8g2.nextPage());
}
}
@ -215,21 +187,10 @@ void checkRPot() {
Serial.print("Encoder Position: ");
Serial.println(currentPos);
// on home screen
if (currentScreen == 0) {
if (editMode == 0) {
if (currentPos > previousPos) {
mainScreenCursorPos++;
if (mainScreenCursorPos > maxMainScreenPos) {
mainScreenCursorPos = 0;
}
BPM++;
} else {
mainScreenCursorPos--;
if (mainScreenCursorPos < 0) {
mainScreenCursorPos = maxMainScreenPos;
}
}
}
BPM--;
}
forceScreenUpdate = 1;
@ -241,17 +202,6 @@ void checkRPot() {
}
}
void handleBPMChange(byte increase) {
if (increase == 1) {
BPM++;
} else {
BPM--;
}
period = (minute / BPM) / ppqn;
Timer1.setPeriod(period);
}
void updateEncoder() {
// The ISR should be as short and fast as possible
// Check the state of the DT pin to determine direction

View file

@ -1,96 +0,0 @@
#include <stdio.h>
#include "hardware/structs/rosc.h"
#include "pico/stdlib.h"
#include "pico/time.h"
#include <cstdint>
#include "globals.h"
#include "Gate.h"
static constexpr uint8_t OUT_1_PIN = 0;
static constexpr uint8_t OUT_2_PIN = 2;
static constexpr uint8_t OUT_3_PIN = 4;
static constexpr uint8_t OUT_4_PIN = 6;
static constexpr uint8_t OUT_5_PIN = 8;
static constexpr uint8_t OUT_6_PIN = 10;
static constexpr uint8_t OUT_7_PIN = 12;
static constexpr uint8_t OUT_8_PIN = 14;
static constexpr uint8_t SCREEN_SCL_PIN = 18;
static constexpr uint8_t SCREEN_SDA_PIN = 19;
static constexpr uint8_t ENCODER_CLK_PIN = 20;
static constexpr uint8_t ENCODER_DT_PIN = 21;
static constexpr uint8_t ENCODER_SW_PIN = 22;
volatile uint8_t PLAY = 1;
volatile uint8_t BPM = 100;
static constexpr uint32_t MINUTE_US = 60000000;
static constexpr uint8_t PPQN = 96;
volatile uint32_t period_us = 0;
struct repeating_timer bpm_timer;
volatile bool beatToggle = false;
Gate out1(OUT_1_PIN);
Gate out2(OUT_2_PIN);
Gate out3(OUT_3_PIN);
Gate out4(OUT_4_PIN);
Gate out5(OUT_5_PIN);
Gate out6(OUT_6_PIN);
Gate out7(OUT_7_PIN);
Gate out8(OUT_8_PIN);
bool timer_callback(struct repeating_timer *t) {
if (PLAY == 1) {
beatToggle = true;
}
return true;
}
void init_timer(uint32_t period_us) {
cancel_repeating_timer(&bpm_timer);
add_repeating_timer_us(-(int64_t)period_us, timer_callback, NULL, &bpm_timer);
}
void update_period() {
period_us = (uint32_t)(MINUTE_US / (uint32_t)BPM / PPQN);
init_timer(period_us);
}
int main() {
stdio_init_all();
srand(rosc_hw->randombit);
gpio_init(out1.pin);
gpio_init(out2.pin);
gpio_init(out3.pin);
gpio_init(out4.pin);
gpio_init(out5.pin);
gpio_init(out6.pin);
gpio_init(out7.pin);
gpio_init(out8.pin);
gpio_set_dir(out1.pin, GPIO_OUT);
gpio_set_dir(out2.pin, GPIO_OUT);
gpio_set_dir(out3.pin, GPIO_OUT);
gpio_set_dir(out4.pin, GPIO_OUT);
gpio_set_dir(out5.pin, GPIO_OUT);
gpio_set_dir(out6.pin, GPIO_OUT);
gpio_set_dir(out7.pin, GPIO_OUT);
gpio_set_dir(out8.pin, GPIO_OUT);
update_period();
while (true) {
}
}