cs-midi/platform/pico_shim.h

237 lines
6.7 KiB
C++

#pragma once
// pico_shim.h — pico-sdk replacements for Arduino primitives
// Used by cs-midi, extracted from tttapa/Control-Surface (GPL-3.0)
#include <cstdint>
#include <cstddef>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <cstdio>
#include "pico/stdlib.h"
#include "pico/time.h"
#include "hardware/gpio.h"
// ---------------------------------------------------------------------------
// Number format bases (Arduino constants)
// ---------------------------------------------------------------------------
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
// ---------------------------------------------------------------------------
// Time
// ---------------------------------------------------------------------------
static inline unsigned long millis() {
return (unsigned long)to_ms_since_boot(get_absolute_time());
}
static inline unsigned long micros() {
return (unsigned long)to_us_since_boot(get_absolute_time());
}
static inline void delay(unsigned long ms) {
sleep_ms(ms);
}
// ---------------------------------------------------------------------------
// Flash strings (identity on ARM — unified address space)
// ---------------------------------------------------------------------------
struct __FlashStringHelper;
#define F(x) (reinterpret_cast<const __FlashStringHelper *>(x))
using FlashString_t = const __FlashStringHelper *;
#define PROGMEM
#define pgm_read_byte_near(ptr) (*((const uint8_t *)(ptr)))
#define pgm_read_ptr_near(ptr) ((void *)*(ptr))
// ---------------------------------------------------------------------------
// Print / Printable
// ---------------------------------------------------------------------------
class Printable;
class Print {
public:
virtual ~Print() = default;
virtual size_t write(uint8_t) = 0;
virtual size_t write(const uint8_t *buf, size_t len) {
size_t n = 0;
while (len--) n += write(*buf++);
return n;
}
size_t write(const char *str) {
if (!str) return 0;
return write((const uint8_t *)str, std::strlen(str));
}
virtual void flush() {}
// print: strings
size_t print(const __FlashStringHelper *s) {
return write(reinterpret_cast<const char *>(s));
}
size_t print(const char *s) { return write(s); }
size_t print(char c) { return write((uint8_t)c); }
// print: integers
size_t print(long n, int base = DEC) {
if (base == DEC && n < 0) {
size_t t = write('-');
return t + printUnsigned((unsigned long)(-n), base);
}
return printUnsigned((unsigned long)n, base);
}
size_t print(int n, int base = DEC) { return print((long)n, base); }
size_t print(unsigned long n, int base = DEC) {
return printUnsigned(n, base);
}
size_t print(unsigned int n, int base = DEC) {
return print((unsigned long)n, base);
}
size_t print(unsigned char n, int base = DEC) {
return print((unsigned long)n, base);
}
// print: float/double
size_t print(double d, int prec = 2) {
char buf[32];
std::snprintf(buf, sizeof(buf), "%.*f", prec, d);
return write(buf);
}
// print: bool
size_t print(bool b) { return print(b ? "true" : "false"); }
// print: Printable
size_t print(const Printable &p);
// println
size_t println() { return write("\r\n"); }
template <class T>
size_t println(T v) { size_t n = print(v); return n + println(); }
template <class T>
size_t println(T v, int fmt) { size_t n = print(v, fmt); return n + println(); }
private:
size_t printUnsigned(unsigned long n, int base) {
char buf[8 * sizeof(long) + 1];
char *p = buf + sizeof(buf) - 1;
*p = '\0';
if (n == 0) { *--p = '0'; }
else {
while (n > 0) {
uint8_t d = n % base;
*--p = d < 10 ? '0' + d : 'A' + d - 10;
n /= base;
}
}
return write(p);
}
};
class Printable {
public:
virtual ~Printable() = default;
virtual size_t printTo(Print &p) const = 0;
};
inline size_t Print::print(const Printable &p) { return p.printTo(*this); }
// ---------------------------------------------------------------------------
// Macros
// ---------------------------------------------------------------------------
#ifndef constrain
#define constrain(amt, low, high) \
((amt) < (low) ? (low) : ((amt) > (high) ? (high) : (amt)))
#endif
#define HIGH 0x1
#define LOW 0x0
#define INPUT 0x0
#define OUTPUT 0x1
#define INPUT_PULLUP 0x2
#define LED_BUILTIN 25
typedef bool boolean;
// ---------------------------------------------------------------------------
// GPIO — real implementations via pico-sdk
// ---------------------------------------------------------------------------
static inline void pinMode(uint8_t pin, uint8_t mode) {
gpio_init(pin);
if (mode == OUTPUT)
gpio_set_dir(pin, GPIO_OUT);
else {
gpio_set_dir(pin, GPIO_IN);
if (mode == INPUT_PULLUP)
gpio_pull_up(pin);
}
}
static inline void digitalWrite(uint8_t pin, uint8_t val) {
gpio_put(pin, val);
}
static inline int digitalRead(uint8_t pin) {
return gpio_get(pin) ? HIGH : LOW;
}
// ---------------------------------------------------------------------------
// ADC
// ---------------------------------------------------------------------------
#include "hardware/adc.h"
#define NUM_DIGITAL_PINS 48
#define NUM_ANALOG_INPUTS 8
static inline int analogRead(uint8_t pin) {
// GPIO 26-29 = ADC 0-3 on RP2350
uint8_t ch = pin;
if (pin >= 26) ch = pin - 26;
adc_select_input(ch);
return (int)adc_read();
}
static inline void analogReadResolution(int) {}
static inline void analogWrite(uint8_t, int) {}
// ---------------------------------------------------------------------------
// Shift register
// ---------------------------------------------------------------------------
#define MSBFIRST 1
#define LSBFIRST 0
static inline void shiftOut(uint8_t dataPin, uint8_t clockPin,
uint8_t bitOrder, uint8_t val) {
for (uint8_t i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
gpio_put(dataPin, (val >> i) & 1);
else
gpio_put(dataPin, (val >> (7 - i)) & 1);
gpio_put(clockPin, 1);
gpio_put(clockPin, 0);
}
}
// ---------------------------------------------------------------------------
// Misc
// ---------------------------------------------------------------------------
static inline void yield() {}
static inline void cli() { __asm volatile("cpsid i"); }
static inline void sei() { __asm volatile("cpsie i"); }
#define noInterrupts() cli()
#define interrupts() sei()