kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Merge pull request #711 from pimoroni/patch-jpegdec-filename
MicroPython: Avoid heap allocations in all C++ modules.pull/723/head v1.19.17
commit
cb5db1d594
|
@ -1,172 +0,0 @@
|
|||
name: MicroPython for Badger2040
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
env:
|
||||
MICROPYTHON_VERSION: 294098d28e2bad0ac0aad0d72595d11a82798096
|
||||
BOARD_TYPE: PIMORONI_BADGER2040
|
||||
# MicroPython version will be contained in github.event.release.tag_name for releases
|
||||
RELEASE_FILE: pimoroni-badger2040-${{github.event.release.tag_name || github.sha}}-micropython
|
||||
|
||||
jobs:
|
||||
deps:
|
||||
runs-on: ubuntu-20.04
|
||||
name: Dependencies
|
||||
steps:
|
||||
- name: Workspace Cache
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{runner.workspace}}
|
||||
key: workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
restore-keys: |
|
||||
workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
|
||||
# Check out MicroPython
|
||||
- name: Checkout MicroPython
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: micropython/micropython
|
||||
ref: ${{env.MICROPYTHON_VERSION}}
|
||||
submodules: false # MicroPython submodules are hideously broken
|
||||
path: micropython
|
||||
|
||||
- name: Fetch base MicroPython submodules
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
working-directory: micropython
|
||||
run: git submodule update --init
|
||||
|
||||
- name: Fetch Pico SDK submodules
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
working-directory: micropython/lib/pico-sdk
|
||||
run: git submodule update --init
|
||||
|
||||
- name: Build mpy-cross
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
working-directory: micropython/mpy-cross
|
||||
run: make
|
||||
|
||||
build:
|
||||
needs: deps
|
||||
name: Build Badger 2040
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Compiler Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /home/runner/.ccache
|
||||
key: ccache-micropython-badger2040-${{github.ref}}-${{github.sha}}
|
||||
restore-keys: |
|
||||
ccache-micropython-badger2040-${{github.ref}}
|
||||
ccache-micropython-badger2040-
|
||||
|
||||
- name: Workspace Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{runner.workspace}}
|
||||
key: workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
restore-keys: |
|
||||
workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
path: pimoroni-pico-${{ github.sha }}
|
||||
|
||||
- name: "HACK: MicroPython Board Fixups"
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
../../../pimoroni-pico-${GITHUB_SHA}/micropython/_board/board-fixup.sh badger2040 ${{env.BOARD_TYPE}} ../../../pimoroni-pico-${GITHUB_SHA}/micropython/_board
|
||||
|
||||
# Linux deps
|
||||
- name: Install Compiler & CCache
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt update && sudo apt install ccache gcc-arm-none-eabi
|
||||
python3 -m pip install pillow
|
||||
|
||||
# Build without BadgerOS
|
||||
- name: Configure MicroPython (No BadgerOS)
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
cmake -S . -B build-${{env.BOARD_TYPE}}-without-badger-os -DBADGER2040_NO_MODULES=1 -DPICO_BUILD_DOCS=0 -DUSER_C_MODULES=../../../pimoroni-pico-${GITHUB_SHA}/micropython/modules/badger2040-micropython.cmake -DMICROPY_BOARD=${{env.BOARD_TYPE}} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build MicroPython (No BadgerOS)
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
ccache --zero-stats || true
|
||||
cmake --build build-${{env.BOARD_TYPE}}-without-badger-os -j 2
|
||||
ccache --show-stats || true
|
||||
|
||||
- name: Rename .uf2 for artifact (No BadgerOS)
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2/build-${{env.BOARD_TYPE}}-without-badger-os
|
||||
run: |
|
||||
cp firmware.uf2 ${{env.RELEASE_FILE}}-without-badger-os.uf2
|
||||
|
||||
- name: Store .uf2 as artifact (No BadgerOS)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{env.RELEASE_FILE}}-without-badger-os.uf2
|
||||
path: micropython/ports/rp2/build-${{env.BOARD_TYPE}}-without-badger-os/${{env.RELEASE_FILE}}-without-badger-os.uf2
|
||||
|
||||
- name: Upload .uf2 (No BadgerOS)
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
with:
|
||||
asset_path: micropython/ports/rp2/build-${{env.BOARD_TYPE}}-without-badger-os/${{env.RELEASE_FILE}}-without-badger-os.uf2
|
||||
upload_url: ${{github.event.release.upload_url}}
|
||||
asset_name: ${{env.RELEASE_FILE}}-without-badger-os.uf2
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
# Build with BadgerOS
|
||||
- name: Configure MicroPython
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
cmake -S . -B build-${{env.BOARD_TYPE}} -DPICO_BUILD_DOCS=0 -DUSER_C_MODULES=../../../pimoroni-pico-${GITHUB_SHA}/micropython/modules/badger2040-micropython.cmake -DMICROPY_BOARD=${{env.BOARD_TYPE}} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build MicroPython
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
ccache --zero-stats || true
|
||||
cmake --build build-${{env.BOARD_TYPE}} -j 2
|
||||
ccache --show-stats || true
|
||||
|
||||
- name: Rename .uf2 for artifact
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2/build-${{env.BOARD_TYPE}}
|
||||
run: |
|
||||
cp firmware.uf2 ${{env.RELEASE_FILE}}.uf2
|
||||
|
||||
- name: Store .uf2 as artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{env.RELEASE_FILE}}.uf2
|
||||
path: micropython/ports/rp2/build-${{env.BOARD_TYPE}}/${{env.RELEASE_FILE}}.uf2
|
||||
|
||||
- name: Upload .uf2
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
with:
|
||||
asset_path: micropython/ports/rp2/build-${{env.BOARD_TYPE}}/${{env.RELEASE_FILE}}.uf2
|
||||
upload_url: ${{github.event.release.upload_url}}
|
||||
asset_name: ${{env.RELEASE_FILE}}.uf2
|
||||
asset_content_type: application/octet-stream
|
|
@ -1,164 +0,0 @@
|
|||
name: MicroPython for Badger2040W
|
||||
|
||||
on:
|
||||
push:
|
||||
pull_request:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
env:
|
||||
MICROPYTHON_VERSION: 294098d28e2bad0ac0aad0d72595d11a82798096
|
||||
BOARD_TYPE: PIMORONI_BADGER2040W
|
||||
# MicroPython version will be contained in github.event.release.tag_name for releases
|
||||
RELEASE_FILE: pimoroni-badger2040w-${{github.event.release.tag_name || github.sha}}-micropython
|
||||
|
||||
jobs:
|
||||
deps:
|
||||
runs-on: ubuntu-20.04
|
||||
name: Dependencies
|
||||
steps:
|
||||
- name: Workspace Cache
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{runner.workspace}}
|
||||
key: workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
restore-keys: |
|
||||
workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
|
||||
# Check out MicroPython
|
||||
- name: Checkout MicroPython
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: micropython/micropython
|
||||
ref: ${{env.MICROPYTHON_VERSION}}
|
||||
submodules: false # MicroPython submodules are hideously broken
|
||||
path: micropython
|
||||
|
||||
- name: Fetch base MicroPython submodules
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
working-directory: micropython
|
||||
run: git submodule update --init
|
||||
|
||||
- name: Fetch Pico SDK submodules
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
working-directory: micropython/lib/pico-sdk
|
||||
run: git submodule update --init
|
||||
|
||||
- name: Build mpy-cross
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
shell: bash
|
||||
working-directory: micropython/mpy-cross
|
||||
run: make
|
||||
|
||||
build:
|
||||
needs: deps
|
||||
name: Build Badger 2040W
|
||||
runs-on: ubuntu-20.04
|
||||
|
||||
steps:
|
||||
- name: Compiler Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: /home/runner/.ccache
|
||||
key: ccache-micropython-badger2040w-${{github.ref}}-${{github.sha}}
|
||||
restore-keys: |
|
||||
ccache-micropython-badger2040w-${{github.ref}}
|
||||
ccache-micropython-badger2040w-
|
||||
|
||||
- name: Workspace Cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{runner.workspace}}
|
||||
key: workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
restore-keys: |
|
||||
workspace-micropython-${{env.MICROPYTHON_VERSION}}
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: true
|
||||
path: pimoroni-pico-${{ github.sha }}
|
||||
|
||||
# Check out dir2u2f
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
repository: gadgetoid/dir2uf2
|
||||
ref: v0.0.1
|
||||
path: dir2uf2
|
||||
|
||||
- name: "HACK: MicroPython Board Fixups"
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
../../../pimoroni-pico-${GITHUB_SHA}/micropython/_board/board-fixup.sh badger2040w ${{env.BOARD_TYPE}} ../../../pimoroni-pico-${GITHUB_SHA}/micropython/_board
|
||||
|
||||
# Linux deps
|
||||
- name: Install Compiler & CCache
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt update && sudo apt install ccache gcc-arm-none-eabi
|
||||
python3 -m pip install pillow
|
||||
|
||||
# Build firmware
|
||||
- name: Configure MicroPython
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
cmake -S . -B build-${{env.BOARD_TYPE}} -DPICO_BUILD_DOCS=0 -DUSER_C_MODULES=../../../pimoroni-pico-${GITHUB_SHA}/micropython/modules/micropython-badger2040w.cmake -DMICROPY_BOARD=${{env.BOARD_TYPE}} -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
|
||||
- name: Build MicroPython
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2
|
||||
run: |
|
||||
ccache --zero-stats || true
|
||||
cmake --build build-${{env.BOARD_TYPE}} -j 2
|
||||
ccache --show-stats || true
|
||||
|
||||
- name: Rename .uf2 for artifact
|
||||
shell: bash
|
||||
working-directory: micropython/ports/rp2/build-${{env.BOARD_TYPE}}
|
||||
run: |
|
||||
cp firmware.uf2 ${{env.RELEASE_FILE}}.uf2
|
||||
|
||||
- name: Append Filesystem
|
||||
shell: bash
|
||||
run: |
|
||||
python3 -m pip install littlefs-python
|
||||
./dir2uf2/dir2uf2 --append-to micropython/ports/rp2/build-${{env.BOARD_TYPE}}/${{env.RELEASE_FILE}}.uf2 --manifest pimoroni-pico-${{ github.sha }}/micropython/examples/badger2040w/uf2-manifest.txt --filename with-examples.uf2 pimoroni-pico-${{ github.sha }}/micropython/examples/badger2040w/
|
||||
|
||||
- name: Store .uf2 as artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{env.RELEASE_FILE}}.uf2
|
||||
path: micropython/ports/rp2/build-${{env.BOARD_TYPE}}/${{env.RELEASE_FILE}}.uf2
|
||||
|
||||
- name: Store .uf2 + examples as artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{env.RELEASE_FILE}}-with-examples.uf2
|
||||
path: ${{env.RELEASE_FILE}}-with-examples.uf2
|
||||
|
||||
- name: Upload .uf2
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
with:
|
||||
asset_path: micropython/ports/rp2/build-${{env.BOARD_TYPE}}/${{env.RELEASE_FILE}}.uf2
|
||||
upload_url: ${{github.event.release.upload_url}}
|
||||
asset_name: ${{env.RELEASE_FILE}}.uf2
|
||||
asset_content_type: application/octet-stream
|
||||
|
||||
- name: Upload .uf2 + examples
|
||||
if: github.event_name == 'release'
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
|
||||
with:
|
||||
asset_path: ${{env.RELEASE_FILE}}-with-examples.uf2
|
||||
upload_url: ${{github.event.release.upload_url}}
|
||||
asset_name: ${{env.RELEASE_FILE}}-with-examples.uf2
|
||||
asset_content_type: application/octet-stream
|
|
@ -7,7 +7,7 @@ on:
|
|||
types: [created]
|
||||
|
||||
env:
|
||||
MICROPYTHON_VERSION: 294098d28e2bad0ac0aad0d72595d11a82798096
|
||||
MICROPYTHON_VERSION: 05bb26010e4a466a82cfed179f8d8d0b406a78ca
|
||||
|
||||
jobs:
|
||||
deps:
|
||||
|
|
|
@ -7,7 +7,7 @@ on:
|
|||
types: [created]
|
||||
|
||||
env:
|
||||
MICROPYTHON_VERSION: 294098d28e2bad0ac0aad0d72595d11a82798096
|
||||
MICROPYTHON_VERSION: 05bb26010e4a466a82cfed179f8d8d0b406a78ca
|
||||
|
||||
jobs:
|
||||
deps:
|
||||
|
|
|
@ -11,7 +11,10 @@ namespace pimoroni {
|
|||
gpio_pull_up(interrupt);
|
||||
}
|
||||
|
||||
device.intf_ptr = new i2c_intf_ptr{.i2c = i2c, .address = address};
|
||||
i2c_interface.i2c = i2c;
|
||||
i2c_interface.address = address;
|
||||
|
||||
device.intf_ptr = &i2c_interface;
|
||||
device.intf = bme280_intf::BME280_I2C_INTF;
|
||||
device.read = (bme280_read_fptr_t)&read_bytes;
|
||||
device.write = (bme280_write_fptr_t)&write_bytes;
|
||||
|
|
|
@ -26,6 +26,8 @@ namespace pimoroni {
|
|||
bool status;
|
||||
};
|
||||
|
||||
i2c_intf_ptr i2c_interface;
|
||||
|
||||
bool debug = false;
|
||||
|
||||
bool init();
|
||||
|
|
|
@ -11,8 +11,10 @@ namespace pimoroni {
|
|||
gpio_pull_up(interrupt);
|
||||
}
|
||||
|
||||
device.intf_ptr = new i2c_intf_ptr{.i2c = i2c, .address = address};
|
||||
i2c_interface.i2c = i2c;
|
||||
i2c_interface.address = address;
|
||||
|
||||
device.intf_ptr = &i2c_interface;
|
||||
device.intf = bme68x_intf::BME68X_I2C_INTF;
|
||||
device.read = (bme68x_read_fptr_t)&read_bytes;
|
||||
device.write = (bme68x_write_fptr_t)&write_bytes;
|
||||
|
|
|
@ -18,6 +18,8 @@ namespace pimoroni {
|
|||
int8_t address;
|
||||
};
|
||||
|
||||
i2c_intf_ptr i2c_interface;
|
||||
|
||||
bool debug = true;
|
||||
|
||||
bool init();
|
||||
|
|
|
@ -11,7 +11,10 @@ namespace pimoroni {
|
|||
gpio_pull_up(interrupt);
|
||||
}
|
||||
|
||||
device.intf_ptr = new i2c_intf_ptr{.i2c = i2c, .address = address};
|
||||
i2c_interface.i2c = i2c;
|
||||
i2c_interface.address = address;
|
||||
|
||||
device.intf_ptr = &i2c_interface;
|
||||
device.intf = BMP280_I2C_INTF;
|
||||
device.read = (bmp280_com_fptr_t)&read_bytes;
|
||||
device.write = (bmp280_com_fptr_t)&write_bytes;
|
||||
|
|
|
@ -25,6 +25,8 @@ namespace pimoroni {
|
|||
bool status;
|
||||
};
|
||||
|
||||
i2c_intf_ptr i2c_interface;
|
||||
|
||||
bool debug = false;
|
||||
|
||||
bool init();
|
||||
|
|
|
@ -29,8 +29,6 @@ namespace motor {
|
|||
}
|
||||
|
||||
MotorCluster::~MotorCluster() {
|
||||
delete[] states;
|
||||
delete[] configs;
|
||||
}
|
||||
|
||||
bool MotorCluster::init() {
|
||||
|
@ -713,10 +711,8 @@ namespace motor {
|
|||
float deadzone, DecayMode mode, bool auto_phase) {
|
||||
uint8_t motor_count = pwms.get_chan_pair_count();
|
||||
if(motor_count > 0) {
|
||||
states = new MotorState[motor_count];
|
||||
configs = new motor_config[motor_count];
|
||||
|
||||
for(uint motor = 0; motor < motor_count; motor++) {
|
||||
configs[motor] = motor_config();
|
||||
states[motor] = MotorState(direction, speed_scale, zeropoint, deadzone);
|
||||
configs[motor].phase = (auto_phase) ? (float)motor / (float)motor_count : 0.0f;
|
||||
configs[motor].mode = mode;
|
||||
|
|
|
@ -22,12 +22,15 @@ namespace motor {
|
|||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
static const uint MAX_MOTOR_CHANNELS = 16;
|
||||
|
||||
private:
|
||||
PWMCluster pwms;
|
||||
uint32_t pwm_period;
|
||||
float pwm_frequency;
|
||||
MotorState* states;
|
||||
motor_config* configs;
|
||||
MotorState states[MAX_MOTOR_CHANNELS];
|
||||
motor_config configs[MAX_MOTOR_CHANNELS];
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
|
|
|
@ -27,7 +27,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, uint pin_mask, bool loading_zone)
|
|||
, sm(sm)
|
||||
, pin_mask(pin_mask & ((1u << NUM_BANK0_GPIOS) - 1))
|
||||
, channel_count(0)
|
||||
, channels(nullptr)
|
||||
, wrap_level(0)
|
||||
, loading_zone(loading_zone) {
|
||||
|
||||
|
@ -48,7 +47,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, uint pin_base, uint pin_count, bool loa
|
|||
, sm(sm)
|
||||
, pin_mask(0x00000000)
|
||||
, channel_count(0)
|
||||
, channels(nullptr)
|
||||
, wrap_level(0)
|
||||
, loading_zone(loading_zone) {
|
||||
|
||||
|
@ -68,7 +66,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, const uint8_t *pins, uint32_t length, b
|
|||
, sm(sm)
|
||||
, pin_mask(0x00000000)
|
||||
, channel_count(0)
|
||||
, channels(nullptr)
|
||||
, wrap_level(0)
|
||||
, loading_zone(loading_zone) {
|
||||
|
||||
|
@ -90,7 +87,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, std::initializer_list<uint8_t> pins, bo
|
|||
, sm(sm)
|
||||
, pin_mask(0x00000000)
|
||||
, channel_count(0)
|
||||
, channels(nullptr)
|
||||
, wrap_level(0)
|
||||
, loading_zone(loading_zone) {
|
||||
|
||||
|
@ -111,7 +107,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, const pin_pair *pin_pairs, uint32_t len
|
|||
, sm(sm)
|
||||
, pin_mask(0x00000000)
|
||||
, channel_count(0)
|
||||
, channels(nullptr)
|
||||
, wrap_level(0)
|
||||
, loading_zone(loading_zone) {
|
||||
|
||||
|
@ -137,7 +132,6 @@ PWMCluster::PWMCluster(PIO pio, uint sm, std::initializer_list<pin_pair> pin_pai
|
|||
, sm(sm)
|
||||
, pin_mask(0x00000000)
|
||||
, channel_count(0)
|
||||
, channels(nullptr)
|
||||
, wrap_level(0)
|
||||
, loading_zone(loading_zone) {
|
||||
|
||||
|
@ -159,8 +153,8 @@ PWMCluster::PWMCluster(PIO pio, uint sm, std::initializer_list<pin_pair> pin_pai
|
|||
|
||||
void PWMCluster::constructor_common() {
|
||||
// Initialise all the channels this PWM will control
|
||||
if(channel_count > 0) {
|
||||
channels = new ChannelState[channel_count];
|
||||
for(uint i = 0; i < channel_count; i++) {
|
||||
channels[i] = ChannelState();
|
||||
}
|
||||
|
||||
// Set up the transition buffers
|
||||
|
@ -216,8 +210,6 @@ PWMCluster::~PWMCluster() {
|
|||
gpio_set_function(channel_to_pin_map[channel], GPIO_FUNC_NULL);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] channels;
|
||||
}
|
||||
|
||||
void PWMCluster::dma_interrupt_handler() {
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace pimoroni {
|
|||
public:
|
||||
static const uint BUFFER_SIZE = 64; // Set to 64, the maximum number of single rises and falls for 32 channels within a looping time period
|
||||
static const uint NUM_BUFFERS = 3;
|
||||
static const uint MAX_PWM_CHANNELS = 32;
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
|
@ -104,7 +105,7 @@ namespace pimoroni {
|
|||
int dma_channel;
|
||||
uint pin_mask;
|
||||
uint8_t channel_count;
|
||||
ChannelState* channels;
|
||||
ChannelState channels[NUM_BANK0_GPIOS];
|
||||
uint8_t channel_to_pin_map[NUM_BANK0_GPIOS];
|
||||
uint wrap_level;
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace servo {
|
|||
}
|
||||
|
||||
Calibration::Calibration()
|
||||
: calibration(nullptr), calibration_size(0), limit_lower(true), limit_upper(true) {
|
||||
: calibration_size(0), limit_lower(true), limit_upper(true) {
|
||||
}
|
||||
|
||||
Calibration::Calibration(CalibrationType default_type)
|
||||
|
@ -19,7 +19,7 @@ namespace servo {
|
|||
}
|
||||
|
||||
Calibration::Calibration(const Calibration &other)
|
||||
: calibration(nullptr), calibration_size(0), limit_lower(other.limit_lower), limit_upper(other.limit_upper) {
|
||||
: calibration_size(0), limit_lower(other.limit_lower), limit_upper(other.limit_upper) {
|
||||
uint size = other.size();
|
||||
apply_blank_pairs(size);
|
||||
for(uint i = 0; i < size; i++) {
|
||||
|
@ -28,10 +28,6 @@ namespace servo {
|
|||
}
|
||||
|
||||
Calibration::~Calibration() {
|
||||
if(calibration != nullptr) {
|
||||
delete[] calibration;
|
||||
calibration = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Calibration &Calibration::operator=(const Calibration &other) {
|
||||
|
@ -57,16 +53,13 @@ namespace servo {
|
|||
}
|
||||
|
||||
void Calibration::apply_blank_pairs(uint size) {
|
||||
if(calibration != nullptr) {
|
||||
delete[] calibration;
|
||||
}
|
||||
|
||||
if(size > 0) {
|
||||
calibration = new Pair[size];
|
||||
for(auto i = 0u; i < size; i++) {
|
||||
calibration[i] = Pair();
|
||||
}
|
||||
calibration_size = size;
|
||||
}
|
||||
else {
|
||||
calibration = nullptr;
|
||||
calibration_size = 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace servo {
|
|||
static constexpr float DEFAULT_MID_PULSE = 1500.0f; // in microseconds
|
||||
static constexpr float DEFAULT_MAX_PULSE = 2500.0f; // in microseconds
|
||||
|
||||
static const uint MAX_CALIBRATION_PAIRS = 32;
|
||||
|
||||
private:
|
||||
static constexpr float LOWER_HARD_LIMIT = 400.0f; // The minimum microsecond pulse to send
|
||||
static constexpr float UPPER_HARD_LIMIT = 2600.0f; // The maximum microsecond pulse to send
|
||||
|
@ -110,7 +112,7 @@ namespace servo {
|
|||
// Variables
|
||||
//--------------------------------------------------
|
||||
private:
|
||||
Pair* calibration;
|
||||
Pair calibration[MAX_CALIBRATION_PAIRS];
|
||||
uint calibration_size;
|
||||
bool limit_lower;
|
||||
bool limit_upper;
|
||||
|
|
|
@ -44,8 +44,6 @@ namespace servo {
|
|||
}
|
||||
|
||||
ServoCluster::~ServoCluster() {
|
||||
delete[] states;
|
||||
delete[] servo_phases;
|
||||
}
|
||||
|
||||
bool ServoCluster::init() {
|
||||
|
@ -502,9 +500,6 @@ namespace servo {
|
|||
void ServoCluster::create_servo_states(CalibrationType default_type, bool auto_phase) {
|
||||
uint8_t servo_count = pwms.get_chan_count();
|
||||
if(servo_count > 0) {
|
||||
states = new ServoState[servo_count];
|
||||
servo_phases = new float[servo_count];
|
||||
|
||||
for(uint servo = 0; servo < servo_count; servo++) {
|
||||
states[servo] = ServoState(default_type);
|
||||
servo_phases[servo] = (auto_phase) ? (float)servo / (float)servo_count : 0.0f;
|
||||
|
@ -515,9 +510,6 @@ namespace servo {
|
|||
void ServoCluster::create_servo_states(const Calibration& calibration, bool auto_phase) {
|
||||
uint8_t servo_count = pwms.get_chan_count();
|
||||
if(servo_count > 0) {
|
||||
states = new ServoState[servo_count];
|
||||
servo_phases = new float[servo_count];
|
||||
|
||||
for(uint servo = 0; servo < servo_count; servo++) {
|
||||
states[servo] = ServoState(calibration);
|
||||
servo_phases[servo] = (auto_phase) ? (float)servo / (float)servo_count : 0.0f;
|
||||
|
|
|
@ -12,12 +12,14 @@ namespace servo {
|
|||
//--------------------------------------------------
|
||||
// Variables
|
||||
//--------------------------------------------------
|
||||
public:
|
||||
static const uint MAX_SERVO_CHANNELS = 32;
|
||||
private:
|
||||
PWMCluster pwms;
|
||||
uint32_t pwm_period;
|
||||
float pwm_frequency;
|
||||
ServoState* states;
|
||||
float* servo_phases;
|
||||
ServoState states[MAX_SERVO_CHANNELS];
|
||||
float servo_phases[MAX_SERVO_CHANNELS];
|
||||
|
||||
|
||||
//--------------------------------------------------
|
||||
|
|
|
@ -4,7 +4,7 @@ add_executable(
|
|||
)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(unicorn pico_stdlib hardware_pio hardware_dma pico_unicorn)
|
||||
target_link_libraries(unicorn pico_stdlib hardware_pio hardware_dma pico_graphics pico_unicorn)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(unicorn)
|
||||
|
|
|
@ -10,9 +10,6 @@ using namespace pimoroni;
|
|||
PicoUnicorn pico_unicorn;
|
||||
|
||||
int main() {
|
||||
|
||||
pico_unicorn.init();
|
||||
|
||||
bool a_pressed = false;
|
||||
bool b_pressed = false;
|
||||
bool x_pressed = false;
|
||||
|
|
|
@ -8,7 +8,7 @@ pico_enable_stdio_usb(unicornplasma 1)
|
|||
pico_enable_stdio_uart(unicornplasma 1)
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(unicornplasma pico_stdlib hardware_pio hardware_dma pico_unicorn)
|
||||
target_link_libraries(unicornplasma pico_stdlib hardware_pio hardware_dma pico_graphics pico_unicorn)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(unicornplasma)
|
||||
|
|
|
@ -21,7 +21,7 @@ namespace bitmap {
|
|||
return font->widths[char_index] * scale;
|
||||
}
|
||||
|
||||
int32_t measure_text(const font_t *font, const std::string &t, const uint8_t scale, const uint8_t letter_spacing) {
|
||||
int32_t measure_text(const font_t *font, const std::string_view &t, const uint8_t scale, const uint8_t letter_spacing) {
|
||||
int32_t text_width = 0;
|
||||
unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195;
|
||||
for(auto c : t) {
|
||||
|
@ -119,7 +119,7 @@ namespace bitmap {
|
|||
}
|
||||
}
|
||||
|
||||
void text(const font_t *font, rect_func rectangle, const std::string &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale, const uint8_t letter_spacing) {
|
||||
void text(const font_t *font, rect_func rectangle, const std::string_view &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale, const uint8_t letter_spacing) {
|
||||
uint32_t co = 0, lo = 0; // character and line (if wrapping) offset
|
||||
unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195;
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <cstdint>
|
||||
#include "common/unicode_sorta.hpp"
|
||||
|
||||
|
@ -19,8 +20,8 @@ namespace bitmap {
|
|||
typedef std::function<void(int32_t x, int32_t y, int32_t w, int32_t h)> rect_func;
|
||||
|
||||
int32_t measure_character(const font_t *font, const char c, const uint8_t scale, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195);
|
||||
int32_t measure_text(const font_t *font, const std::string &t, const uint8_t scale = 2, const uint8_t letter_spacing = 1);
|
||||
int32_t measure_text(const font_t *font, const std::string_view &t, const uint8_t scale = 2, const uint8_t letter_spacing = 1);
|
||||
|
||||
void character(const font_t *font, rect_func rectangle, const char c, const int32_t x, const int32_t y, const uint8_t scale = 2, unicode_sorta::codepage_t codepage = unicode_sorta::PAGE_195);
|
||||
void text(const font_t *font, rect_func rectangle, const std::string &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale = 2, const uint8_t letter_spacing = 1);
|
||||
void text(const font_t *font, rect_func rectangle, const std::string_view &t, const int32_t x, const int32_t y, const int32_t wrap, const uint8_t scale = 2, const uint8_t letter_spacing = 1);
|
||||
}
|
|
@ -14,6 +14,26 @@ namespace hershey {
|
|||
//{ "serif_bold", ×rb }
|
||||
};
|
||||
|
||||
bool has_font(std::string_view font) {
|
||||
if(font == "sans"
|
||||
|| font == "gothic"
|
||||
|| font == "cursive"
|
||||
|| font == "serif_italic"
|
||||
|| font == "serif") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const font_t* font(std::string_view font) {
|
||||
if(font == "sans") return &futural;
|
||||
else if(font == "gothic") return &gothgbt;
|
||||
else if(font == "cursive") return &scripts;
|
||||
else if(font == "serif_italic") return ×i;
|
||||
else if(font == "serif") return ×r;
|
||||
return &futural;
|
||||
}
|
||||
|
||||
inline float deg2rad(float degrees) {
|
||||
return (degrees * M_PI) / 180.0f;
|
||||
}
|
||||
|
@ -41,7 +61,7 @@ namespace hershey {
|
|||
return gd->width * s;
|
||||
}
|
||||
|
||||
int32_t measure_text(const font_t* font, std::string message, float s) {
|
||||
int32_t measure_text(const font_t* font, std::string_view message, float s) {
|
||||
int32_t width = 0;
|
||||
for(auto &c : message) {
|
||||
width += measure_glyph(font, c, s);
|
||||
|
@ -93,7 +113,7 @@ namespace hershey {
|
|||
return gd->width * s;
|
||||
}
|
||||
|
||||
void text(const font_t* font, line_func line, std::string message, int32_t x, int32_t y, float s, float a) {
|
||||
void text(const font_t* font, line_func line, std::string_view message, int32_t x, int32_t y, float s, float a) {
|
||||
int32_t cx = x;
|
||||
int32_t cy = y;
|
||||
|
||||
|
|
|
@ -44,7 +44,10 @@ namespace hershey {
|
|||
inline float deg2rad(float degrees);
|
||||
const font_glyph_t* glyph_data(const font_t* font, unsigned char c);
|
||||
int32_t measure_glyph(const font_t* font, unsigned char c, float s);
|
||||
int32_t measure_text(const font_t* font, std::string message, float s);
|
||||
int32_t measure_text(const font_t* font, std::string_view message, float s);
|
||||
int32_t glyph(const font_t* font, line_func line, unsigned char c, int32_t x, int32_t y, float s, float a);
|
||||
void text(const font_t* font, line_func line, std::string message, int32_t x, int32_t y, float s, float a);
|
||||
void text(const font_t* font, line_func line, std::string_view message, int32_t x, int32_t y, float s, float a);
|
||||
|
||||
bool has_font(std::string_view font);
|
||||
const font_t* font(std::string_view font);
|
||||
}
|
|
@ -35,7 +35,7 @@ namespace pimoroni {
|
|||
this->hershey_font = font;
|
||||
}
|
||||
|
||||
void PicoGraphics::set_font(std::string name){
|
||||
void PicoGraphics::set_font(std::string_view name){
|
||||
if (name == "bitmap6") {
|
||||
set_font(&font6);
|
||||
} else if (name == "bitmap8") {
|
||||
|
@ -44,8 +44,8 @@ namespace pimoroni {
|
|||
set_font(&font14_outline);
|
||||
} else {
|
||||
// check that font exists and assign it
|
||||
if(hershey::fonts.find(name) != hershey::fonts.end()) {
|
||||
set_font(hershey::fonts[name]);
|
||||
if(hershey::has_font(name)) {
|
||||
set_font(hershey::font(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
void PicoGraphics::text(const std::string &t, const Point &p, int32_t wrap, float s, float a, uint8_t letter_spacing) {
|
||||
void PicoGraphics::text(const std::string_view &t, const Point &p, int32_t wrap, float s, float a, uint8_t letter_spacing) {
|
||||
if (bitmap_font) {
|
||||
bitmap::text(bitmap_font, [this](int32_t x, int32_t y, int32_t w, int32_t h) {
|
||||
rectangle(Rect(x, y, w, h));
|
||||
|
@ -166,7 +166,7 @@ namespace pimoroni {
|
|||
}
|
||||
}
|
||||
|
||||
int32_t PicoGraphics::measure_text(const std::string &t, float s, uint8_t letter_spacing) {
|
||||
int32_t PicoGraphics::measure_text(const std::string_view &t, float s, uint8_t letter_spacing) {
|
||||
if (bitmap_font) return bitmap::measure_text(bitmap_font, t, std::max(1.0f, s), letter_spacing);
|
||||
if (hershey_font) return hershey::measure_text(hershey_font, t, s);
|
||||
return 0;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
|
@ -268,7 +269,7 @@ namespace pimoroni {
|
|||
|
||||
void set_font(const bitmap::font_t *font);
|
||||
void set_font(const hershey::font_t *font);
|
||||
void set_font(std::string font);
|
||||
void set_font(std::string_view name);
|
||||
|
||||
void set_dimensions(int width, int height);
|
||||
void set_framebuffer(void *frame_buffer);
|
||||
|
@ -285,8 +286,8 @@ namespace pimoroni {
|
|||
void rectangle(const Rect &r);
|
||||
void circle(const Point &p, int32_t r);
|
||||
void character(const char c, const Point &p, float s = 2.0f, float a = 0.0f);
|
||||
void text(const std::string &t, const Point &p, int32_t wrap, float s = 2.0f, float a = 0.0f, uint8_t letter_spacing = 1);
|
||||
int32_t measure_text(const std::string &t, float s = 2.0f, uint8_t letter_spacing = 1);
|
||||
void text(const std::string_view &t, const Point &p, int32_t wrap, float s = 2.0f, float a = 0.0f, uint8_t letter_spacing = 1);
|
||||
int32_t measure_text(const std::string_view &t, float s = 2.0f, uint8_t letter_spacing = 1);
|
||||
void polygon(const std::vector<Point> &points);
|
||||
void triangle(Point p1, Point p2, Point p3);
|
||||
void line(Point p1, Point p2);
|
||||
|
|
|
@ -17,6 +17,11 @@ enum pin {
|
|||
|
||||
namespace pimoroni {
|
||||
|
||||
PicoRGBKeypad::~PicoRGBKeypad() {
|
||||
clear();
|
||||
update();
|
||||
}
|
||||
|
||||
void PicoRGBKeypad::init() {
|
||||
memset(buffer, 0, sizeof(buffer));
|
||||
led_data = buffer + 4;
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace pimoroni {
|
|||
uint8_t *led_data;
|
||||
|
||||
public:
|
||||
~PicoRGBKeypad();
|
||||
void init();
|
||||
void update();
|
||||
void set_brightness(float brightness);
|
||||
|
|
|
@ -11,4 +11,4 @@ target_sources(pico_scroll INTERFACE
|
|||
target_include_directories(pico_scroll INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(pico_scroll INTERFACE pico_stdlib hardware_i2c)
|
||||
target_link_libraries(pico_scroll INTERFACE pico_stdlib pico_graphics hardware_i2c)
|
|
@ -35,6 +35,11 @@ enum reg {
|
|||
|
||||
namespace pimoroni {
|
||||
|
||||
PicoScroll::~PicoScroll() {
|
||||
clear();
|
||||
update();
|
||||
}
|
||||
|
||||
void PicoScroll::init() {
|
||||
// setup i2c interface
|
||||
i2c_init(i2c0, 400000);
|
||||
|
@ -166,4 +171,61 @@ namespace pimoroni {
|
|||
memcpy(&buffer[1], data, len);
|
||||
i2c_write_blocking(i2c0, DEFAULT_ADDRESS, buffer, len + 1, true);
|
||||
}
|
||||
|
||||
void PicoScroll::update(PicoGraphics *graphics) {
|
||||
if(graphics->pen_type == PicoGraphics::PEN_RGB888) {
|
||||
uint32_t *p = (uint32_t *)graphics->frame_buffer;
|
||||
|
||||
for(int y = 0; y < HEIGHT; y++) {
|
||||
for(int x = 0; x < WIDTH; x++) {
|
||||
uint32_t col = *p;
|
||||
uint8_t r = (col & 0xff0000) >> 16;
|
||||
uint8_t g = (col & 0x00ff00) >> 8;
|
||||
uint8_t b = (col & 0x0000ff) >> 0;
|
||||
p++;
|
||||
|
||||
set_pixel(x, y, (r + g + b) / 3);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
else if(graphics->pen_type == PicoGraphics::PEN_RGB565) {
|
||||
uint16_t *p = (uint16_t *)graphics->frame_buffer;
|
||||
for(int y = 0; y < HEIGHT; y++) {
|
||||
for(int x = 0; x < WIDTH; x++) {
|
||||
uint16_t col = __builtin_bswap16(*p);
|
||||
uint8_t r = (col & 0b1111100000000000) >> 8;
|
||||
uint8_t g = (col & 0b0000011111100000) >> 3;
|
||||
uint8_t b = (col & 0b0000000000011111) << 3;
|
||||
p++;
|
||||
|
||||
set_pixel(x, y, (r + g + b) / 3);
|
||||
}
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
else if(graphics->pen_type == PicoGraphics::PEN_P8 || graphics->pen_type == PicoGraphics::PEN_P4) {
|
||||
int offset = 0;
|
||||
graphics->frame_convert(PicoGraphics::PEN_RGB888, [this, offset](void *data, size_t length) mutable {
|
||||
uint32_t *p = (uint32_t *)data;
|
||||
for(auto i = 0u; i < length / 4; i++) {
|
||||
int x = offset % WIDTH;
|
||||
int y = offset / WIDTH;
|
||||
|
||||
uint32_t col = *p;
|
||||
uint8_t r = (col & 0xff0000) >> 16;
|
||||
uint8_t g = (col & 0x00ff00) >> 8;
|
||||
uint8_t b = (col & 0x0000ff) >> 0;
|
||||
|
||||
set_pixel(x, y, (r + g + b) / 3);
|
||||
offset++;
|
||||
p++;
|
||||
}
|
||||
});
|
||||
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#include <string>
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "pico_graphics.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
class PicoScroll {
|
||||
|
@ -19,6 +21,7 @@ namespace pimoroni {
|
|||
uint8_t __fb[BUFFER_SIZE];
|
||||
|
||||
public:
|
||||
~PicoScroll();
|
||||
void init();
|
||||
void update();
|
||||
void set_pixels(const char *pixels);
|
||||
|
@ -35,6 +38,7 @@ namespace pimoroni {
|
|||
void clear();
|
||||
bool is_pressed(uint8_t button);
|
||||
|
||||
void update(PicoGraphics *graphics);
|
||||
private:
|
||||
void i2c_write(uint8_t reg, const char *data, uint8_t len);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "pico_scroll_font.hpp"
|
||||
#include <string.h>
|
||||
|
||||
/* static font data */
|
||||
static const unsigned char __bitmap[256][5] = {
|
||||
|
@ -135,13 +136,15 @@ static const unsigned char __bitmap[256][5] = {
|
|||
/* render a text string to a pre-allocated buffer - strlen(text) * 6 bytes */
|
||||
int render_text(const char *text, unsigned int nchr, unsigned char *buffer, unsigned int nbfr) {
|
||||
// TODO check nbfr >= 6 * nchr
|
||||
memset(buffer, 0, nbfr);
|
||||
|
||||
for (unsigned int i = 0; i < nchr; i++) {
|
||||
const unsigned char *symbol = __bitmap[(unsigned int)text[i]];
|
||||
for (unsigned int j = 0; j < 5; j++) {
|
||||
buffer[i * 6 + j] = symbol[j];
|
||||
unsigned int offset = i * 6 + j;
|
||||
if (offset >= nbfr) return -1;
|
||||
buffer[offset] = symbol[j];
|
||||
}
|
||||
buffer[i * 6 + 5] = 0x0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,13 +12,12 @@ We've included helper functions to handle every aspect of drawing to the display
|
|||
- [Buttons](#buttons)
|
||||
- [WIDTH / HEIGHT](#width--height)
|
||||
- [Functions](#functions)
|
||||
- [init](#init)
|
||||
- [set_pixel](#set_pixel)
|
||||
- [is_pressed](#is_pressed)
|
||||
- [set\_pixel](#set_pixel)
|
||||
- [is\_pressed](#is_pressed)
|
||||
|
||||
## Example Program
|
||||
|
||||
The following example sets up Pico Unicorn, displays some basic demo text and graphics and will illuminate the RGB LED green if the A button is presse
|
||||
The following example sets up Pico Unicorn, displays some basic demo text and graphics and will illuminate the RGB LED green if the A button is pressed.
|
||||
|
||||
```c++
|
||||
|
||||
|
@ -48,15 +47,6 @@ int num_pixels = pico_unicorn.WIDTH * pico_unicorn.HEIGHT;
|
|||
|
||||
### Functions
|
||||
|
||||
#### init
|
||||
|
||||
Sets up Pico Unicorn. `init` must be called before any other functions since it configures the PIO and require GPIO inputs. Just call `init()` like so:
|
||||
|
||||
```c++
|
||||
PicoUnicorn pico_unicorn;
|
||||
pico_unicorn.init();
|
||||
```
|
||||
|
||||
#### set_pixel
|
||||
|
||||
```c++
|
||||
|
|
|
@ -9,4 +9,4 @@ target_sources(pico_unicorn INTERFACE
|
|||
target_include_directories(pico_unicorn INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
# Pull in pico libraries that we need
|
||||
target_link_libraries(pico_unicorn INTERFACE pico_stdlib hardware_pio hardware_dma)
|
||||
target_link_libraries(pico_unicorn INTERFACE pico_stdlib pico_graphics hardware_pio hardware_dma)
|
||||
|
|
|
@ -44,82 +44,53 @@ enum pin {
|
|||
Y = 15,
|
||||
};
|
||||
|
||||
constexpr uint32_t ROW_COUNT = 7;
|
||||
constexpr uint32_t ROW_BYTES = 12;
|
||||
constexpr uint32_t BCD_FRAMES = 15; // includes fet discharge frame
|
||||
constexpr uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES * BCD_FRAMES);
|
||||
|
||||
// must be aligned for 32bit dma transfer
|
||||
alignas(4) static uint8_t bitstream[BITSTREAM_LENGTH] = {0};
|
||||
|
||||
static uint32_t dma_channel;
|
||||
|
||||
static inline void unicorn_jetpack_program_init(PIO pio, uint sm, uint offset) {
|
||||
pio_gpio_init(pio, pin::LED_DATA);
|
||||
pio_gpio_init(pio, pin::LED_CLOCK);
|
||||
pio_gpio_init(pio, pin::LED_LATCH);
|
||||
pio_gpio_init(pio, pin::LED_BLANK);
|
||||
pio_gpio_init(pio, pin::ROW_0);
|
||||
pio_gpio_init(pio, pin::ROW_1);
|
||||
pio_gpio_init(pio, pin::ROW_2);
|
||||
pio_gpio_init(pio, pin::ROW_3);
|
||||
pio_gpio_init(pio, pin::ROW_4);
|
||||
pio_gpio_init(pio, pin::ROW_5);
|
||||
pio_gpio_init(pio, pin::ROW_6);
|
||||
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin::LED_DATA, 4, true);
|
||||
pio_sm_set_consecutive_pindirs(pio, sm, pin::ROW_6, 7, true);
|
||||
|
||||
pio_sm_config c = unicorn_program_get_default_config(offset);
|
||||
|
||||
// osr shifts right, autopull on, autopull threshold 8
|
||||
sm_config_set_out_shift(&c, true, false, 32);
|
||||
|
||||
// configure out, set, and sideset pins
|
||||
sm_config_set_out_pins(&c, pin::ROW_6, 7);
|
||||
sm_config_set_sideset_pins(&c, pin::LED_CLOCK);
|
||||
sm_config_set_set_pins(&c, pin::LED_DATA, 4);
|
||||
|
||||
// join fifos as only tx needed (gives 8 deep fifo instead of 4)
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
pio_sm_set_enabled(pio, sm, true);
|
||||
}
|
||||
static uint32_t dma_ctrl_channel;
|
||||
|
||||
namespace pimoroni {
|
||||
PicoUnicorn* PicoUnicorn::unicorn = nullptr;
|
||||
PIO PicoUnicorn::bitstream_pio = pio0;
|
||||
uint PicoUnicorn::bitstream_sm = 0;
|
||||
uint PicoUnicorn::bitstream_sm_offset = 0;
|
||||
|
||||
// once the dma transfer of the scanline is complete we move to the
|
||||
// next scanline (or quit if we're finished)
|
||||
void __isr dma_complete() {
|
||||
if (dma_hw->ints0 & (1u << dma_channel)) {
|
||||
dma_hw->ints0 = (1u << dma_channel); // clear irq flag
|
||||
dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false);
|
||||
dma_channel_set_read_addr(dma_channel, bitstream, true);
|
||||
PicoUnicorn::~PicoUnicorn() {
|
||||
if(unicorn == this) {
|
||||
partial_teardown();
|
||||
|
||||
dma_channel_unclaim(dma_ctrl_channel); // This works now the teardown behaves correctly
|
||||
dma_channel_unclaim(dma_channel); // This works now the teardown behaves correctly
|
||||
pio_sm_unclaim(bitstream_pio, bitstream_sm);
|
||||
pio_remove_program(bitstream_pio, &unicorn_program, bitstream_sm_offset);
|
||||
|
||||
unicorn = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
PicoUnicorn::~PicoUnicorn() {
|
||||
// stop and release the dma channel
|
||||
irq_set_enabled(DMA_IRQ_0, false);
|
||||
dma_channel_set_irq0_enabled(dma_channel, false);
|
||||
irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false);
|
||||
irq_remove_handler(DMA_IRQ_0, dma_complete);
|
||||
void PicoUnicorn::partial_teardown() {
|
||||
// Stop the bitstream SM
|
||||
pio_sm_set_enabled(bitstream_pio, bitstream_sm, false);
|
||||
|
||||
dma_channel_wait_for_finish_blocking(dma_channel);
|
||||
dma_channel_unclaim(dma_channel);
|
||||
// Make sure the display is off and switch it to an invisible row, to be safe
|
||||
const uint pins_to_set = 0b1111111 << ROW_6;
|
||||
pio_sm_set_pins_with_mask(bitstream_pio, bitstream_sm, pins_to_set, pins_to_set);
|
||||
|
||||
// release the pio and sm
|
||||
pio_sm_unclaim(bitstream_pio, bitstream_sm);
|
||||
pio_clear_instruction_memory(bitstream_pio);
|
||||
pio_sm_restart(bitstream_pio, bitstream_sm);
|
||||
dma_hw->ch[dma_ctrl_channel].al1_ctrl = (dma_hw->ch[dma_ctrl_channel].al1_ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (dma_ctrl_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB);
|
||||
dma_hw->ch[dma_channel].al1_ctrl = (dma_hw->ch[dma_channel].al1_ctrl & ~DMA_CH0_CTRL_TRIG_CHAIN_TO_BITS) | (dma_channel << DMA_CH0_CTRL_TRIG_CHAIN_TO_LSB);
|
||||
// Abort any in-progress DMA transfer
|
||||
dma_safe_abort(dma_ctrl_channel);
|
||||
dma_safe_abort(dma_channel);
|
||||
}
|
||||
|
||||
[[deprecated("Handled by constructor.")]]
|
||||
void PicoUnicorn::init() {
|
||||
// todo: shouldn't need to do this if things were cleaned up properly but without
|
||||
// this any attempt to run a micropython script twice will fail
|
||||
static bool already_init = false;
|
||||
return;
|
||||
}
|
||||
|
||||
PicoUnicorn::PicoUnicorn() {
|
||||
if(unicorn != nullptr) {
|
||||
partial_teardown();
|
||||
}
|
||||
|
||||
// setup pins
|
||||
gpio_init(pin::LED_DATA); gpio_set_dir(pin::LED_DATA, GPIO_OUT);
|
||||
gpio_init(pin::LED_CLOCK); gpio_set_dir(pin::LED_CLOCK, GPIO_OUT);
|
||||
|
@ -171,47 +142,81 @@ namespace pimoroni {
|
|||
gpio_set_function(pin::X, GPIO_FUNC_SIO); gpio_set_dir(pin::X, GPIO_IN); gpio_pull_up(pin::X);
|
||||
gpio_set_function(pin::Y, GPIO_FUNC_SIO); gpio_set_dir(pin::Y, GPIO_IN); gpio_pull_up(pin::Y);
|
||||
|
||||
if(already_init) {
|
||||
// stop and release the dma channel
|
||||
irq_set_enabled(DMA_IRQ_0, false);
|
||||
dma_channel_abort(dma_channel);
|
||||
dma_channel_wait_for_finish_blocking(dma_channel);
|
||||
|
||||
dma_channel_set_irq0_enabled(dma_channel, false);
|
||||
irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), false);
|
||||
irq_remove_handler(DMA_IRQ_0, dma_complete);
|
||||
|
||||
dma_channel_unclaim(dma_channel);
|
||||
|
||||
// release the pio and sm
|
||||
pio_sm_unclaim(bitstream_pio, bitstream_sm);
|
||||
pio_clear_instruction_memory(bitstream_pio);
|
||||
pio_sm_restart(bitstream_pio, bitstream_sm);
|
||||
//return;
|
||||
}
|
||||
|
||||
// setup the pio
|
||||
bitstream_pio = pio0;
|
||||
bitstream_sm = pio_claim_unused_sm(pio0, true);
|
||||
sm_offset = pio_add_program(bitstream_pio, &unicorn_program);
|
||||
unicorn_jetpack_program_init(bitstream_pio, bitstream_sm, sm_offset);
|
||||
if(unicorn == nullptr) {
|
||||
bitstream_sm = pio_claim_unused_sm(bitstream_pio, true);
|
||||
bitstream_sm_offset = pio_add_program(bitstream_pio, &unicorn_program);
|
||||
}
|
||||
|
||||
pio_gpio_init(bitstream_pio, pin::LED_DATA);
|
||||
pio_gpio_init(bitstream_pio, pin::LED_CLOCK);
|
||||
pio_gpio_init(bitstream_pio, pin::LED_LATCH);
|
||||
pio_gpio_init(bitstream_pio, pin::LED_BLANK);
|
||||
pio_gpio_init(bitstream_pio, pin::ROW_0);
|
||||
pio_gpio_init(bitstream_pio, pin::ROW_1);
|
||||
pio_gpio_init(bitstream_pio, pin::ROW_2);
|
||||
pio_gpio_init(bitstream_pio, pin::ROW_3);
|
||||
pio_gpio_init(bitstream_pio, pin::ROW_4);
|
||||
pio_gpio_init(bitstream_pio, pin::ROW_5);
|
||||
pio_gpio_init(bitstream_pio, pin::ROW_6);
|
||||
|
||||
// setup dma transfer for pixel data to the pio
|
||||
pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, pin::LED_DATA, 4, true);
|
||||
pio_sm_set_consecutive_pindirs(bitstream_pio, bitstream_sm, pin::ROW_6, 7, true);
|
||||
|
||||
pio_sm_config c = unicorn_program_get_default_config(bitstream_sm_offset);
|
||||
|
||||
// osr shifts right, autopull on, autopull threshold 8
|
||||
sm_config_set_out_shift(&c, true, false, 32);
|
||||
|
||||
// configure out, set, and sideset pins
|
||||
sm_config_set_out_pins(&c, pin::ROW_6, 7);
|
||||
sm_config_set_sideset_pins(&c, pin::LED_CLOCK);
|
||||
sm_config_set_set_pins(&c, pin::LED_DATA, 4);
|
||||
|
||||
// join fifos as only tx needed (gives 8 deep fifo instead of 4)
|
||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
|
||||
|
||||
// setup chained dma transfer for pixel data to the pio
|
||||
dma_channel = dma_claim_unused_channel(true);
|
||||
dma_ctrl_channel = dma_claim_unused_channel(true);
|
||||
|
||||
dma_channel_config ctrl_config = dma_channel_get_default_config(dma_ctrl_channel);
|
||||
channel_config_set_transfer_data_size(&ctrl_config, DMA_SIZE_32);
|
||||
channel_config_set_read_increment(&ctrl_config, false);
|
||||
channel_config_set_write_increment(&ctrl_config, false);
|
||||
channel_config_set_chain_to(&ctrl_config, dma_channel);
|
||||
|
||||
dma_channel_configure(
|
||||
dma_ctrl_channel,
|
||||
&ctrl_config,
|
||||
&dma_hw->ch[dma_channel].read_addr,
|
||||
&bitstream_addr,
|
||||
1,
|
||||
false
|
||||
);
|
||||
|
||||
dma_channel_config config = dma_channel_get_default_config(dma_channel);
|
||||
channel_config_set_transfer_data_size(&config, DMA_SIZE_32);
|
||||
channel_config_set_bswap(&config, false); // byte swap to reverse little endian
|
||||
channel_config_set_dreq(&config, pio_get_dreq(bitstream_pio, bitstream_sm, true));
|
||||
dma_channel_configure(dma_channel, &config, &bitstream_pio->txf[bitstream_sm], NULL, 0, false);
|
||||
dma_channel_set_irq0_enabled(dma_channel, true);
|
||||
irq_set_enabled(pio_get_dreq(bitstream_pio, bitstream_sm, true), true);
|
||||
irq_set_exclusive_handler(DMA_IRQ_0, dma_complete);
|
||||
irq_set_enabled(DMA_IRQ_0, true);
|
||||
channel_config_set_chain_to(&config, dma_ctrl_channel);
|
||||
|
||||
dma_channel_set_trans_count(dma_channel, BITSTREAM_LENGTH / 4, false);
|
||||
dma_channel_set_read_addr(dma_channel, bitstream, true);
|
||||
dma_channel_configure(
|
||||
dma_channel,
|
||||
&config,
|
||||
&bitstream_pio->txf[bitstream_sm],
|
||||
NULL,
|
||||
BITSTREAM_LENGTH / 4,
|
||||
false);
|
||||
|
||||
already_init = true;
|
||||
pio_sm_init(bitstream_pio, bitstream_sm, bitstream_sm_offset, &c);
|
||||
pio_sm_set_enabled(bitstream_pio, bitstream_sm, true);
|
||||
|
||||
// start the control channel
|
||||
dma_start_channel_mask(1u << dma_ctrl_channel);
|
||||
|
||||
unicorn = this;
|
||||
}
|
||||
|
||||
void PicoUnicorn::clear() {
|
||||
|
@ -269,4 +274,74 @@ namespace pimoroni {
|
|||
return !gpio_get(button);
|
||||
}
|
||||
|
||||
void PicoUnicorn::dma_safe_abort(uint channel) {
|
||||
// Tear down the DMA channel.
|
||||
// This is copied from: https://github.com/raspberrypi/pico-sdk/pull/744/commits/5e0e8004dd790f0155426e6689a66e08a83cd9fc
|
||||
uint32_t irq0_save = dma_hw->inte0 & (1u << channel);
|
||||
hw_clear_bits(&dma_hw->inte0, irq0_save);
|
||||
|
||||
dma_hw->abort = 1u << channel;
|
||||
|
||||
// To fence off on in-flight transfers, the BUSY bit should be polled
|
||||
// rather than the ABORT bit, because the ABORT bit can clear prematurely.
|
||||
while (dma_hw->ch[channel].ctrl_trig & DMA_CH0_CTRL_TRIG_BUSY_BITS) tight_loop_contents();
|
||||
|
||||
// Clear the interrupt (if any) and restore the interrupt masks.
|
||||
dma_hw->ints0 = 1u << channel;
|
||||
hw_set_bits(&dma_hw->inte0, irq0_save);
|
||||
}
|
||||
|
||||
void PicoUnicorn::update(PicoGraphics *graphics) {
|
||||
if(unicorn == this) {
|
||||
if(graphics->pen_type == PicoGraphics::PEN_RGB888) {
|
||||
uint32_t *p = (uint32_t *)graphics->frame_buffer;
|
||||
|
||||
for(int y = 0; y < HEIGHT; y++) {
|
||||
for(int x = 0; x < WIDTH; x++) {
|
||||
uint32_t col = *p;
|
||||
uint8_t r = (col & 0xff0000) >> 16;
|
||||
uint8_t g = (col & 0x00ff00) >> 8;
|
||||
uint8_t b = (col & 0x0000ff) >> 0;
|
||||
p++;
|
||||
|
||||
set_pixel(x, y, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(graphics->pen_type == PicoGraphics::PEN_RGB565) {
|
||||
uint16_t *p = (uint16_t *)graphics->frame_buffer;
|
||||
for(int y = 0; y < HEIGHT; y++) {
|
||||
for(int x = 0; x < WIDTH; x++) {
|
||||
uint16_t col = __builtin_bswap16(*p);
|
||||
uint8_t r = (col & 0b1111100000000000) >> 8;
|
||||
uint8_t g = (col & 0b0000011111100000) >> 3;
|
||||
uint8_t b = (col & 0b0000000000011111) << 3;
|
||||
p++;
|
||||
|
||||
set_pixel(x, y, r, g, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(graphics->pen_type == PicoGraphics::PEN_P8 || graphics->pen_type == PicoGraphics::PEN_P4) {
|
||||
int offset = 0;
|
||||
graphics->frame_convert(PicoGraphics::PEN_RGB888, [this, offset](void *data, size_t length) mutable {
|
||||
uint32_t *p = (uint32_t *)data;
|
||||
for(auto i = 0u; i < length / 4; i++) {
|
||||
int x = offset % WIDTH;
|
||||
int y = offset / WIDTH;
|
||||
|
||||
uint32_t col = *p;
|
||||
uint8_t r = (col & 0xff0000) >> 16;
|
||||
uint8_t g = (col & 0x00ff00) >> 8;
|
||||
uint8_t b = (col & 0x0000ff) >> 0;
|
||||
|
||||
set_pixel(x, y, r, g, b);
|
||||
offset++;
|
||||
p++;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "hardware/pio.h"
|
||||
#include "pico_graphics.hpp"
|
||||
|
||||
namespace pimoroni {
|
||||
|
||||
|
@ -12,11 +13,24 @@ namespace pimoroni {
|
|||
static const uint8_t B = 13;
|
||||
static const uint8_t X = 14;
|
||||
static const uint8_t Y = 15;
|
||||
|
||||
static const uint32_t ROW_COUNT = 7;
|
||||
static const uint32_t ROW_BYTES = 12;
|
||||
static const uint32_t BCD_FRAMES = 15; // includes fet discharge frame
|
||||
static const uint32_t BITSTREAM_LENGTH = (ROW_COUNT * ROW_BYTES * BCD_FRAMES);
|
||||
|
||||
private:
|
||||
PIO bitstream_pio = pio0;
|
||||
uint bitstream_sm = 0;
|
||||
uint sm_offset = 0;
|
||||
static PIO bitstream_pio;
|
||||
static uint bitstream_sm;
|
||||
static uint bitstream_sm_offset;
|
||||
|
||||
// must be aligned for 32bit dma transfer
|
||||
alignas(4) uint8_t bitstream[BITSTREAM_LENGTH] = {0};
|
||||
const uint32_t bitstream_addr = (uint32_t)bitstream;
|
||||
static PicoUnicorn* unicorn;
|
||||
|
||||
public:
|
||||
PicoUnicorn();
|
||||
~PicoUnicorn();
|
||||
|
||||
void init();
|
||||
|
@ -26,6 +40,11 @@ namespace pimoroni {
|
|||
void set_pixel(uint8_t x, uint8_t y, uint8_t v);
|
||||
|
||||
bool is_pressed(uint8_t button);
|
||||
|
||||
void update(PicoGraphics *graphics);
|
||||
private:
|
||||
void partial_teardown();
|
||||
void dma_safe_abort(uint channel);
|
||||
};
|
||||
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import time
|
||||
import picokeypad as keypad
|
||||
import picokeypad
|
||||
|
||||
keypad.init()
|
||||
keypad = picokeypad.PicoKeypad()
|
||||
keypad.set_brightness(1.0)
|
||||
|
||||
lit = 0
|
||||
|
|
|
@ -1,30 +1,28 @@
|
|||
import time
|
||||
import picoscroll as scroll
|
||||
from picoscroll import PicoScroll, WIDTH, HEIGHT
|
||||
|
||||
scroll = PicoScroll()
|
||||
|
||||
scroll.init()
|
||||
i = 0
|
||||
loop = 18
|
||||
br_mult = 1
|
||||
br_pressed = 32
|
||||
tail = 12
|
||||
|
||||
width = scroll.get_width()
|
||||
height = scroll.get_height()
|
||||
|
||||
while True:
|
||||
scroll.clear()
|
||||
for y in range(0, height):
|
||||
for x in range(0, width):
|
||||
for y in range(0, HEIGHT):
|
||||
for x in range(0, WIDTH):
|
||||
if x < 3 and y < 3 and scroll.is_pressed(scroll.BUTTON_A):
|
||||
scroll.set_pixel(x, y, br_pressed)
|
||||
elif x < 3 and y > 3 and scroll.is_pressed(scroll.BUTTON_B):
|
||||
scroll.set_pixel(x, y, br_pressed)
|
||||
elif x > width - 4 and y < 3 and scroll.is_pressed(scroll.BUTTON_X):
|
||||
elif x > WIDTH - 4 and y < 3 and scroll.is_pressed(scroll.BUTTON_X):
|
||||
scroll.set_pixel(x, y, br_pressed)
|
||||
elif x > width - 4 and y > 3 and scroll.is_pressed(scroll.BUTTON_Y):
|
||||
elif x > WIDTH - 4 and y > 3 and scroll.is_pressed(scroll.BUTTON_Y):
|
||||
scroll.set_pixel(x, y, br_pressed)
|
||||
else:
|
||||
m = (x + (y * width)) % loop
|
||||
m = (x + (y * WIDTH)) % loop
|
||||
for b in range(0, loop):
|
||||
if m == (i + (loop - b)) % loop and b < tail:
|
||||
scroll.set_pixel(x, y, br_mult * (tail - b))
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
from picographics import PicoGraphics, DISPLAY_SCROLL_PACK, PEN_P8
|
||||
from picoscroll import PicoScroll
|
||||
import time
|
||||
|
||||
TEXT = "Hello World"
|
||||
|
||||
# By default P8 has a greyscale palette
|
||||
graphics = PicoGraphics(DISPLAY_SCROLL_PACK, pen_type=PEN_P8)
|
||||
scroll = PicoScroll()
|
||||
|
||||
t = scroll.get_width()
|
||||
|
||||
wrap = -graphics.measure_text(TEXT, scale=0)
|
||||
|
||||
while True:
|
||||
graphics.set_pen(0)
|
||||
graphics.clear()
|
||||
graphics.set_pen(255)
|
||||
graphics.text(TEXT, t, 0, scale=1)
|
||||
scroll.update(graphics)
|
||||
t -= 1
|
||||
time.sleep(0.1)
|
||||
if t <= wrap:
|
||||
t = scroll.get_width()
|
|
@ -1,7 +1,7 @@
|
|||
import time
|
||||
import picoscroll as scroll
|
||||
from picoscroll import PicoScroll
|
||||
|
||||
scroll.init()
|
||||
scroll = PicoScroll()
|
||||
|
||||
while True:
|
||||
scroll.scroll_text("Hello World", 128, 80)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import picounicorn
|
||||
from picounicorn import PicoUnicorn
|
||||
|
||||
picounicorn.init()
|
||||
picounicorn = PicoUnicorn()
|
||||
|
||||
|
||||
# From CPython Lib/colorsys.py
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import picounicorn
|
||||
from picounicorn import PicoUnicorn
|
||||
import time
|
||||
|
||||
picounicorn.init()
|
||||
picounicorn = PicoUnicorn()
|
||||
|
||||
|
||||
# From CPython Lib/colorsys.py
|
||||
|
|
|
@ -3,6 +3,9 @@ include_directories(${CMAKE_CURRENT_LIST_DIR}/../../)
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
||||
|
|
|
@ -48,11 +48,15 @@ mp_obj_t BreakoutBME280_read(mp_obj_t self_in) {
|
|||
breakout_bme280_BreakoutBME280_obj_t *self = MP_OBJ_TO_PTR2(self_in, breakout_bme280_BreakoutBME280_obj_t);
|
||||
BME280::bme280_reading result = self->breakout->read_forced();
|
||||
|
||||
mp_obj_t tuple[3];
|
||||
tuple[0] = mp_obj_new_float(result.temperature);
|
||||
tuple[1] = mp_obj_new_float(result.pressure);
|
||||
tuple[2] = mp_obj_new_float(result.humidity);
|
||||
return mp_obj_new_tuple(3, tuple);
|
||||
if(result.status) {
|
||||
mp_obj_t tuple[3];
|
||||
tuple[0] = mp_obj_new_float(result.temperature);
|
||||
tuple[1] = mp_obj_new_float(result.pressure);
|
||||
tuple[2] = mp_obj_new_float(result.humidity);
|
||||
return mp_obj_new_tuple(3, tuple);
|
||||
}
|
||||
|
||||
mp_raise_msg(&mp_type_RuntimeError, "BME280: read failed.");
|
||||
}
|
||||
|
||||
mp_obj_t BreakoutBME280_configure(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
|
|
|
@ -247,10 +247,8 @@ mp_obj_t _JPEG_decode(size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args
|
|||
if(mp_obj_is_str_or_bytes(self->file)){
|
||||
GET_STR_DATA_LEN(self->file, str, str_len);
|
||||
|
||||
std::string t((const char*)str);
|
||||
|
||||
result = self->jpeg->open(
|
||||
t.c_str(),
|
||||
(const char*)str,
|
||||
jpegdec_open_callback,
|
||||
jpegdec_close_callback,
|
||||
jpegdec_read_callback,
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
|
|
@ -1,31 +1,43 @@
|
|||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
||||
# Pico Graphics Essential
|
||||
include(hershey_fonts/micropython)
|
||||
include(bitmap_fonts/micropython)
|
||||
include(picographics/micropython)
|
||||
|
||||
# Pico Graphics Extra
|
||||
include(jpegdec/micropython)
|
||||
include(qrcode/micropython/micropython)
|
||||
|
||||
# Sensors & Breakouts
|
||||
include(micropython-common-breakouts)
|
||||
|
||||
# Packs & Bases
|
||||
include(pico_unicorn/micropython)
|
||||
include(pico_scroll/micropython)
|
||||
include(pico_rgb_keypad/micropython)
|
||||
include(pico_unicorn/micropython)
|
||||
include(pico_wireless/micropython)
|
||||
include(pico_explorer/micropython)
|
||||
|
||||
include(hershey_fonts/micropython)
|
||||
include(bitmap_fonts/micropython)
|
||||
|
||||
# LEDs & Matrices
|
||||
include(plasma/micropython)
|
||||
include(hub75/micropython)
|
||||
|
||||
# Servos & Motors
|
||||
include(pwm/micropython)
|
||||
include(servo/micropython)
|
||||
include(encoder/micropython)
|
||||
include(motor/micropython)
|
||||
include(qrcode/micropython/micropython)
|
||||
|
||||
# Utility
|
||||
include(adcfft/micropython)
|
||||
include(pcf85063a/micropython)
|
||||
|
||||
include(picographics/micropython)
|
||||
include(jpegdec/micropython)
|
||||
include(galactic_unicorn/micropython)
|
||||
|
||||
# RTC (Badger 2040W, Enviro)
|
||||
if(PICO_BOARD STREQUAL "pico_w")
|
||||
include(pcf85063a/micropython)
|
||||
endif()
|
||||
|
||||
include(modules_py/modules_py)
|
||||
|
||||
|
@ -37,4 +49,5 @@ if(PICO_BOARD STREQUAL "pico_w")
|
|||
copy_module(inventor.py)
|
||||
endif()
|
||||
|
||||
# Must call `enable_ulab()` to enable
|
||||
include(micropython-common-ulab)
|
|
@ -4,4 +4,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include(micropython-common)
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include(micropython-common)
|
||||
|
||||
enable_ulab()
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include(micropython-common)
|
||||
|
||||
enable_ulab()
|
||||
|
|
|
@ -4,41 +4,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Pico Graphics Essential
|
||||
include(hershey_fonts/micropython)
|
||||
include(bitmap_fonts/micropython)
|
||||
include(picographics/micropython)
|
||||
|
||||
# Pico Graphics Extra
|
||||
include(jpegdec/micropython)
|
||||
include(qrcode/micropython/micropython)
|
||||
|
||||
# Sensors & Breakouts
|
||||
include(micropython-common-breakouts)
|
||||
include(pcf85063a/micropython)
|
||||
|
||||
# Utility
|
||||
include(adcfft/micropython)
|
||||
|
||||
# LEDs & Matrices
|
||||
include(plasma/micropython)
|
||||
include(hub75/micropython)
|
||||
|
||||
# Packs
|
||||
include(pico_unicorn/micropython)
|
||||
include(pico_scroll/micropython)
|
||||
include(pico_rgb_keypad/micropython)
|
||||
|
||||
# Servos & Motors
|
||||
include(pwm/micropython)
|
||||
include(servo/micropython)
|
||||
include(encoder/micropython)
|
||||
include(motor/micropython)
|
||||
|
||||
# include(micropython-common)
|
||||
|
||||
include(modules_py/modules_py)
|
||||
include(micropython-common)
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
|
|
@ -4,4 +4,7 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
include(micropython-common)
|
||||
|
|
|
@ -4,6 +4,9 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}")
|
|||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../")
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# Essential
|
||||
include(pimoroni_i2c/micropython)
|
||||
include(pimoroni_bus/micropython)
|
||||
|
|
|
@ -32,11 +32,11 @@ void pimoroni_tuple_or_list(const mp_obj_t &object, mp_obj_t **items, size_t *le
|
|||
}
|
||||
|
||||
uint8_t* pimoroni_motors_from_items(mp_obj_t *items, size_t length, int motor_count) {
|
||||
uint8_t *motors = new uint8_t[length];
|
||||
uint8_t *motors = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int motor = mp_obj_get_int(items[i]);
|
||||
if(motor < 0 || motor >= motor_count) {
|
||||
delete[] motors;
|
||||
m_free(motors);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a motor in the list or tuple is out of range. Expected 0 to %d"), motor_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -636,7 +636,7 @@ mp_obj_t MotorCluster_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
else {
|
||||
// Specific check for is a single 2 pin list/tuple was provided
|
||||
if(pair_count == 2 && mp_obj_is_int(items[0]) && mp_obj_is_int(items[1])) {
|
||||
pins = new pin_pair[1];
|
||||
pins = m_new(pin_pair, 1);
|
||||
pair_count = 1;
|
||||
|
||||
int pos = mp_obj_get_int(items[0]);
|
||||
|
@ -656,7 +656,7 @@ mp_obj_t MotorCluster_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
}
|
||||
else {
|
||||
// Create and populate a local array of pins
|
||||
pins = new pin_pair[pair_count];
|
||||
pins = m_new(pin_pair, pair_count);
|
||||
for(size_t i = 0; i < pair_count; i++) {
|
||||
mp_obj_t obj = items[i];
|
||||
if(!mp_obj_is_type(obj, &mp_type_tuple)) {
|
||||
|
|
|
@ -5,21 +5,20 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/***** Module Functions *****/
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_init_obj, picokeypad_init);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_width_obj, picokeypad_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_height_obj, picokeypad_get_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_num_pads_obj, picokeypad_get_num_pads);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_update_obj, picokeypad_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_set_brightness_obj, picokeypad_set_brightness);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_xy_obj, 5, 5, picokeypad_illuminate_xy);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_obj, 4, 4, picokeypad_illuminate);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_clear_obj, picokeypad_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picokeypad_get_button_states_obj, picokeypad_get_button_states);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad___del___obj, picokeypad___del__);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_width_obj, picokeypad_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_height_obj, picokeypad_get_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_num_pads_obj, picokeypad_get_num_pads);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_update_obj, picokeypad_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(picokeypad_set_brightness_obj, picokeypad_set_brightness);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_xy_obj, 6, 6, picokeypad_illuminate_xy);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picokeypad_illuminate_obj, 5, 5, picokeypad_illuminate);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_clear_obj, picokeypad_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picokeypad_get_button_states_obj, picokeypad_get_button_states);
|
||||
|
||||
/***** Globals Table *****/
|
||||
STATIC const mp_map_elem_t picokeypad_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picokeypad) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picokeypad_init_obj) },
|
||||
/* Class Methods */
|
||||
STATIC const mp_rom_map_elem_t picokeypad_locals[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picokeypad___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picokeypad_get_width_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picokeypad_get_height_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_num_pads), MP_ROM_PTR(&picokeypad_get_num_pads_obj) },
|
||||
|
@ -30,9 +29,34 @@ STATIC const mp_map_elem_t picokeypad_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picokeypad_clear_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_button_states), MP_ROM_PTR(&picokeypad_get_button_states_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picokeypad_globals, picokeypad_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picokeypad_locals, picokeypad_locals);
|
||||
|
||||
#ifdef MP_DEFINE_CONST_OBJ_TYPE
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
PicoKeypad_type,
|
||||
MP_QSTR_PicoKeypad,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, picokeypad_make_new,
|
||||
locals_dict, (mp_obj_dict_t*)&mp_module_picokeypad_locals
|
||||
);
|
||||
#else
|
||||
const mp_obj_type_t PicoKeypad_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PicoKeypad,
|
||||
.make_new = picokeypad_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&mp_module_picokeypad_locals,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Module Globals */
|
||||
STATIC const mp_map_elem_t picokeypad_globals[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_picokeypad) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PicoKeypad), (mp_obj_t)&PicoKeypad_type },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(4) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(4) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picokeypad_globals, picokeypad_globals);
|
||||
|
||||
/***** Module Definition *****/
|
||||
const mp_obj_module_t picokeypad_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_picokeypad_globals,
|
||||
|
|
|
@ -2,134 +2,130 @@
|
|||
#include "hardware/sync.h"
|
||||
#include "pico/binary_info.h"
|
||||
|
||||
#include "micropython/modules/util.hpp"
|
||||
#include "libraries/pico_rgb_keypad/pico_rgb_keypad.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoRGBKeypad *keypad = nullptr;
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "pico_rgb_keypad.h"
|
||||
|
||||
#define NOT_INITIALISED_MSG "Cannot call this function, as picokeypad is not initialised. Call picokeypad.init() first."
|
||||
typedef struct _PicoKeypad_obj_t {
|
||||
mp_obj_base_t base;
|
||||
PicoRGBKeypad* keypad;
|
||||
} PicoKeypad_obj_t;
|
||||
|
||||
mp_obj_t picokeypad_init() {
|
||||
if(keypad == nullptr) {
|
||||
keypad = new PicoRGBKeypad();
|
||||
keypad->init();
|
||||
}
|
||||
mp_obj_t picokeypad_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
_PicoKeypad_obj_t *self = nullptr;
|
||||
|
||||
self = m_new_obj_with_finaliser(PicoKeypad_obj_t);
|
||||
self->base.type = &PicoKeypad_type;
|
||||
|
||||
self->keypad = m_new_class(PicoRGBKeypad);
|
||||
self->keypad->init();
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad___del__(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
m_del_class(PicoRGBKeypad, self->keypad);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_width() {
|
||||
mp_obj_t picokeypad_get_width(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoRGBKeypad::WIDTH);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_height() {
|
||||
mp_obj_t picokeypad_get_height(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoRGBKeypad::HEIGHT);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_num_pads() {
|
||||
mp_obj_t picokeypad_get_num_pads(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoRGBKeypad::NUM_PADS);
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_update() {
|
||||
if(keypad != nullptr)
|
||||
keypad->update();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
mp_obj_t picokeypad_update(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
self->keypad->update();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_set_brightness(mp_obj_t brightness_obj) {
|
||||
if(keypad != nullptr) {
|
||||
float brightness = mp_obj_get_float(brightness_obj);
|
||||
mp_obj_t picokeypad_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
|
||||
if(brightness < 0 || brightness > 1.0f)
|
||||
mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0");
|
||||
else
|
||||
keypad->set_brightness(brightness);
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
float brightness = mp_obj_get_float(brightness_obj);
|
||||
|
||||
if(brightness < 0 || brightness > 1.0f)
|
||||
mp_raise_ValueError("brightness out of range. Expected 0.0 to 1.0");
|
||||
|
||||
self->keypad->set_brightness(brightness);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_illuminate_xy(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's 5
|
||||
(void)n_args; //Unused input parameter, we know it's self + 5
|
||||
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoKeypad_obj_t);
|
||||
|
||||
if(keypad != nullptr) {
|
||||
int x = mp_obj_get_int(args[0]);
|
||||
int y = mp_obj_get_int(args[1]);
|
||||
int r = mp_obj_get_int(args[2]);
|
||||
int g = mp_obj_get_int(args[3]);
|
||||
int b = mp_obj_get_int(args[4]);
|
||||
int x = mp_obj_get_int(args[1]);
|
||||
int y = mp_obj_get_int(args[2]);
|
||||
int r = mp_obj_get_int(args[3]);
|
||||
int g = mp_obj_get_int(args[4]);
|
||||
int b = mp_obj_get_int(args[5]);
|
||||
|
||||
if(x < 0 || x >= PicoRGBKeypad::WIDTH || y < 0 || y >= PicoRGBKeypad::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
else {
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
else if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
else if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
else
|
||||
keypad->illuminate(x, y, r, g, b);
|
||||
}
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
if(x < 0 || x >= PicoRGBKeypad::WIDTH || y < 0 || y >= PicoRGBKeypad::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
|
||||
self->keypad->illuminate(x, y, r, g, b);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_illuminate(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's 5
|
||||
(void)n_args; //Unused input parameter, we know it's self + 5
|
||||
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoKeypad_obj_t);
|
||||
|
||||
if(keypad != nullptr) {
|
||||
int i = mp_obj_get_int(args[0]);
|
||||
int r = mp_obj_get_int(args[1]);
|
||||
int g = mp_obj_get_int(args[2]);
|
||||
int b = mp_obj_get_int(args[3]);
|
||||
int i = mp_obj_get_int(args[1]);
|
||||
int r = mp_obj_get_int(args[2]);
|
||||
int g = mp_obj_get_int(args[3]);
|
||||
int b = mp_obj_get_int(args[4]);
|
||||
|
||||
if(i < 0 || i >= PicoRGBKeypad::NUM_PADS)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
else {
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
else if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
else if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
else
|
||||
keypad->illuminate(i, r, g, b);
|
||||
}
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
if(i < 0 || i >= PicoRGBKeypad::NUM_PADS)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
|
||||
self->keypad->illuminate(i, r, g, b);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_clear() {
|
||||
if(keypad != nullptr)
|
||||
keypad->clear();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
mp_obj_t picokeypad_clear(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
self->keypad->clear();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picokeypad_get_button_states() {
|
||||
mp_obj_t picokeypad_get_button_states(mp_obj_t self_in) {
|
||||
PicoKeypad_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoKeypad_obj_t);
|
||||
uint16_t states = 0;
|
||||
if(keypad != nullptr)
|
||||
states = keypad->get_button_states();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
states = self->keypad->get_button_states();
|
||||
return mp_obj_new_int(states);
|
||||
}
|
||||
}
|
|
@ -1,14 +1,17 @@
|
|||
// Include MicroPython API.
|
||||
#include "py/runtime.h"
|
||||
|
||||
extern const mp_obj_type_t PicoKeypad_type;
|
||||
|
||||
// Declare the functions we'll make available in Python
|
||||
extern mp_obj_t picokeypad_init();
|
||||
extern mp_obj_t picokeypad_get_width();
|
||||
extern mp_obj_t picokeypad_get_height();
|
||||
extern mp_obj_t picokeypad_get_num_pads();
|
||||
extern mp_obj_t picokeypad_update();
|
||||
extern mp_obj_t picokeypad_set_brightness(mp_obj_t brightness_obj);
|
||||
extern mp_obj_t picokeypad_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t picokeypad___del__(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_width(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_height(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_num_pads(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_update(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_set_brightness(mp_obj_t self_in, mp_obj_t brightness_obj);
|
||||
extern mp_obj_t picokeypad_illuminate_xy(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picokeypad_illuminate(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picokeypad_clear();
|
||||
extern mp_obj_t picokeypad_get_button_states();
|
||||
extern mp_obj_t picokeypad_clear(mp_obj_t self_in);
|
||||
extern mp_obj_t picokeypad_get_button_states(mp_obj_t self_in);
|
|
@ -5,28 +5,27 @@ Our Pico Scroll Pack offers a 17x7 white LED matrix for your Raspberry Pi Pico.
|
|||
We've included helper functions to handle every aspect of drawing to the matrix and interfacing with the buttons. See the [function reference](#function-reference) for details.
|
||||
|
||||
- [Example Program](#example-program)
|
||||
- [Function Reference](#function-reference)
|
||||
- [init](#init)
|
||||
- [get_width](#get_width)
|
||||
- [get_height](#get_height)
|
||||
- [set_pixel](#set_pixel)
|
||||
- [set_pixels](#set_pixels)
|
||||
- [show_text](#show_text)
|
||||
- [scroll_text](#scroll_text)
|
||||
- [show_bitmap_1d](#show_bitmap_1d)
|
||||
- [Function reference](#function-reference)
|
||||
- [get\_width](#get_width)
|
||||
- [get\_height](#get_height)
|
||||
- [set\_pixel](#set_pixel)
|
||||
- [set\_pixels](#set_pixels)
|
||||
- [show\_text](#show_text)
|
||||
- [scroll\_text](#scroll_text)
|
||||
- [show\_bitmap\_1d](#show_bitmap_1d)
|
||||
- [update](#update)
|
||||
- [clear](#clear)
|
||||
- [is_pressed](#is_pressed)
|
||||
- [is\_pressed](#is_pressed)
|
||||
|
||||
## Example Program
|
||||
|
||||
The following example sets up the matrix, sets each pixel to an increasing brightnesses level, and then clears the matrix only after button A is pressed.
|
||||
|
||||
```python
|
||||
import picoscroll
|
||||
from picoscroll import PicoScroll
|
||||
|
||||
# Initialise the board
|
||||
picoscroll.init()
|
||||
picoscroll = PicoScroll()
|
||||
|
||||
brightness = 0
|
||||
|
||||
|
@ -51,14 +50,6 @@ picoscroll.update()
|
|||
|
||||
## Function reference
|
||||
|
||||
### init
|
||||
|
||||
Sets up the Pico Scroll Pack. The `init` function must be called before any other functions as it configures the required pins on the Pico board.
|
||||
|
||||
```python
|
||||
picoscroll.init()
|
||||
```
|
||||
|
||||
### get_width
|
||||
### get_height
|
||||
|
||||
|
|
|
@ -15,40 +15,70 @@ enum buttons
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/***** Module Functions *****/
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_init_obj, picoscroll_init);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_get_width_obj, picoscroll_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_get_height_obj, picoscroll_get_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_update_obj, picoscroll_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(picoscroll_set_pixel_obj, picoscroll_set_pixel);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_set_pixels_obj, picoscroll_set_pixels);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(picoscroll_show_text_obj, picoscroll_show_text);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(picoscroll_scroll_text_obj, picoscroll_scroll_text);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(picoscroll_show_bitmap_1d_obj, picoscroll_show_bitmap_1d);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picoscroll_clear_obj, picoscroll_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_is_pressed_obj, picoscroll_is_pressed);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll___del___obj, picoscroll___del__);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_get_width_obj, picoscroll_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_get_height_obj, picoscroll_get_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_show_obj, picoscroll_show);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_set_pixel_obj, 4, 4, picoscroll_set_pixel);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(picoscroll_set_pixels_obj, picoscroll_set_pixels);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_show_text_obj, 4, 4, picoscroll_show_text);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_scroll_text_obj, 4, 4, picoscroll_scroll_text);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picoscroll_show_bitmap_1d_obj, 4, 4, picoscroll_show_bitmap_1d);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picoscroll_clear_obj, picoscroll_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(picoscroll_is_pressed_obj, picoscroll_is_pressed);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(picoscroll_update_obj, picoscroll_update);
|
||||
|
||||
/***** Globals Table *****/
|
||||
STATIC const mp_map_elem_t picoscroll_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picoscroll) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picoscroll_init_obj) },
|
||||
/* Class Methods */
|
||||
STATIC const mp_rom_map_elem_t picoscroll_locals[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picoscroll___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picoscroll_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show), MP_ROM_PTR(&picoscroll_show_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picoscroll_get_width_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picoscroll_get_height_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picoscroll_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&picoscroll_set_pixel_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_pixels), MP_ROM_PTR(&picoscroll_set_pixels_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show_text), MP_ROM_PTR(&picoscroll_show_text_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_scroll_text), MP_ROM_PTR(&picoscroll_scroll_text_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_show_bitmap_1d), MP_ROM_PTR(&picoscroll_show_bitmap_1d_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picoscroll_clear_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picoscroll_is_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picoscroll_is_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_INT(BUTTON_A) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_INT(BUTTON_B) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_X), MP_ROM_INT(BUTTON_X) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_Y), MP_ROM_INT(BUTTON_Y) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picoscroll_globals, picoscroll_globals_table);
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picoscroll_locals, picoscroll_locals);
|
||||
|
||||
#ifdef MP_DEFINE_CONST_OBJ_TYPE
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
PicoScroll_type,
|
||||
MP_QSTR_PicoScroll,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, picoscroll_make_new,
|
||||
locals_dict, (mp_obj_dict_t*)&mp_module_picoscroll_locals
|
||||
);
|
||||
#else
|
||||
const mp_obj_type_t PicoScroll_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PicoScroll,
|
||||
.make_new = picoscroll_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&mp_module_picoscroll_locals,
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Module Globals */
|
||||
STATIC const mp_map_elem_t picoscroll_globals[] = {
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_picoscroll) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PicoScroll), (mp_obj_t)&PicoScroll_type },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(17) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(7) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_INT(BUTTON_A) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_INT(BUTTON_B) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_X), MP_ROM_INT(BUTTON_X) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_Y), MP_ROM_INT(BUTTON_Y) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picoscroll_globals, picoscroll_globals);
|
||||
|
||||
/***** Module Definition *****/
|
||||
const mp_obj_module_t picoscroll_user_cmodule = {
|
||||
.base = { &mp_type_module },
|
||||
.globals = (mp_obj_dict_t*)&mp_module_picoscroll_globals,
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#include <cstdio>
|
||||
#include "hardware/spi.h"
|
||||
#include "hardware/sync.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "pico/stdlib.h"
|
||||
|
||||
#include "micropython/modules/util.hpp"
|
||||
#include "libraries/pico_scroll/pico_scroll.hpp"
|
||||
#include "libraries/pico_scroll/pico_scroll_font.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
|
@ -12,165 +15,219 @@ PicoScroll *scroll = nullptr;
|
|||
|
||||
extern "C" {
|
||||
#include "pico_scroll.h"
|
||||
#include "micropython/modules/pimoroni_i2c/pimoroni_i2c.h"
|
||||
#include "py/builtin.h"
|
||||
|
||||
#define NOT_INITIALISED_MSG "Cannot call this function, as picoscroll is not initialised. Call picoscroll.init() first."
|
||||
#define BUFFER_TOO_SMALL_MSG "bytearray too small: len(image) < width * height."
|
||||
#define INCORRECT_SIZE_MSG "Scroll height wrong: > 8 pixels."
|
||||
|
||||
mp_obj_t picoscroll_init() {
|
||||
if(scroll == nullptr)
|
||||
scroll = new PicoScroll();
|
||||
scroll->init();
|
||||
typedef struct _PicoScroll_obj_t {
|
||||
mp_obj_base_t base;
|
||||
PicoScroll* scroll;
|
||||
} PicoScroll_obj_t;
|
||||
|
||||
// from picographics/picographics.cpp
|
||||
// used to support accepting a PicoGraphics class
|
||||
typedef struct _ModPicoGraphics_obj_t {
|
||||
mp_obj_base_t base;
|
||||
PicoGraphics *graphics;
|
||||
DisplayDriver *display;
|
||||
void *spritedata;
|
||||
void *buffer;
|
||||
_PimoroniI2C_obj_t *i2c;
|
||||
} ModPicoGraphics_obj_t;
|
||||
|
||||
mp_obj_t picoscroll_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
_PicoScroll_obj_t *self = nullptr;
|
||||
|
||||
self = m_new_obj_with_finaliser(PicoScroll_obj_t);
|
||||
self->base.type = &PicoScroll_type;
|
||||
|
||||
self->scroll = m_new_class(PicoScroll);
|
||||
self->scroll->init();
|
||||
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll___del__(mp_obj_t self_in) {
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t);
|
||||
m_del_class(PicoScroll, self->scroll);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_get_width() {
|
||||
mp_obj_t picoscroll_get_width(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoScroll::WIDTH);
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_get_height() {
|
||||
mp_obj_t picoscroll_get_height(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoScroll::HEIGHT);
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_update() {
|
||||
if(scroll != nullptr)
|
||||
scroll->update();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
mp_obj_t picoscroll_show(mp_obj_t self_in) {
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t);
|
||||
self->scroll->update();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_set_pixel(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t v_obj) {
|
||||
if (scroll != nullptr) {
|
||||
int x = mp_obj_get_int(x_obj);
|
||||
int y = mp_obj_get_int(y_obj);
|
||||
int val = mp_obj_get_int(v_obj);
|
||||
mp_obj_t picoscroll_set_pixel(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's self + 3
|
||||
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoScroll_obj_t);
|
||||
|
||||
if (x < 0 || x >= PicoScroll::WIDTH || y < 0 || y >= PicoScroll::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
else {
|
||||
if (val < 0 || val > 255)
|
||||
mp_raise_ValueError("val out of range. Expected 0 to 255");
|
||||
else
|
||||
scroll->set_pixel(x, y, val);
|
||||
int x = mp_obj_get_int(args[1]);
|
||||
int y = mp_obj_get_int(args[2]);
|
||||
int val = mp_obj_get_int(args[3]);
|
||||
|
||||
if (x < 0 || x >= PicoScroll::WIDTH || y < 0 || y >= PicoScroll::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
if (val < 0 || val > 255)
|
||||
mp_raise_ValueError("val out of range. Expected 0 to 255");
|
||||
|
||||
self->scroll->set_pixel(x, y, val);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_scroll_text(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's self + 3
|
||||
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoScroll_obj_t);
|
||||
|
||||
int brightness = mp_obj_get_int(args[2]);
|
||||
int delay_ms = mp_obj_get_int(args[3]);
|
||||
|
||||
if(mp_obj_is_str_or_bytes(args[1])) {
|
||||
GET_STR_DATA_LEN(args[1], str, str_len);
|
||||
|
||||
int draw_buffer_len = 6 * str_len;
|
||||
char *draw_buffer = m_new(char, draw_buffer_len);
|
||||
|
||||
render_text((const char *)str, str_len, (unsigned char *)draw_buffer, draw_buffer_len);
|
||||
|
||||
for (int offset = -PicoScroll::WIDTH; offset < draw_buffer_len; offset++) {
|
||||
self->scroll->clear();
|
||||
self->scroll->set_bitmap_1d((const char *)draw_buffer, draw_buffer_len, brightness, offset);
|
||||
self->scroll->update();
|
||||
MICROPY_EVENT_POLL_HOOK
|
||||
sleep_ms(delay_ms);
|
||||
}
|
||||
} else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
m_free(draw_buffer);
|
||||
|
||||
mp_obj_t picoscroll_scroll_text(mp_obj_t text_obj, mp_obj_t brightness_obj,
|
||||
mp_obj_t delay_ms_obj) {
|
||||
if (scroll != nullptr) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(text_obj, &bufinfo, MP_BUFFER_READ);
|
||||
int brightness = mp_obj_get_int(brightness_obj);
|
||||
int delay_ms = mp_obj_get_int(delay_ms_obj);
|
||||
|
||||
scroll->scroll_text((const char *)bufinfo.buf, bufinfo.len, brightness, delay_ms);
|
||||
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
self->scroll->clear();
|
||||
self->scroll->update();
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_show_text(mp_obj_t text_obj, mp_obj_t brightness_obj,
|
||||
mp_obj_t offset_obj) {
|
||||
if (scroll != nullptr) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(text_obj, &bufinfo, MP_BUFFER_READ);
|
||||
int brightness = mp_obj_get_int(brightness_obj);
|
||||
int offset = mp_obj_get_int(offset_obj);
|
||||
mp_obj_t picoscroll_show_text(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's self + 3
|
||||
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoScroll_obj_t);
|
||||
|
||||
scroll->set_text((const char *)bufinfo.buf, bufinfo.len, brightness, offset);
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
int brightness = mp_obj_get_int(args[2]);
|
||||
int offset = mp_obj_get_int(args[3]);
|
||||
|
||||
if(mp_obj_is_str_or_bytes(args[1])) {
|
||||
GET_STR_DATA_LEN(args[1], str, str_len);
|
||||
|
||||
int draw_buffer_len = 6 * str_len;
|
||||
char *draw_buffer = m_new(char, draw_buffer_len);
|
||||
|
||||
render_text((const char *)str, str_len, (unsigned char *)draw_buffer, draw_buffer_len);
|
||||
self->scroll->set_bitmap_1d((const char *)draw_buffer, draw_buffer_len, brightness, offset);
|
||||
|
||||
m_free(draw_buffer);
|
||||
}
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_set_pixels(mp_obj_t image_obj) {
|
||||
if (scroll != nullptr) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(image_obj, &bufinfo, MP_BUFFER_RW);
|
||||
mp_obj_t picoscroll_set_pixels(mp_obj_t self_in, mp_obj_t image_obj) {
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t);
|
||||
|
||||
if (bufinfo.len < (PicoScroll::WIDTH * PicoScroll::HEIGHT)) {
|
||||
mp_raise_msg(&mp_type_IndexError, BUFFER_TOO_SMALL_MSG);
|
||||
}
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(image_obj, &bufinfo, MP_BUFFER_RW);
|
||||
|
||||
scroll->set_pixels((const char*)bufinfo.buf);
|
||||
} else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_show_bitmap_1d(mp_obj_t bitmap_obj, mp_obj_t brightness_obj,
|
||||
mp_obj_t offset_obj) {
|
||||
if (scroll != nullptr) {
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(bitmap_obj, &bufinfo, MP_BUFFER_RW);
|
||||
int offset = mp_obj_get_int(offset_obj);
|
||||
int brightness = mp_obj_get_int(brightness_obj);
|
||||
int length = bufinfo.len;
|
||||
|
||||
// clear the scroll, so only need to write visible bytes
|
||||
scroll->clear();
|
||||
|
||||
if ((offset < -PicoScroll::WIDTH) || (offset > length)) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
scroll->set_bitmap_1d((const char *)bufinfo.buf, bufinfo.len, brightness, offset);
|
||||
} else {
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
if (bufinfo.len < (PicoScroll::WIDTH * PicoScroll::HEIGHT)) {
|
||||
mp_raise_msg(&mp_type_IndexError, BUFFER_TOO_SMALL_MSG);
|
||||
}
|
||||
|
||||
self->scroll->set_pixels((const char*)bufinfo.buf);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_clear() {
|
||||
if (scroll != nullptr)
|
||||
scroll->clear();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
mp_obj_t picoscroll_show_bitmap_1d(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's self + 3
|
||||
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(args[0], PicoScroll_obj_t);
|
||||
|
||||
mp_buffer_info_t bufinfo;
|
||||
mp_get_buffer_raise(args[1], &bufinfo, MP_BUFFER_RW);
|
||||
int offset = mp_obj_get_int(args[3]);
|
||||
int brightness = mp_obj_get_int(args[2]);
|
||||
int length = bufinfo.len;
|
||||
|
||||
// clear the scroll, so only need to write visible bytes
|
||||
self->scroll->clear();
|
||||
|
||||
if ((offset < -PicoScroll::WIDTH) || (offset > length)) {
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
self->scroll->set_bitmap_1d((const char *)bufinfo.buf, bufinfo.len, brightness, offset);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_is_pressed(mp_obj_t button_obj) {
|
||||
mp_obj_t picoscroll_clear(mp_obj_t self_in) {
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t);
|
||||
self->scroll->clear();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_is_pressed(mp_obj_t self_in, mp_obj_t button_obj) {
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t);
|
||||
|
||||
bool buttonPressed = false;
|
||||
|
||||
if(scroll != nullptr) {
|
||||
int buttonID = mp_obj_get_int(button_obj);
|
||||
switch(buttonID) {
|
||||
case 0:
|
||||
buttonPressed = scroll->is_pressed(PicoScroll::A);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
buttonPressed = scroll->is_pressed(PicoScroll::B);
|
||||
break;
|
||||
int buttonID = mp_obj_get_int(button_obj);
|
||||
switch(buttonID) {
|
||||
case 0:
|
||||
buttonPressed = self->scroll->is_pressed(PicoScroll::A);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
buttonPressed = scroll->is_pressed(PicoScroll::X);
|
||||
break;
|
||||
case 1:
|
||||
buttonPressed = self->scroll->is_pressed(PicoScroll::B);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
buttonPressed = scroll->is_pressed(PicoScroll::Y);
|
||||
break;
|
||||
case 2:
|
||||
buttonPressed = self->scroll->is_pressed(PicoScroll::X);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_raise_ValueError("button not valid. Expected 0 to 3");
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
buttonPressed = self->scroll->is_pressed(PicoScroll::Y);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_raise_ValueError("button not valid. Expected 0 to 3");
|
||||
break;
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
return buttonPressed ? mp_const_true : mp_const_false;
|
||||
}
|
||||
|
||||
mp_obj_t picoscroll_update(mp_obj_t self_in, mp_obj_t graphics_in) {
|
||||
PicoScroll_obj_t *self = MP_OBJ_TO_PTR2(self_in, PicoScroll_obj_t);
|
||||
ModPicoGraphics_obj_t *picographics = MP_OBJ_TO_PTR2(graphics_in, ModPicoGraphics_obj_t);
|
||||
|
||||
if(picographics->base.type == &ModPicoGraphics_type) {
|
||||
self->scroll->update(picographics->graphics);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,22 @@
|
|||
// Include MicroPython API.
|
||||
#include "py/runtime.h"
|
||||
#include "py/objstr.h"
|
||||
|
||||
extern const mp_obj_type_t PicoScroll_type;
|
||||
extern const mp_obj_type_t ModPicoGraphics_type;
|
||||
|
||||
// Declare the functions we'll make available in Python
|
||||
extern mp_obj_t picoscroll_init();
|
||||
extern mp_obj_t picoscroll_get_width();
|
||||
extern mp_obj_t picoscroll_get_height();
|
||||
extern mp_obj_t picoscroll_update();
|
||||
extern mp_obj_t picoscroll_set_pixel(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t v_obj);
|
||||
extern mp_obj_t picoscroll_set_pixels(mp_obj_t image_obj);
|
||||
extern mp_obj_t picoscroll_show_text(mp_obj_t text_obj, mp_obj_t brightness, mp_obj_t offset);
|
||||
extern mp_obj_t picoscroll_scroll_text(mp_obj_t text_obj, mp_obj_t brightness, mp_obj_t delay);
|
||||
extern mp_obj_t picoscroll_show_bitmap_1d(mp_obj_t bitmap_obj, mp_obj_t brightness, mp_obj_t offset);
|
||||
extern mp_obj_t picoscroll_clear();
|
||||
extern mp_obj_t picoscroll_is_pressed(mp_obj_t button_obj);
|
||||
extern mp_obj_t picoscroll_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t picoscroll___del__(mp_obj_t self_in);
|
||||
extern mp_obj_t picoscroll_get_width(mp_obj_t self_in);
|
||||
extern mp_obj_t picoscroll_get_height(mp_obj_t self_in);
|
||||
extern mp_obj_t picoscroll_show(mp_obj_t self_in);
|
||||
extern mp_obj_t picoscroll_set_pixel(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picoscroll_set_pixels(mp_obj_t self_in, mp_obj_t image_obj);
|
||||
extern mp_obj_t picoscroll_show_text(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picoscroll_scroll_text(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picoscroll_show_bitmap_1d(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picoscroll_clear(mp_obj_t self_in);
|
||||
extern mp_obj_t picoscroll_is_pressed(mp_obj_t self_in, mp_obj_t button_obj);
|
||||
|
||||
extern mp_obj_t picoscroll_update(mp_obj_t self_in, mp_obj_t graphics_in);
|
|
@ -10,6 +10,7 @@ pico_generate_pio_header(usermod_pico_unicorn ${CMAKE_CURRENT_LIST_DIR}/../../..
|
|||
|
||||
target_include_directories(usermod_pico_unicorn INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/../../../libraries/pico_graphics/
|
||||
)
|
||||
|
||||
target_compile_definitions(usermod_pico_unicorn INTERFACE
|
||||
|
|
|
@ -16,30 +16,55 @@ enum buttons
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/***** Module Functions *****/
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_init_obj, picounicorn_init);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_get_width_obj, picounicorn_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_get_height_obj, picounicorn_get_height);
|
||||
//STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_update_obj, picounicorn_update);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picounicorn_set_pixel_obj, 5, 5, picounicorn_set_pixel);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_3(picounicorn_set_pixel_value_obj, picounicorn_set_pixel_value);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_0(picounicorn_clear_obj, picounicorn_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_is_pressed_obj, picounicorn_is_pressed);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn__del__obj, picounicorn__del__);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picounicorn_set_pixel_obj, 6, 6, picounicorn_set_pixel);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(picounicorn_set_pixel_value_obj, 4, 4, picounicorn_set_pixel_value);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_clear_obj, picounicorn_clear);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(picounicorn_is_pressed_obj, picounicorn_is_pressed);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_get_width_obj, picounicorn_get_width);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(picounicorn_get_height_obj, picounicorn_get_height);
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(picounicorn_update_obj, picounicorn_update);
|
||||
|
||||
/***** Globals Table *****/
|
||||
STATIC const mp_rom_map_elem_t picounicorn_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picounicorn) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&picounicorn_init_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picounicorn_get_width_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picounicorn_get_height_obj) },
|
||||
//{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picounicorn_update_obj) },
|
||||
STATIC const mp_rom_map_elem_t picounicorn_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&picounicorn__del__obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&picounicorn_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_pixel), MP_ROM_PTR(&picounicorn_set_pixel_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_set_pixel_value), MP_ROM_PTR(&picounicorn_set_pixel_value_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_clear), MP_ROM_PTR(&picounicorn_clear_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picounicorn_is_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_is_pressed), MP_ROM_PTR(&picounicorn_is_pressed_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_width), MP_ROM_PTR(&picounicorn_get_width_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_get_height), MP_ROM_PTR(&picounicorn_get_height_obj) },
|
||||
};
|
||||
|
||||
STATIC MP_DEFINE_CONST_DICT(picounicorn_locals_dict, picounicorn_locals_dict_table);
|
||||
|
||||
#ifdef MP_DEFINE_CONST_OBJ_TYPE
|
||||
MP_DEFINE_CONST_OBJ_TYPE(
|
||||
picounicorn_type,
|
||||
MP_QSTR_PicoUnicorn,
|
||||
MP_TYPE_FLAG_NONE,
|
||||
make_new, picounicorn_make_new,
|
||||
locals_dict, (mp_obj_dict_t*)&picounicorn_locals_dict
|
||||
);
|
||||
#else
|
||||
const mp_obj_type_t picounicorn_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_PicoUnicorn,
|
||||
.make_new = picounicorn_make_new,
|
||||
.locals_dict = (mp_obj_dict_t*)&picounicorn_locals_dict,
|
||||
};
|
||||
#endif
|
||||
|
||||
/***** Globals Table *****/
|
||||
STATIC const mp_rom_map_elem_t picounicorn_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_picounicorn) },
|
||||
{ MP_OBJ_NEW_QSTR(MP_QSTR_PicoUnicorn), (mp_obj_t)&picounicorn_type },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_A), MP_ROM_INT(BUTTON_A) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_B), MP_ROM_INT(BUTTON_B) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_X), MP_ROM_INT(BUTTON_X) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_BUTTON_Y), MP_ROM_INT(BUTTON_Y) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_WIDTH), MP_ROM_INT(16) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_HEIGHT), MP_ROM_INT(7) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_picounicorn_globals, picounicorn_globals_table);
|
||||
|
||||
|
|
|
@ -2,127 +2,146 @@
|
|||
#include "hardware/sync.h"
|
||||
#include "pico/binary_info.h"
|
||||
|
||||
#include "micropython/modules/util.hpp"
|
||||
#include "libraries/pico_unicorn/pico_unicorn.hpp"
|
||||
#include "libraries/pico_graphics/pico_graphics.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
||||
PicoUnicorn *unicorn = nullptr;
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "pico_unicorn.h"
|
||||
#include "micropython/modules/pimoroni_i2c/pimoroni_i2c.h"
|
||||
#include "py/builtin.h"
|
||||
|
||||
#define NOT_INITIALISED_MSG "Cannot call this function, as picounicorn is not initialised. Call picounicorn.init() first."
|
||||
typedef struct _picounicorn_obj_t {
|
||||
mp_obj_base_t base;
|
||||
PicoUnicorn *unicorn;
|
||||
} picounicorn_obj_t;
|
||||
|
||||
mp_obj_t picounicorn_init() {
|
||||
if(unicorn == nullptr)
|
||||
unicorn = new PicoUnicorn();
|
||||
unicorn->init();
|
||||
// from picographics/picographics.cpp
|
||||
// used to support accepting a PicoGraphics class
|
||||
typedef struct _ModPicoGraphics_obj_t {
|
||||
mp_obj_base_t base;
|
||||
PicoGraphics *graphics;
|
||||
DisplayDriver *display;
|
||||
void *spritedata;
|
||||
void *buffer;
|
||||
_PimoroniI2C_obj_t *i2c;
|
||||
} ModPicoGraphics_obj_t;
|
||||
|
||||
mp_obj_t picounicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
|
||||
picounicorn_obj_t *self = m_new_obj_with_finaliser(picounicorn_obj_t);
|
||||
self->base.type = &picounicorn_type;
|
||||
self->unicorn = m_new_class(PicoUnicorn);
|
||||
return MP_OBJ_FROM_PTR(self);
|
||||
}
|
||||
|
||||
mp_obj_t picounicorn__del__(mp_obj_t self_in) {
|
||||
picounicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, picounicorn_obj_t);
|
||||
m_del_class(PicoUnicorn, self->unicorn);
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picounicorn_get_width() {
|
||||
mp_obj_t picounicorn_get_width(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoUnicorn::WIDTH);
|
||||
}
|
||||
|
||||
mp_obj_t picounicorn_get_height() {
|
||||
mp_obj_t picounicorn_get_height(mp_obj_t self_in) {
|
||||
(void)self_in;
|
||||
return mp_obj_new_int(PicoUnicorn::HEIGHT);
|
||||
}
|
||||
|
||||
// mp_obj_t picounicorn_update() {
|
||||
// unicorn.update();
|
||||
// return mp_const_none;
|
||||
// }
|
||||
|
||||
mp_obj_t picounicorn_set_pixel(mp_uint_t n_args, const mp_obj_t *args) {
|
||||
(void)n_args; //Unused input parameter, we know it's 5
|
||||
(void)n_args; // Unused input parameter, we know it's 5
|
||||
|
||||
if(unicorn != nullptr) {
|
||||
int x = mp_obj_get_int(args[0]);
|
||||
int y = mp_obj_get_int(args[1]);
|
||||
int r = mp_obj_get_int(args[2]);
|
||||
int g = mp_obj_get_int(args[3]);
|
||||
int b = mp_obj_get_int(args[4]);
|
||||
enum { ARG_self, ARG_x, ARG_y, ARG_r, ARG_g, ARG_b };
|
||||
|
||||
if(x < 0 || x >= PicoUnicorn::WIDTH || y < 0 || y >= PicoUnicorn::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
else
|
||||
{
|
||||
if(r < 0 || r > 255)
|
||||
mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
else if(g < 0 || g > 255)
|
||||
mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
else if(b < 0 || b > 255)
|
||||
mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
else
|
||||
unicorn->set_pixel(x, y, r, g, b);
|
||||
}
|
||||
picounicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], picounicorn_obj_t);
|
||||
|
||||
int x = mp_obj_get_int(args[ARG_x]);
|
||||
int y = mp_obj_get_int(args[ARG_y]);
|
||||
int r = mp_obj_get_int(args[ARG_r]);
|
||||
int g = mp_obj_get_int(args[ARG_g]);
|
||||
int b = mp_obj_get_int(args[ARG_b]);
|
||||
|
||||
if(x < 0 || x >= PicoUnicorn::WIDTH || y < 0 || y >= PicoUnicorn::HEIGHT) {
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
if(r < 0 || r > 255) mp_raise_ValueError("r out of range. Expected 0 to 255");
|
||||
if(g < 0 || g > 255) mp_raise_ValueError("g out of range. Expected 0 to 255");
|
||||
if(b < 0 || b > 255) mp_raise_ValueError("b out of range. Expected 0 to 255");
|
||||
self->unicorn->set_pixel(x, y, r, g, b);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picounicorn_set_pixel_value(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t v_obj) {
|
||||
if(unicorn != nullptr) {
|
||||
int x = mp_obj_get_int(x_obj);
|
||||
int y = mp_obj_get_int(y_obj);
|
||||
int val = mp_obj_get_int(v_obj);
|
||||
mp_obj_t picounicorn_set_pixel_value(size_t n_args, const mp_obj_t *args) {
|
||||
enum { ARG_self, ARG_x, ARG_y, ARG_v };
|
||||
|
||||
if(x < 0 || x >= PicoUnicorn::WIDTH || y < 0 || y >= PicoUnicorn::HEIGHT)
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
else {
|
||||
if(val < 0 || val > 255)
|
||||
mp_raise_ValueError("val out of range. Expected 0 to 255");
|
||||
else
|
||||
unicorn->set_pixel(x, y, val);
|
||||
}
|
||||
picounicorn_obj_t *self = MP_OBJ_TO_PTR2(args[ARG_self], picounicorn_obj_t);
|
||||
|
||||
int x = mp_obj_get_int(args[ARG_x]);
|
||||
int y = mp_obj_get_int(args[ARG_y]);
|
||||
int val = mp_obj_get_int(args[ARG_v]);
|
||||
|
||||
if(x < 0 || x >= PicoUnicorn::WIDTH || y < 0 || y >= PicoUnicorn::HEIGHT) {
|
||||
mp_raise_ValueError("x or y out of range.");
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
if(val < 0 || val > 255) mp_raise_ValueError("val out of range. Expected 0 to 255");
|
||||
|
||||
self->unicorn->set_pixel(x, y, val);
|
||||
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picounicorn_clear() {
|
||||
if(unicorn != nullptr)
|
||||
unicorn->clear();
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
mp_obj_t picounicorn_clear(mp_obj_t self_in) {
|
||||
picounicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, picounicorn_obj_t);
|
||||
self->unicorn->clear();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
mp_obj_t picounicorn_is_pressed(mp_obj_t button_obj) {
|
||||
mp_obj_t picounicorn_is_pressed(mp_obj_t self_in, mp_obj_t button_obj) {
|
||||
picounicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, picounicorn_obj_t);
|
||||
|
||||
bool buttonPressed = false;
|
||||
|
||||
if(unicorn != nullptr) {
|
||||
int buttonID = mp_obj_get_int(button_obj);
|
||||
switch(buttonID) {
|
||||
case 0:
|
||||
buttonPressed = unicorn->is_pressed(PicoUnicorn::A);
|
||||
break;
|
||||
int buttonID = mp_obj_get_int(button_obj);
|
||||
|
||||
case 1:
|
||||
buttonPressed = unicorn->is_pressed(PicoUnicorn::B);
|
||||
break;
|
||||
switch(buttonID) {
|
||||
case 0:
|
||||
buttonPressed = self->unicorn->is_pressed(PicoUnicorn::A);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
buttonPressed = unicorn->is_pressed(PicoUnicorn::X);
|
||||
break;
|
||||
case 1:
|
||||
buttonPressed = self->unicorn->is_pressed(PicoUnicorn::B);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
buttonPressed = unicorn->is_pressed(PicoUnicorn::Y);
|
||||
break;
|
||||
case 2:
|
||||
buttonPressed = self->unicorn->is_pressed(PicoUnicorn::X);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_raise_ValueError("button not valid. Expected 0 to 3");
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
buttonPressed = self->unicorn->is_pressed(PicoUnicorn::Y);
|
||||
break;
|
||||
|
||||
default:
|
||||
mp_raise_ValueError("button not valid. Expected 0 to 3");
|
||||
break;
|
||||
}
|
||||
else
|
||||
mp_raise_msg(&mp_type_RuntimeError, NOT_INITIALISED_MSG);
|
||||
|
||||
return buttonPressed ? mp_const_true : mp_const_false;
|
||||
}
|
||||
|
||||
mp_obj_t picounicorn_update(mp_obj_t self_in, mp_obj_t graphics_in) {
|
||||
picounicorn_obj_t *self = MP_OBJ_TO_PTR2(self_in, picounicorn_obj_t);
|
||||
ModPicoGraphics_obj_t *picographics = MP_OBJ_TO_PTR2(graphics_in, ModPicoGraphics_obj_t);
|
||||
|
||||
if(picographics->base.type == &ModPicoGraphics_type) {
|
||||
self->unicorn->update(picographics->graphics);
|
||||
}
|
||||
return mp_const_none;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,16 @@
|
|||
// Include MicroPython API.
|
||||
//#include "py/obj.h"
|
||||
#include "py/runtime.h"
|
||||
|
||||
// Declare the functions we'll make available in Python
|
||||
extern mp_obj_t picounicorn_init();
|
||||
extern mp_obj_t picounicorn_get_width();
|
||||
extern mp_obj_t picounicorn_get_height();
|
||||
//extern mp_obj_t picounicorn_update();
|
||||
extern const mp_obj_type_t picounicorn_type;
|
||||
extern const mp_obj_type_t ModPicoGraphics_type;
|
||||
|
||||
extern mp_obj_t picounicorn_get_width(mp_obj_t self_in);
|
||||
extern mp_obj_t picounicorn_get_height(mp_obj_t self_in);
|
||||
|
||||
extern mp_obj_t picounicorn__del__(mp_obj_t self_in);
|
||||
extern mp_obj_t picounicorn_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args);
|
||||
extern mp_obj_t picounicorn_set_pixel(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picounicorn_set_pixel_value(mp_obj_t x_obj, mp_obj_t y_obj, mp_obj_t v_obj);
|
||||
extern mp_obj_t picounicorn_clear();
|
||||
extern mp_obj_t picounicorn_is_pressed(mp_obj_t button_obj);
|
||||
extern mp_obj_t picounicorn_set_pixel_value(mp_uint_t n_args, const mp_obj_t *args);
|
||||
extern mp_obj_t picounicorn_clear(mp_obj_t self_in);
|
||||
extern mp_obj_t picounicorn_is_pressed(mp_obj_t self_in, mp_obj_t button_obj);
|
||||
|
||||
extern mp_obj_t picounicorn_update(mp_obj_t self_in, mp_obj_t graphics_in);
|
|
@ -2,6 +2,7 @@
|
|||
#include "hardware/sync.h"
|
||||
#include "pico/binary_info.h"
|
||||
|
||||
#include "micropython/modules/util.hpp"
|
||||
#include "libraries/pico_wireless/pico_wireless.hpp"
|
||||
|
||||
using namespace pimoroni;
|
||||
|
@ -51,7 +52,7 @@ mp_obj_t mp_ip_to_obj(IPAddress ip) {
|
|||
|
||||
mp_obj_t picowireless_init() {
|
||||
if(wireless == nullptr)
|
||||
wireless = new PicoWireless();
|
||||
wireless = m_tracked_alloc_class(PicoWireless);
|
||||
wireless->init();
|
||||
return mp_const_none;
|
||||
}
|
||||
|
|
|
@ -152,6 +152,8 @@ STATIC const mp_map_elem_t picographics_globals_table[] = {
|
|||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_INTERSTATE75_256X64), MP_ROM_INT(DISPLAY_INTERSTATE75_256X64) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_INKY_FRAME_7), MP_ROM_INT(DISPLAY_INKY_FRAME_7) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_COSMIC_UNICORN), MP_ROM_INT(DISPLAY_COSMIC_UNICORN) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_UNICORN_PACK), MP_ROM_INT(DISPLAY_UNICORN_PACK) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_DISPLAY_SCROLL_PACK), MP_ROM_INT(DISPLAY_SCROLL_PACK) },
|
||||
|
||||
{ MP_ROM_QSTR(MP_QSTR_PEN_1BIT), MP_ROM_INT(PEN_1BIT) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_PEN_P4), MP_ROM_INT(PEN_P4) },
|
||||
|
|
|
@ -23,10 +23,10 @@ extern "C" {
|
|||
#include "py/reader.h"
|
||||
#include "extmod/vfs.h"
|
||||
|
||||
std::string mp_obj_to_string_r(const mp_obj_t &obj) {
|
||||
const std::string_view mp_obj_to_string_r(const mp_obj_t &obj) {
|
||||
if(mp_obj_is_str_or_bytes(obj)) {
|
||||
GET_STR_DATA_LEN(obj, str, str_len);
|
||||
return (const char*)str;
|
||||
return std::string_view((const char*)str, str_len);
|
||||
}
|
||||
mp_raise_TypeError("can't convert object to str implicitly");
|
||||
}
|
||||
|
@ -210,6 +210,20 @@ bool get_display_settings(PicoGraphicsDisplay display, int &width, int &height,
|
|||
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
|
||||
if(pen_type == -1) pen_type = PEN_RGB888;
|
||||
break;
|
||||
case DISPLAY_UNICORN_PACK:
|
||||
width = 16;
|
||||
height = 7;
|
||||
bus_type = BUS_PIO;
|
||||
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
|
||||
if(pen_type == -1) pen_type = PEN_RGB888;
|
||||
break;
|
||||
case DISPLAY_SCROLL_PACK:
|
||||
width = 17;
|
||||
height = 7;
|
||||
bus_type = BUS_PIO;
|
||||
if(rotate == -1) rotate = (int)Rotation::ROTATE_0;
|
||||
if(pen_type == -1) pen_type = PEN_RGB888;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -331,17 +345,18 @@ mp_obj_t ModPicoGraphics_make_new(const mp_obj_type_t *type, size_t n_args, size
|
|||
|
||||
} else if (display == DISPLAY_INKY_PACK) {
|
||||
self->display = m_new_class(UC8151, width, height, (Rotation)rotate, spi_bus);
|
||||
|
||||
} else if (display == DISPLAY_GALACTIC_UNICORN) {
|
||||
self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate);
|
||||
|
||||
} else if (display == DISPLAY_GFX_PACK) {
|
||||
self->display = m_new_class(ST7567, width, height, spi_bus);
|
||||
|
||||
} else if (display == DISPLAY_INTERSTATE75_32X32 || display == DISPLAY_INTERSTATE75_64X64 || display == DISPLAY_INTERSTATE75_64X32) {
|
||||
self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate);
|
||||
|
||||
} else if (display == DISPLAY_COSMIC_UNICORN) {
|
||||
} else if (display == DISPLAY_INTERSTATE75_32X32
|
||||
|| display == DISPLAY_INTERSTATE75_64X64
|
||||
|| display == DISPLAY_INTERSTATE75_64X32
|
||||
|| display == DISPLAY_GALACTIC_UNICORN
|
||||
|| display == DISPLAY_COSMIC_UNICORN
|
||||
|| display == DISPLAY_UNICORN_PACK
|
||||
|| display == DISPLAY_SCROLL_PACK) {
|
||||
// Create a dummy display driver
|
||||
self->display = m_new_class(DisplayDriver, width, height, (Rotation)rotate);
|
||||
|
||||
} else {
|
||||
|
@ -935,7 +950,7 @@ mp_obj_t ModPicoGraphics_text(size_t n_args, const mp_obj_t *pos_args, mp_map_t
|
|||
|
||||
GET_STR_DATA_LEN(text_obj, str, str_len);
|
||||
|
||||
std::string t((const char*)str);
|
||||
const std::string_view t((const char*)str, str_len);
|
||||
|
||||
int x = args[ARG_x].u_int;
|
||||
int y = args[ARG_y].u_int;
|
||||
|
@ -969,7 +984,7 @@ mp_obj_t ModPicoGraphics_measure_text(size_t n_args, const mp_obj_t *pos_args, m
|
|||
|
||||
GET_STR_DATA_LEN(text_obj, str, str_len);
|
||||
|
||||
std::string t((const char*)str);
|
||||
const std::string_view t((const char*)str, str_len);
|
||||
|
||||
float scale = args[ARG_scale].u_obj == mp_const_none ? 2.0f : mp_obj_get_float(args[ARG_scale].u_obj);
|
||||
int letter_spacing = args[ARG_spacing].u_int;
|
||||
|
|
|
@ -25,7 +25,9 @@ enum PicoGraphicsDisplay {
|
|||
DISPLAY_INTERSTATE75_192X64,
|
||||
DISPLAY_INTERSTATE75_256X64,
|
||||
DISPLAY_INKY_FRAME_7,
|
||||
DISPLAY_COSMIC_UNICORN
|
||||
DISPLAY_COSMIC_UNICORN,
|
||||
DISPLAY_UNICORN_PACK,
|
||||
DISPLAY_SCROLL_PACK
|
||||
};
|
||||
|
||||
enum PicoGraphicsPenType {
|
||||
|
|
|
@ -1289,11 +1289,11 @@ mp_obj_t ServoCluster_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of pins
|
||||
pins = new uint8_t[pin_count];
|
||||
pins = m_new(uint8_t, pin_count);
|
||||
for(size_t i = 0; i < pin_count; i++) {
|
||||
int pin = mp_obj_get_int(items[i]);
|
||||
if(pin < 0 || pin >= (int)NUM_BANK0_GPIOS) {
|
||||
delete[] pins;
|
||||
m_free(pins);
|
||||
mp_raise_ValueError("a pin in the list or tuple is out of range. Expected 0 to 29");
|
||||
}
|
||||
else {
|
||||
|
@ -1348,7 +1348,7 @@ mp_obj_t ServoCluster_make_new(const mp_obj_type_t *type, size_t n_args, size_t
|
|||
|
||||
// Cleanup the pins array
|
||||
if(pins != nullptr)
|
||||
delete[] pins;
|
||||
m_free(pins);
|
||||
|
||||
if(!cluster->init()) {
|
||||
m_del_class(ServoCluster, cluster);
|
||||
|
@ -1449,11 +1449,11 @@ extern mp_obj_t ServoCluster_enable(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -1461,7 +1461,7 @@ extern mp_obj_t ServoCluster_enable(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
}
|
||||
}
|
||||
self->cluster->enable(servos, length, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1533,11 +1533,11 @@ extern mp_obj_t ServoCluster_disable(size_t n_args, const mp_obj_t *pos_args, mp
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -1545,7 +1545,7 @@ extern mp_obj_t ServoCluster_disable(size_t n_args, const mp_obj_t *pos_args, mp
|
|||
}
|
||||
}
|
||||
self->cluster->disable(servos, length, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1668,11 +1668,11 @@ extern mp_obj_t ServoCluster_pulse(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -1681,7 +1681,7 @@ extern mp_obj_t ServoCluster_pulse(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
}
|
||||
float pulse = mp_obj_get_float(args[ARG_pulse].u_obj);
|
||||
self->cluster->pulse(servos, length, pulse, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1786,11 +1786,11 @@ extern mp_obj_t ServoCluster_value(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -1799,7 +1799,7 @@ extern mp_obj_t ServoCluster_value(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
}
|
||||
float value = mp_obj_get_float(args[ARG_value].u_obj);
|
||||
self->cluster->value(servos, length, value, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1904,11 +1904,11 @@ extern mp_obj_t ServoCluster_phase(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -1917,7 +1917,7 @@ extern mp_obj_t ServoCluster_phase(size_t n_args, const mp_obj_t *pos_args, mp_m
|
|||
}
|
||||
float phase = mp_obj_get_float(args[ARG_phase].u_obj);
|
||||
self->cluster->phase(servos, length, phase, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2108,11 +2108,11 @@ extern mp_obj_t ServoCluster_to_min(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -2120,7 +2120,7 @@ extern mp_obj_t ServoCluster_to_min(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
}
|
||||
}
|
||||
self->cluster->to_min(servos, length, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2196,11 +2196,11 @@ extern mp_obj_t ServoCluster_to_mid(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -2208,7 +2208,7 @@ extern mp_obj_t ServoCluster_to_mid(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
}
|
||||
}
|
||||
self->cluster->to_mid(servos, length, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2284,11 +2284,11 @@ extern mp_obj_t ServoCluster_to_max(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -2296,7 +2296,7 @@ extern mp_obj_t ServoCluster_to_max(size_t n_args, const mp_obj_t *pos_args, mp_
|
|||
}
|
||||
}
|
||||
self->cluster->to_max(servos, length, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2376,11 +2376,11 @@ extern mp_obj_t ServoCluster_to_percent(size_t n_args, const mp_obj_t *pos_args,
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -2389,7 +2389,7 @@ extern mp_obj_t ServoCluster_to_percent(size_t n_args, const mp_obj_t *pos_args,
|
|||
}
|
||||
float in = mp_obj_get_float(args[ARG_in].u_obj);
|
||||
self->cluster->to_percent(servos, length, in, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2448,11 +2448,11 @@ extern mp_obj_t ServoCluster_to_percent(size_t n_args, const mp_obj_t *pos_args,
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -2463,7 +2463,7 @@ extern mp_obj_t ServoCluster_to_percent(size_t n_args, const mp_obj_t *pos_args,
|
|||
float in_min = mp_obj_get_float(args[ARG_in_min].u_obj);
|
||||
float in_max = mp_obj_get_float(args[ARG_in_max].u_obj);
|
||||
self->cluster->to_percent(servos, length, in, in_min, in_max, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2526,11 +2526,11 @@ extern mp_obj_t ServoCluster_to_percent(size_t n_args, const mp_obj_t *pos_args,
|
|||
mp_raise_TypeError("list or tuple must contain at least one integer");
|
||||
else {
|
||||
// Create and populate a local array of servo indices
|
||||
uint8_t *servos = new uint8_t[length];
|
||||
uint8_t *servos = m_new(uint8_t, length);
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
int servo = mp_obj_get_int(items[i]);
|
||||
if(servo < 0 || servo >= servo_count) {
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("a servo in the list or tuple is out of range. Expected 0 to %d"), servo_count - 1);
|
||||
}
|
||||
else {
|
||||
|
@ -2543,7 +2543,7 @@ extern mp_obj_t ServoCluster_to_percent(size_t n_args, const mp_obj_t *pos_args,
|
|||
float value_min = mp_obj_get_float(args[ARG_value_min].u_obj);
|
||||
float value_max = mp_obj_get_float(args[ARG_value_max].u_obj);
|
||||
self->cluster->to_percent(servos, length, in, in_min, in_max, value_min, value_max, args[ARG_load].u_bool);
|
||||
delete[] servos;
|
||||
m_free(servos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,4 +13,7 @@
|
|||
|
||||
|
||||
#define m_new_class(cls, ...) new(m_new(cls, 1)) cls(__VA_ARGS__)
|
||||
#define m_del_class(cls, ptr) ptr->~cls();m_del(cls, ptr, 1)
|
||||
#define m_del_class(cls, ptr) ptr->~cls();m_del(cls, ptr, 1)
|
||||
|
||||
#define m_tracked_alloc_class(cls, ...) new(m_tracked_calloc(1, sizeof(cls))) cls(__VA_ARGS__)
|
||||
#define m_tracked_free_class(cls, ptr) ptr->~cls();m_tracked_free(ptr)
|
Ładowanie…
Reference in New Issue