diff --git a/.gitignore b/.gitignore deleted file mode 100644 index ac4d88d..0000000 --- a/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.ignore diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 84792a2..0000000 --- a/.gitmodules +++ /dev/null @@ -1,12 +0,0 @@ -[submodule "ch32v-insert-coin/ext/ch32-hal"] - path = ch32v-insert-coin/ext/ch32-hal - url = https://github.com/sigil-03/ch32-hal.git -[submodule "ch32v-insert-coin/ext/qingke"] - path = ch32v-insert-coin/ext/qingke - url = https://github.com/ch32-rs/qingke.git -[submodule "ch32v-insert-coin/ext/adpcm-pwm-dac"] - path = ch32v-insert-coin/ext/adpcm-pwm-dac - url = https://git.glyphs.tech/sigil-03/adpcm-pwm-dac.git -[submodule "ch32v-insert-coin/ext/wavetable-synth"] - path = ch32v-insert-coin/ext/wavetable-synth - url = https://git.glyphs.tech/sigil-03/wavetable-synth.git diff --git a/02175f27333ffe6b0c61218fae3142b6/description b/02175f27333ffe6b0c61218fae3142b6/description new file mode 100644 index 0000000..c2ce541 --- /dev/null +++ b/02175f27333ffe6b0c61218fae3142b6/description @@ -0,0 +1 @@ +enter deep sleep after long button press diff --git a/02175f27333ffe6b0c61218fae3142b6/tags b/02175f27333ffe6b0c61218fae3142b6/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/02175f27333ffe6b0c61218fae3142b6/tags @@ -0,0 +1 @@ +feature diff --git a/0acf72abc9e4641d0683e1bb5f2cf829/comments/6eb67d2adaef9836f4fde15755ec8c80/description b/0acf72abc9e4641d0683e1bb5f2cf829/comments/6eb67d2adaef9836f4fde15755ec8c80/description new file mode 100644 index 0000000..57ce453 --- /dev/null +++ b/0acf72abc9e4641d0683e1bb5f2cf829/comments/6eb67d2adaef9836f4fde15755ec8c80/description @@ -0,0 +1 @@ +modified blinky.rs to have 3 heartbeat blinks, was able to flash and observe the update. diff --git a/0acf72abc9e4641d0683e1bb5f2cf829/description b/0acf72abc9e4641d0683e1bb5f2cf829/description new file mode 100644 index 0000000..85a5ead --- /dev/null +++ b/0acf72abc9e4641d0683e1bb5f2cf829/description @@ -0,0 +1 @@ +blink an LED diff --git a/0acf72abc9e4641d0683e1bb5f2cf829/state b/0acf72abc9e4641d0683e1bb5f2cf829/state new file mode 100644 index 0000000..348ebd9 --- /dev/null +++ b/0acf72abc9e4641d0683e1bb5f2cf829/state @@ -0,0 +1 @@ +done \ No newline at end of file diff --git a/0acf72abc9e4641d0683e1bb5f2cf829/tags b/0acf72abc9e4641d0683e1bb5f2cf829/tags new file mode 100644 index 0000000..970be2b --- /dev/null +++ b/0acf72abc9e4641d0683e1bb5f2cf829/tags @@ -0,0 +1 @@ +phase-0 diff --git a/1892880782c8c31990d591c7b05fa6c3/comments/b90b4b71d0559508b16931dcf8250859/description b/1892880782c8c31990d591c7b05fa6c3/comments/b90b4b71d0559508b16931dcf8250859/description new file mode 100644 index 0000000..71e5f82 --- /dev/null +++ b/1892880782c8c31990d591c7b05fa6c3/comments/b90b4b71d0559508b16931dcf8250859/description @@ -0,0 +1 @@ +flashing successful using wch linkE programmer diff --git a/1892880782c8c31990d591c7b05fa6c3/description b/1892880782c8c31990d591c7b05fa6c3/description new file mode 100644 index 0000000..cd8422a --- /dev/null +++ b/1892880782c8c31990d591c7b05fa6c3/description @@ -0,0 +1 @@ +flash CH32V board diff --git a/1892880782c8c31990d591c7b05fa6c3/state b/1892880782c8c31990d591c7b05fa6c3/state new file mode 100644 index 0000000..348ebd9 --- /dev/null +++ b/1892880782c8c31990d591c7b05fa6c3/state @@ -0,0 +1 @@ +done \ No newline at end of file diff --git a/1892880782c8c31990d591c7b05fa6c3/tags b/1892880782c8c31990d591c7b05fa6c3/tags new file mode 100644 index 0000000..970be2b --- /dev/null +++ b/1892880782c8c31990d591c7b05fa6c3/tags @@ -0,0 +1 @@ +phase-0 diff --git a/2207e89d7201efbdceadd1c528d95341/description b/2207e89d7201efbdceadd1c528d95341/description new file mode 100644 index 0000000..2bf140f --- /dev/null +++ b/2207e89d7201efbdceadd1c528d95341/description @@ -0,0 +1,4 @@ +adpcm decoder + +REQUIREMENTS: +* write a module which takes as input adpcm data and outputs amplitudes diff --git a/2ff2ce2cae3914fbb8382372498abdd5/comments/93feac46f17a40fa41f543c56b5eafb2/description b/2ff2ce2cae3914fbb8382372498abdd5/comments/93feac46f17a40fa41f543c56b5eafb2/description new file mode 100644 index 0000000..1fa60ea --- /dev/null +++ b/2ff2ce2cae3914fbb8382372498abdd5/comments/93feac46f17a40fa41f543c56b5eafb2/description @@ -0,0 +1,21 @@ +had some pretty good progress tonight. got the board, soldered headers on, got it breadboarded, and got started trying to compile for the riscv core, and get the device flashed. + +there's good HAL support, actually, which is awesome: +[ch32-hal](https://github.com/ch32-rs/ch32-hal) + +i was able to eventually get it compiling, however flashing was a different story. + +apparently these chips don't have a 'standard' SWD implementation, and instead have some proprietary stuff from WCH which is annoying. + +there was this project, which has been inactive for 2 years: +[picorvd](https://github.com/aappleby/picorvd) + +it took a decent amount of work to get that project running - had to fix a bunch of broken dependencies, CMAKE version issues causing CMAKE to exit (protip: `export CMAKE_POLICY_VERSION_MINIMUM=3.5` from [stackoverflow](https://stackoverflow.com/questions/79534856/cannot-build-cmake-project-because-compatibility-with-cmake-3-5-has-been-remo). + +once that was all fixed, and i had soldered headers on / flashed a pico - i then had to get the riscv64 version of GDB running, and talking to the pico. GDB did seem to have trouble with the probe sometimes, but i was able to (i think) flash a program to one of the boards.... and it bricked. + +immediately i saw a bunch of activity on the SWD line, and the LED stopped blinking. + +what concerned me is that the waveform did not go away after a long period of time. i did determine that the pico was the one driving the line (on the ch32v it's SWIO, so because there were debug prints in the code, i thought it might have been from that). + +ultimately i think i'm going to just have to use the WCH Link(E?)... which is only $7 or so, but it does mean i'm going to have to wait for it... diff --git a/2ff2ce2cae3914fbb8382372498abdd5/comments/b0ff36f6102eaa30463133423f4d7ffe/description b/2ff2ce2cae3914fbb8382372498abdd5/comments/b0ff36f6102eaa30463133423f4d7ffe/description new file mode 100644 index 0000000..c8fcba0 --- /dev/null +++ b/2ff2ce2cae3914fbb8382372498abdd5/comments/b0ff36f6102eaa30463133423f4d7ffe/description @@ -0,0 +1 @@ +this is done - required getting a wch-linkE programmer, which was able to interface with probe-rs and program the ch32v003 chip. diff --git a/2ff2ce2cae3914fbb8382372498abdd5/description b/2ff2ce2cae3914fbb8382372498abdd5/description new file mode 100644 index 0000000..a0ed520 --- /dev/null +++ b/2ff2ce2cae3914fbb8382372498abdd5/description @@ -0,0 +1 @@ +set up toolchain for CH32V development diff --git a/2ff2ce2cae3914fbb8382372498abdd5/state b/2ff2ce2cae3914fbb8382372498abdd5/state new file mode 100644 index 0000000..348ebd9 --- /dev/null +++ b/2ff2ce2cae3914fbb8382372498abdd5/state @@ -0,0 +1 @@ +done \ No newline at end of file diff --git a/2ff2ce2cae3914fbb8382372498abdd5/tags b/2ff2ce2cae3914fbb8382372498abdd5/tags new file mode 100644 index 0000000..970be2b --- /dev/null +++ b/2ff2ce2cae3914fbb8382372498abdd5/tags @@ -0,0 +1 @@ +phase-0 diff --git a/3eb0b69b70c8853f9f533c6daa6acd1f/description b/3eb0b69b70c8853f9f533c6daa6acd1f/description new file mode 100644 index 0000000..bca79ec --- /dev/null +++ b/3eb0b69b70c8853f9f533c6daa6acd1f/description @@ -0,0 +1 @@ +ADC battery voltage reading diff --git a/3eb0b69b70c8853f9f533c6daa6acd1f/tags b/3eb0b69b70c8853f9f533c6daa6acd1f/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/3eb0b69b70c8853f9f533c6daa6acd1f/tags @@ -0,0 +1 @@ +feature diff --git a/49260fa4a2467b55f7b4d197825683a2/description b/49260fa4a2467b55f7b4d197825683a2/description new file mode 100644 index 0000000..f44cd6d --- /dev/null +++ b/49260fa4a2467b55f7b4d197825683a2/description @@ -0,0 +1,7 @@ +gpio inputs + +4x GPIO inputs + +* 1-2 of these wake from sleep interrupt + * 1 for button press + * 1 for coin detect diff --git a/49260fa4a2467b55f7b4d197825683a2/tags b/49260fa4a2467b55f7b4d197825683a2/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/49260fa4a2467b55f7b4d197825683a2/tags @@ -0,0 +1 @@ +feature diff --git a/4b5cce76398043576a0f9a6e29492127/assignee b/4b5cce76398043576a0f9a6e29492127/assignee new file mode 100644 index 0000000..284bb3b --- /dev/null +++ b/4b5cce76398043576a0f9a6e29492127/assignee @@ -0,0 +1 @@ +sigil-03 \ No newline at end of file diff --git a/4b5cce76398043576a0f9a6e29492127/description b/4b5cce76398043576a0f9a6e29492127/description new file mode 100644 index 0000000..dc791fd --- /dev/null +++ b/4b5cce76398043576a0f9a6e29492127/description @@ -0,0 +1,6 @@ +phase 0: bootstrap + +REQUIREMENTS: +* set up toolchain for CH32V development +* flash CH32V board +* blink an LED diff --git a/4b5cce76398043576a0f9a6e29492127/state b/4b5cce76398043576a0f9a6e29492127/state new file mode 100644 index 0000000..348ebd9 --- /dev/null +++ b/4b5cce76398043576a0f9a6e29492127/state @@ -0,0 +1 @@ +done \ No newline at end of file diff --git a/4b5cce76398043576a0f9a6e29492127/tags b/4b5cce76398043576a0f9a6e29492127/tags new file mode 100644 index 0000000..970be2b --- /dev/null +++ b/4b5cce76398043576a0f9a6e29492127/tags @@ -0,0 +1 @@ +phase-0 diff --git a/777077169fce2ffba439b0af82e0f574/assignee b/777077169fce2ffba439b0af82e0f574/assignee new file mode 100644 index 0000000..284bb3b --- /dev/null +++ b/777077169fce2ffba439b0af82e0f574/assignee @@ -0,0 +1 @@ +sigil-03 \ No newline at end of file diff --git a/777077169fce2ffba439b0af82e0f574/description b/777077169fce2ffba439b0af82e0f574/description new file mode 100644 index 0000000..b5f019d --- /dev/null +++ b/777077169fce2ffba439b0af82e0f574/description @@ -0,0 +1,41 @@ +insert-coin + +# HW +CHV32V003 or STM32F0 variant + +LM386/SC8002B amplifier +* HW PWM filtering for audio + + + +# FW FEATURES +## DEEP SLEEP +* wake from deep sleep on rising edge +* deep sleep when battery voltage is low +* deep sleep on long button press +* deep sleep after some long period of time + * does not need to be accurate + * time domain approx. several hours + +## BATTERY VOLTAGE MONITORING +* ADC battery voltage reading + + + +## GPIO INPUT +* 4x switch input + * one for button press + * one for coin detect + +## LED DRIVER +* 3 channels of LEDs + * need PWM-ish dimming but can be rough (bit-banged) + +## AUDIO +* store audio in MCU flash memory +* 10 audio files with total of 3-5 seconds of audio time +* output using PWM channels, will filter in HW + + +# REFERENCE +[spec](https://docs.google.com/document/d/1WP9aMegpzNuwF81Cxm263mibuAER9fZ7Ktj7NuHr9Rs) diff --git a/777077169fce2ffba439b0af82e0f574/state b/777077169fce2ffba439b0af82e0f574/state new file mode 100644 index 0000000..505c028 --- /dev/null +++ b/777077169fce2ffba439b0af82e0f574/state @@ -0,0 +1 @@ +inprogress \ No newline at end of file diff --git a/8b98f887e6f027890908edf066debce1/comments/ce3b8bdb2b09e0b7610e363bef7fc146/description b/8b98f887e6f027890908edf066debce1/comments/ce3b8bdb2b09e0b7610e363bef7fc146/description new file mode 100644 index 0000000..a0497af --- /dev/null +++ b/8b98f887e6f027890908edf066debce1/comments/ce3b8bdb2b09e0b7610e363bef7fc146/description @@ -0,0 +1,3 @@ +this is basically done, there's a PWM dac that can read DPCM data and output it via PWM. + +additionally, there's an encoder which can take a raw u8 encoded PCM file and turn it into a 4-bit DPCM file diff --git a/8b98f887e6f027890908edf066debce1/dependencies/2207e89d7201efbdceadd1c528d95341 b/8b98f887e6f027890908edf066debce1/dependencies/2207e89d7201efbdceadd1c528d95341 new file mode 100644 index 0000000..e69de29 diff --git a/8b98f887e6f027890908edf066debce1/dependencies/c6c969915b74005bc0b7f0c4b182243e b/8b98f887e6f027890908edf066debce1/dependencies/c6c969915b74005bc0b7f0c4b182243e new file mode 100644 index 0000000..e69de29 diff --git a/8b98f887e6f027890908edf066debce1/description b/8b98f887e6f027890908edf066debce1/description new file mode 100644 index 0000000..d2095a8 --- /dev/null +++ b/8b98f887e6f027890908edf066debce1/description @@ -0,0 +1,5 @@ +audio player + +requirements: +* DAC using PWM output +* read DPCM data and export to DAC diff --git a/8b98f887e6f027890908edf066debce1/tags b/8b98f887e6f027890908edf066debce1/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/8b98f887e6f027890908edf066debce1/tags @@ -0,0 +1 @@ +feature diff --git a/95dbcb73dd29dafe84621252289a4179/description b/95dbcb73dd29dafe84621252289a4179/description new file mode 100644 index 0000000..5a93718 --- /dev/null +++ b/95dbcb73dd29dafe84621252289a4179/description @@ -0,0 +1 @@ +wake from deep sleep on rising edge diff --git a/95dbcb73dd29dafe84621252289a4179/tags b/95dbcb73dd29dafe84621252289a4179/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/95dbcb73dd29dafe84621252289a4179/tags @@ -0,0 +1 @@ +feature diff --git a/README.md b/README.md new file mode 100644 index 0000000..2bd9d23 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +This branch is used by entomologist to track issues. \ No newline at end of file diff --git a/a05a70c9994ab6c8e3f9c69c7d536952/description b/a05a70c9994ab6c8e3f9c69c7d536952/description new file mode 100644 index 0000000..e8fd071 --- /dev/null +++ b/a05a70c9994ab6c8e3f9c69c7d536952/description @@ -0,0 +1 @@ +enter deep sleep after inactivity timeout diff --git a/a05a70c9994ab6c8e3f9c69c7d536952/tags b/a05a70c9994ab6c8e3f9c69c7d536952/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/a05a70c9994ab6c8e3f9c69c7d536952/tags @@ -0,0 +1 @@ +feature diff --git a/b0682a96fb4d2cb7c6d06141b5d36849/description b/b0682a96fb4d2cb7c6d06141b5d36849/description new file mode 100644 index 0000000..a41443b --- /dev/null +++ b/b0682a96fb4d2cb7c6d06141b5d36849/description @@ -0,0 +1,5 @@ +LED control + +3 channels of LEDs + +* need PWM-ish dimming, but can be bit-banged / slow diff --git a/b0682a96fb4d2cb7c6d06141b5d36849/tags b/b0682a96fb4d2cb7c6d06141b5d36849/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/b0682a96fb4d2cb7c6d06141b5d36849/tags @@ -0,0 +1 @@ +feature diff --git a/c6c969915b74005bc0b7f0c4b182243e/description b/c6c969915b74005bc0b7f0c4b182243e/description new file mode 100644 index 0000000..734f5ad --- /dev/null +++ b/c6c969915b74005bc0b7f0c4b182243e/description @@ -0,0 +1,4 @@ +pwm dac + +REQUIREMENTS: +* create an interface that accepts an input amplitude and outputs a PWM signal diff --git a/ch32v-insert-coin/.cargo/config.toml b/ch32v-insert-coin/.cargo/config.toml deleted file mode 100644 index 68ad23c..0000000 --- a/ch32v-insert-coin/.cargo/config.toml +++ /dev/null @@ -1,27 +0,0 @@ -[build] -target = "riscv32ec-unknown-none-elf.json" -#target = "riscv32i-unknown-none-elf" - -[target.'cfg(all(target_arch = "riscv32", target_os = "none"))'] -# runner = "riscv64-elf-gdb -q -x openocd.gdb" -# runner = "riscv-none-embed-gdb -q -x openocd.gdb" -# runner = "gdb -q -x openocd.gdb" -# runner = "wlink -v flash" - -runner = "wlink -v flash --enable-sdi-print --watch-serial" - -# Flash and debug chip with probe-rs. https://probe.rs/ -# runner = "probe-rs run --chip ch32v003" - -[unstable] -build-std = ["core"] -# build-std = ["core", "compiler_builtins"] -# build-std-features = ["compiler-builtins-mem"] - -[target."riscv32ec-unknown-none-elf"] -rustflags = ["-C", "link-arg=-Tlink.x"] - -#[target."riscv32i-unknown-none-elf"] -#rustflags = [ -## "-C", "link-arg=-Tlink.x", -#] diff --git a/ch32v-insert-coin/.gitignore b/ch32v-insert-coin/.gitignore deleted file mode 100644 index eb5a316..0000000 --- a/ch32v-insert-coin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target diff --git a/ch32v-insert-coin/Cargo.lock b/ch32v-insert-coin/Cargo.lock deleted file mode 100644 index 7fd7006..0000000 --- a/ch32v-insert-coin/Cargo.lock +++ /dev/null @@ -1,633 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "adpcm-pwm-dac" -version = "0.1.0" - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cfg-if" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" - -[[package]] -name = "ch32-hal" -version = "0.1.0" -dependencies = [ - "ch32-metapac", - "critical-section", - "embassy-futures", - "embassy-hal-internal", - "embassy-sync", - "embassy-time", - "embassy-time-driver", - "embassy-time-queue-utils", - "embassy-usb-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-hal-nb", - "futures", - "nb 1.1.0", - "proc-macro2", - "qingke 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "qingke-rt", - "quote", - "rand_core", - "sdio-host", -] - -[[package]] -name = "ch32-metapac" -version = "0.1.0" -source = "git+https://github.com/ch32-rs/ch32-metapac?rev=b1cbc7a98e43af3fd3170821654784e2c01cb26b#b1cbc7a98e43af3fd3170821654784e2c01cb26b" -dependencies = [ - "riscv 0.11.1", - "vcell", -] - -[[package]] -name = "ch32v-insert-coin" -version = "0.1.0" -dependencies = [ - "adpcm-pwm-dac", - "ch32-hal", - "critical-section", - "embassy-executor", - "embedded-hal 1.0.0", - "panic-halt", - "qingke 0.5.0", - "qingke-rt", - "wavetable-synth", -] - -[[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.104", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.104", -] - -[[package]] -name = "document-features" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" -dependencies = [ - "litrs", -] - -[[package]] -name = "embassy-executor" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90327bcc66333a507f89ecc4e2d911b265c45f5c9bc241f98eee076752d35ac6" -dependencies = [ - "critical-section", - "document-features", - "embassy-executor-macros", -] - -[[package]] -name = "embassy-executor-macros" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3577b1e9446f61381179a330fc5324b01d511624c55f25e3c66c9e3c626dbecf" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.104", -] - -[[package]] -name = "embassy-futures" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f878075b9794c1e4ac788c95b728f26aa6366d32eeb10c7051389f898f7d067" - -[[package]] -name = "embassy-hal-internal" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ef3bac31ec146321248a169e9c7b5799f1e0b3829c7a9b324cb4600a7438f59" -dependencies = [ - "num-traits", -] - -[[package]] -name = "embassy-sync" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2c8cdff05a7a51ba0087489ea44b0b1d97a296ca6b1d6d1a33ea7423d34049" -dependencies = [ - "cfg-if", - "critical-section", - "embedded-io-async", - "futures-sink", - "futures-util", - "heapless", -] - -[[package]] -name = "embassy-time" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f820157f198ada183ad62e0a66f554c610cdcd1a9f27d4b316358103ced7a1f8" -dependencies = [ - "cfg-if", - "critical-section", - "document-features", - "embassy-time-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "futures-util", -] - -[[package]] -name = "embassy-time-driver" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d45f5d833b6d98bd2aab0c2de70b18bfaa10faf661a1578fd8e5dfb15eb7eba" -dependencies = [ - "document-features", -] - -[[package]] -name = "embassy-time-queue-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc55c748d16908a65b166d09ce976575fb8852cf60ccd06174092b41064d8f83" -dependencies = [ - "embassy-executor", - "heapless", -] - -[[package]] -name = "embassy-usb-driver" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340c5ce591ef58c6449e43f51d2c53efe1bf0bb6a40cbf80afa0d259c7d52c76" -dependencies = [ - "embedded-io-async", -] - -[[package]] -name = "embedded-hal" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" -dependencies = [ - "nb 0.1.3", - "void", -] - -[[package]] -name = "embedded-hal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" - -[[package]] -name = "embedded-hal-async" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" -dependencies = [ - "embedded-hal 1.0.0", -] - -[[package]] -name = "embedded-hal-nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" -dependencies = [ - "embedded-hal 1.0.0", - "nb 1.1.0", -] - -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" - -[[package]] -name = "embedded-io-async" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" -dependencies = [ - "embedded-io", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-io" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" - -[[package]] -name = "futures-macro" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "futures-task" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" - -[[package]] -name = "futures-util" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" -dependencies = [ - "futures-core", - "futures-macro", - "futures-sink", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "litrs" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed" - -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.1.0", -] - -[[package]] -name = "nb" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "panic-halt" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a513e167849a384b7f9b746e517604398518590a9142f4846a32e3c2a4de7b11" - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "qingke" -version = "0.5.0" -dependencies = [ - "bit_field", - "riscv 0.12.1", -] - -[[package]] -name = "qingke" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0230c5310b68c08a3cf8b59fbeec3e9d8e352bc6500f62cbaf9c677f42c8dfc" -dependencies = [ - "bit_field", - "critical-section", - "riscv 0.12.1", -] - -[[package]] -name = "qingke-rt" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b955c60adac70c6d40205b1dbe9f57e1151d06aa842069cdbaef7bc07ad283fd" -dependencies = [ - "qingke 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "qingke-rt-macros", -] - -[[package]] -name = "qingke-rt-macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2ed46d18953ea5765ab26a07d1f092dffac2da1b4830c4397e02c3cec08501" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - -[[package]] -name = "riscv" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5c1b8bf41ea746266cdee443d1d1e9125c86ce1447e1a2615abd34330d33a9" -dependencies = [ - "critical-section", - "embedded-hal 1.0.0", -] - -[[package]] -name = "riscv" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea8ff73d3720bdd0a97925f0bf79ad2744b6da8ff36be3840c48ac81191d7a7" -dependencies = [ - "critical-section", - "embedded-hal 1.0.0", - "paste", - "riscv-macros", - "riscv-pac", -] - -[[package]] -name = "riscv-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f265be5d634272320a7de94cea15c22a3bfdd4eb42eb43edc528415f066a1f25" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.104", -] - -[[package]] -name = "riscv-pac" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8188909339ccc0c68cfb5a04648313f09621e8b87dc03095454f1a11f6c5d436" - -[[package]] -name = "sdio-host" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93c025f9cfe4c388c328ece47d11a54a823da3b5ad0370b22d95ad47137f85a" - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "vcell" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "wavetable-synth" -version = "0.1.0" diff --git a/ch32v-insert-coin/Cargo.toml b/ch32v-insert-coin/Cargo.toml deleted file mode 100644 index e09776c..0000000 --- a/ch32v-insert-coin/Cargo.toml +++ /dev/null @@ -1,44 +0,0 @@ -[package] -name = "ch32v-insert-coin" -version = "0.1.0" -edition = "2024" - -[features] -enable_print = [] - -[dependencies] -ch32-hal = { path = "ext/ch32-hal/", features = [ - "ch32v003f4u6", - "memory-x", - "embassy", - "time-driver-tim2", - "rt", -] } - -embassy-executor = { version = "0.7.0", features = [ - "arch-spin", - "executor-thread", - "task-arena-size-128", # or better use nightly, but fails on recent Rust versions -] } - -panic-halt = "1.0" - -embedded-hal = "1.0.0" - -qingke-rt = { version = "*", features = ["highcode"] } - -qingke = {path = "ext/qingke"} - -adpcm-pwm-dac = { path = "ext/adpcm-pwm-dac/" } - -wavetable-synth = { path = "ext/wavetable-synth" } - -critical-section = { version = "1.2.0" } - -[profile.release] -strip = false # symbols are not flashed to the microcontroller, so don't strip them. -lto = true -opt-level = "s" # Optimize for size. - -[profile.dev] -overflow-checks = false diff --git a/ch32v-insert-coin/audio/button_1.raw b/ch32v-insert-coin/audio/button_1.raw deleted file mode 100644 index ade05bd..0000000 Binary files a/ch32v-insert-coin/audio/button_1.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/button_2.raw b/ch32v-insert-coin/audio/button_2.raw deleted file mode 100644 index 16b9b36..0000000 Binary files a/ch32v-insert-coin/audio/button_2.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/button_3.raw b/ch32v-insert-coin/audio/button_3.raw deleted file mode 100644 index 0477e75..0000000 Binary files a/ch32v-insert-coin/audio/button_3.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/coin.raw b/ch32v-insert-coin/audio/coin.raw deleted file mode 100644 index 2a0af56..0000000 Binary files a/ch32v-insert-coin/audio/coin.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/coin2.raw b/ch32v-insert-coin/audio/coin2.raw deleted file mode 100644 index 1caabb9..0000000 Binary files a/ch32v-insert-coin/audio/coin2.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/coin3.raw b/ch32v-insert-coin/audio/coin3.raw deleted file mode 100644 index 8c590d9..0000000 Binary files a/ch32v-insert-coin/audio/coin3.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/coin4.raw b/ch32v-insert-coin/audio/coin4.raw deleted file mode 100644 index f350cd0..0000000 Binary files a/ch32v-insert-coin/audio/coin4.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/coin5.raw b/ch32v-insert-coin/audio/coin5.raw deleted file mode 100644 index 922bb2c..0000000 Binary files a/ch32v-insert-coin/audio/coin5.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/coin8ksps.raw b/ch32v-insert-coin/audio/coin8ksps.raw deleted file mode 100644 index 72caab0..0000000 Binary files a/ch32v-insert-coin/audio/coin8ksps.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/coinMixTest1_dpcm_u4.raw b/ch32v-insert-coin/audio/coinMixTest1_dpcm_u4.raw deleted file mode 100644 index 36cc103..0000000 Binary files a/ch32v-insert-coin/audio/coinMixTest1_dpcm_u4.raw and /dev/null differ diff --git a/ch32v-insert-coin/audio/sequences b/ch32v-insert-coin/audio/sequences deleted file mode 100644 index edef1a1..0000000 --- a/ch32v-insert-coin/audio/sequences +++ /dev/null @@ -1,18 +0,0 @@ -"wahwahwahwah" sound - let play a few times -note timing: 6hz -data: let freqs = [100, 200, 300, 400, 500, 600, 700, 800, 900]; - -"falling" sound -note timing: 6hz -[ -1000, -990, 980, 970, 960, 950, 940, 930, 920, 910, 900, -890, 880, 870, 860, 850, 840, 830, 820, 810, 800, -790, 780, 770, 760, 750, 740, 730, 720, 710, 700, -690, 680, 670, 660, 650, 640, 630, 620, 610, 600, -590, 580, 570, 560, 550, 540, 530, 520, 510, 500, -490, 480, 470, 460, 450, 440, 430, 420, 410, 400, -390, 380, 370, 360, 350, 340, 330, 320, 310, 300, -290, 280, 270, 260, 250, 240, 230, 220, 210, 200, -190, 180, 170, 160, 150, 140, 130, 120, 110, 100, -] diff --git a/ch32v-insert-coin/audio/sweep_dpcm_u4.raw b/ch32v-insert-coin/audio/sweep_dpcm_u4.raw deleted file mode 100644 index 1adc494..0000000 Binary files a/ch32v-insert-coin/audio/sweep_dpcm_u4.raw and /dev/null differ diff --git a/ch32v-insert-coin/build-run.sh b/ch32v-insert-coin/build-run.sh deleted file mode 100755 index 8461b3a..0000000 --- a/ch32v-insert-coin/build-run.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -cargo +nightly run --release \ No newline at end of file diff --git a/ch32v-insert-coin/ext/adpcm-pwm-dac b/ch32v-insert-coin/ext/adpcm-pwm-dac deleted file mode 160000 index 99ce71e..0000000 --- a/ch32v-insert-coin/ext/adpcm-pwm-dac +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 99ce71e8d03e382b51732db7d0771349c51c7f48 diff --git a/ch32v-insert-coin/ext/ch32-hal b/ch32v-insert-coin/ext/ch32-hal deleted file mode 160000 index 4f11d68..0000000 --- a/ch32v-insert-coin/ext/ch32-hal +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4f11d68e62dcb0e7098eecf357168724a8322d80 diff --git a/ch32v-insert-coin/ext/patches/optional-exti.patch b/ch32v-insert-coin/ext/patches/optional-exti.patch deleted file mode 100644 index 2ea58f3..0000000 --- a/ch32v-insert-coin/ext/patches/optional-exti.patch +++ /dev/null @@ -1,652 +0,0 @@ -From 7b086336e3820714c564aac13dc44fbaf7f5bc17 Mon Sep 17 00:00:00 2001 -From: mindshub -Date: Sat, 9 Aug 2025 10:16:33 +0200 -Subject: [PATCH] optional exti - ---- - Cargo.toml | 3 +- - src/exti.rs | 548 ++++++++++++++++++++++++++-------------------------- - src/lib.rs | 1 + - 3 files changed, 281 insertions(+), 271 deletions(-) - -diff --git a/Cargo.toml b/Cargo.toml -index ec451bf..55fa288 100644 ---- a/Cargo.toml -+++ b/Cargo.toml -@@ -56,7 +56,7 @@ proc-macro2 = "1.0" - quote = "1.0" - - [features] --default = ["embassy", "rt"] -+default = ["embassy", "rt", "exti"] - rt = ["dep:qingke-rt"] - highcode = ["qingke-rt/highcode"] - embassy = [ -@@ -66,6 +66,7 @@ embassy = [ - ] - defmt = ["dep:defmt"] - memory-x = ["ch32-metapac/memory-x"] -+exti = [] - - - # Features starting with `_` are for internal use only. They're not intended -diff --git a/src/exti.rs b/src/exti.rs -index a2458d1..3d613ea 100644 ---- a/src/exti.rs -+++ b/src/exti.rs -@@ -1,37 +1,11 @@ --use core::future::Future; --use core::marker::PhantomData; --use core::pin::Pin; --use core::task::{Context, Poll}; -- - use embassy_sync::waitqueue::AtomicWaker; --use qingke_rt::interrupt; - --use crate::gpio::{AnyPin, Input, Level, Pin as GpioPin, Pull}; --use crate::{impl_peripheral, into_ref, peripherals, Peripheral}; -+use crate::{impl_peripheral, peripherals}; - - const EXTI_COUNT: usize = 24; - const NEW_AW: AtomicWaker = AtomicWaker::new(); - static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT]; - --pub unsafe fn on_irq() { -- let exti = &crate::pac::EXTI; -- -- let bits = exti.intfr().read(); -- -- // We don't handle or change any EXTI lines above 24. -- let bits = bits.0 & 0x00FFFFFF; -- -- // Clear pending - Clears the EXTI's line pending bits. -- exti.intfr().write(|w| w.0 = bits); -- -- exti.intenr().modify(|w| w.0 = w.0 & !bits); -- -- // Wake the tasks -- for pin in BitIter(bits) { -- EXTI_WAKERS[pin as usize].wake(); -- } --} -- - struct BitIter(u32); - - impl Iterator for BitIter { -@@ -48,150 +22,6 @@ impl Iterator for BitIter { - } - } - --/// EXTI input driver --pub struct ExtiInput<'d> { -- pin: Input<'d>, --} -- --impl<'d> Unpin for ExtiInput<'d> {} -- --impl<'d> ExtiInput<'d> { -- pub fn new( -- pin: impl Peripheral

+ 'd, -- ch: impl Peripheral

+ 'd, -- pull: Pull, -- ) -> Self { -- into_ref!(pin, ch); -- // Needed if using AnyPin+AnyChannel. -- assert_eq!(pin.pin(), ch.number()); -- -- Self { -- pin: Input::new(pin, pull), -- } -- } -- -- pub fn is_high(&self) -> bool { -- self.pin.is_high() -- } -- -- pub fn is_low(&self) -> bool { -- self.pin.is_low() -- } -- -- pub fn get_level(&self) -> Level { -- self.pin.get_level() -- } -- -- pub async fn wait_for_high<'a>(&'a mut self) { -- let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false); -- if self.is_high() { -- return; -- } -- fut.await -- } -- -- pub async fn wait_for_low<'a>(&'a mut self) { -- let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true); -- if self.is_low() { -- return; -- } -- fut.await -- } -- -- pub async fn wait_for_rising_edge<'a>(&'a mut self) { -- ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await -- } -- -- pub async fn wait_for_falling_edge<'a>(&'a mut self) { -- ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await -- } -- -- pub async fn wait_for_any_edge<'a>(&'a mut self) { -- ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await -- } --} -- --#[must_use = "futures do nothing unless you `.await` or poll them"] --struct ExtiInputFuture<'a> { -- pin: u8, -- phantom: PhantomData<&'a mut AnyPin>, --} -- --// EXTI0-EXTI23 Px0-Px23(x=A/B/C) --impl<'a> ExtiInputFuture<'a> { -- fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { -- critical_section::with(|_| { -- let exti = &crate::pac::EXTI; -- let afio = &crate::pac::AFIO; -- -- let port = port as u8; -- let pin = pin as usize; -- -- #[cfg(afio_v0)] -- { -- // AFIO_EXTICR -- // stride: 2, len: 15, 8 lines -- afio.exticr().modify(|w| w.set_exti(pin, port)); -- } -- // V1, V2, V3, L1 -- #[cfg(any(afio_v3, afio_l1))] -- { -- // AFIO_EXTICRx -- // stride: 4, len: 4, 16 lines -- afio.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); -- } -- #[cfg(afio_x0)] -- { -- // stride: 2, len: 15, 24 lines -- afio.exticr(pin / 16).modify(|w| w.set_exti(pin % 16, port)); -- } -- #[cfg(afio_ch641)] -- { -- // single register -- afio.exticr().modify(|w| w.set_exti(pin, port != 0)); -- } -- -- // See-also: 7.4.3 -- exti.intenr().modify(|w| w.set_mr(pin, true)); // enable interrupt -- -- exti.rtenr().modify(|w| w.set_tr(pin, rising)); -- exti.ftenr().modify(|w| w.set_tr(pin, falling)); -- }); -- -- Self { -- pin, -- phantom: PhantomData, -- } -- } --} -- --impl<'a> Drop for ExtiInputFuture<'a> { -- fn drop(&mut self) { -- critical_section::with(|_| { -- let exti = &crate::pac::EXTI; -- let pin = self.pin; -- exti.intenr().modify(|w| w.0 = w.0 & !(1 << pin)); -- }); -- } --} -- --impl<'a> Future for ExtiInputFuture<'a> { -- type Output = (); -- -- fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { -- let exti = &crate::pac::EXTI; -- -- EXTI_WAKERS[self.pin as usize].register(cx.waker()); -- -- if exti.intenr().read().mr(self.pin as _) == false { -- // intenr cleared by on_irq, then we can assume it is triggered -- Poll::Ready(()) -- } else { -- Poll::Pending -- } -- } --} -- - trait SealedChannel {} - - #[allow(private_bounds)] -@@ -207,6 +37,7 @@ pub trait Channel: SealedChannel + Sized { - pub struct AnyChannel { - number: u8, - } -+ - impl_peripheral!(AnyChannel); - impl SealedChannel for AnyChannel {} - impl Channel for AnyChannel { -@@ -267,128 +98,305 @@ mod _exti_24lines { - impl_exti!(EXTI23, 23); - } - --/* --EXTI0 --EXTI1 --EXTI2 --EXTI3 --EXTI4 --EXTI9_5 --EXTI15_10 --EXTI7_0 --EXTI15_8 --EXTI25_16 --*/ -- --/// safety: must be called only once --#[cfg(gpio_x0)] --mod irq_impl { -- use super::*; -+#[cfg(feature = "exti")] -+pub use exti_inner::*; -+ -+#[cfg(feature = "exti")] -+mod exti_inner { -+ use super::{BitIter, Channel, EXTI_WAKERS}; -+ use crate::gpio::{AnyPin, Input, Level, Pin as GpioPin, Pull}; -+ use crate::{into_ref, Peripheral}; -+ use core::future::Future; -+ use core::marker::PhantomData; -+ use core::pin::Pin; -+ use core::task::{Context, Poll}; -+ use qingke_rt::interrupt; -+ -+ /// EXTI input driver -+ pub struct ExtiInput<'d> { -+ pin: Input<'d>, -+ } -+ -+ impl<'d> Unpin for ExtiInput<'d> {} -+ -+ impl<'d> ExtiInput<'d> { -+ pub fn new( -+ pin: impl Peripheral

+ 'd, -+ ch: impl Peripheral

+ 'd, -+ pull: Pull, -+ ) -> Self { -+ into_ref!(pin, ch); -+ // Needed if using AnyPin+AnyChannel. -+ assert_eq!(pin.pin(), ch.number()); -+ -+ Self { -+ pin: Input::new(pin, pull), -+ } -+ } - -- #[interrupt] -- unsafe fn EXTI7_0() { -- on_irq(); -- } -- #[interrupt] -- unsafe fn EXTI15_8() { -- on_irq(); -- } -- #[interrupt] -- unsafe fn EXTI25_16() { -- on_irq(); -- } -+ pub fn is_high(&self) -> bool { -+ self.pin.is_high() -+ } - -- pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -- use crate::pac::Interrupt; -+ pub fn is_low(&self) -> bool { -+ self.pin.is_low() -+ } - -- qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI15_8 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI25_16 as u8); -- } --} -+ pub fn get_level(&self) -> Level { -+ self.pin.get_level() -+ } - --#[cfg(all(gpio_v3, not(ch641)))] --mod irq_impl { -- use super::*; -+ pub async fn wait_for_high<'a>(&'a mut self) { -+ let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false); -+ if self.is_high() { -+ return; -+ } -+ fut.await -+ } - -- #[interrupt] -- unsafe fn EXTI0() { -- on_irq(); -- } -- #[interrupt] -- unsafe fn EXTI1() { -- on_irq(); -- } -- #[interrupt] -- unsafe fn EXTI2() { -- on_irq(); -- } -- #[interrupt] -- unsafe fn EXTI3() { -- on_irq(); -+ pub async fn wait_for_low<'a>(&'a mut self) { -+ let fut = ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true); -+ if self.is_low() { -+ return; -+ } -+ fut.await -+ } -+ -+ pub async fn wait_for_rising_edge<'a>(&'a mut self) { -+ ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, false).await -+ } -+ -+ pub async fn wait_for_falling_edge<'a>(&'a mut self) { -+ ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), false, true).await -+ } -+ -+ pub async fn wait_for_any_edge<'a>(&'a mut self) { -+ ExtiInputFuture::new(self.pin.pin.pin.pin(), self.pin.pin.pin.port(), true, true).await -+ } - } -- #[interrupt] -- unsafe fn EXTI4() { -- on_irq(); -+ -+ pub unsafe fn on_irq() { -+ let exti = &crate::pac::EXTI; -+ -+ let bits = exti.intfr().read(); -+ -+ // We don't handle or change any EXTI lines above 24. -+ let bits = bits.0 & 0x00FFFFFF; -+ -+ // Clear pending - Clears the EXTI's line pending bits. -+ exti.intfr().write(|w| w.0 = bits); -+ -+ exti.intenr().modify(|w| w.0 = w.0 & !bits); -+ -+ // Wake the tasks -+ for pin in BitIter(bits) { -+ EXTI_WAKERS[pin as usize].wake(); -+ } - } -- #[interrupt] -- unsafe fn EXTI9_5() { -- on_irq(); -+ -+ #[must_use = "futures do nothing unless you `.await` or poll them"] -+ struct ExtiInputFuture<'a> { -+ pin: u8, -+ phantom: PhantomData<&'a mut AnyPin>, -+ } -+ -+ // EXTI0-EXTI23 Px0-Px23(x=A/B/C) -+ impl<'a> ExtiInputFuture<'a> { -+ fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { -+ critical_section::with(|_| { -+ let exti = &crate::pac::EXTI; -+ let afio = &crate::pac::AFIO; -+ -+ let port = port as u8; -+ let pin = pin as usize; -+ -+ #[cfg(afio_v0)] -+ { -+ // AFIO_EXTICR -+ // stride: 2, len: 15, 8 lines -+ afio.exticr().modify(|w| w.set_exti(pin, port)); -+ } -+ // V1, V2, V3, L1 -+ #[cfg(any(afio_v3, afio_l1))] -+ { -+ // AFIO_EXTICRx -+ // stride: 4, len: 4, 16 lines -+ afio.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); -+ } -+ #[cfg(afio_x0)] -+ { -+ // stride: 2, len: 15, 24 lines -+ afio.exticr(pin / 16).modify(|w| w.set_exti(pin % 16, port)); -+ } -+ #[cfg(afio_ch641)] -+ { -+ // single register -+ afio.exticr().modify(|w| w.set_exti(pin, port != 0)); -+ } -+ -+ // See-also: 7.4.3 -+ exti.intenr().modify(|w| w.set_mr(pin, true)); // enable interrupt -+ -+ exti.rtenr().modify(|w| w.set_tr(pin, rising)); -+ exti.ftenr().modify(|w| w.set_tr(pin, falling)); -+ }); -+ -+ Self { -+ pin, -+ phantom: PhantomData, -+ } -+ } - } -- #[interrupt] -- unsafe fn EXTI15_10() { -- on_irq(); -+ -+ impl<'a> Drop for ExtiInputFuture<'a> { -+ fn drop(&mut self) { -+ critical_section::with(|_| { -+ let exti = &crate::pac::EXTI; -+ let pin = self.pin; -+ exti.intenr().modify(|w| w.0 = w.0 & !(1 << pin)); -+ }); -+ } - } - -- pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -- use crate::pac::Interrupt; -+ impl<'a> Future for ExtiInputFuture<'a> { -+ type Output = (); - -- qingke::pfic::enable_interrupt(Interrupt::EXTI0 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI1 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI2 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI3 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI4 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI9_5 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI15_10 as u8); -- } --} -+ fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { -+ let exti = &crate::pac::EXTI; - --#[cfg(gpio_v0)] --mod irq_impl { -- use super::*; -+ EXTI_WAKERS[self.pin as usize].register(cx.waker()); - -- #[interrupt] -- unsafe fn EXTI7_0() { -- on_irq(); -+ if exti.intenr().read().mr(self.pin as _) == false { -+ // intenr cleared by on_irq, then we can assume it is triggered -+ Poll::Ready(()) -+ } else { -+ Poll::Pending -+ } -+ } - } - -- pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -- use crate::pac::Interrupt; -+ /* -+ EXTI0 -+ EXTI1 -+ EXTI2 -+ EXTI3 -+ EXTI4 -+ EXTI9_5 -+ EXTI15_10 -+ EXTI7_0 -+ EXTI15_8 -+ EXTI25_16 -+ */ -+ -+ /// safety: must be called only once -+ #[cfg(gpio_x0)] -+ mod irq_impl { -+ use super::*; -+ -+ #[interrupt] -+ unsafe fn EXTI7_0() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI15_8() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI25_16() { -+ on_irq(); -+ } -+ -+ pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -+ use crate::pac::Interrupt; - -- qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI15_8 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI25_16 as u8); -+ } - } --} - --#[cfg(all(gpio_v3, ch641))] --mod irq_impl { -- use super::*; -+ #[cfg(all(gpio_v3, not(ch641)))] -+ mod irq_impl { -+ use super::*; -+ -+ #[interrupt] -+ unsafe fn EXTI0() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI1() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI2() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI3() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI4() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI9_5() { -+ on_irq(); -+ } -+ #[interrupt] -+ unsafe fn EXTI15_10() { -+ on_irq(); -+ } - -- #[interrupt] -- unsafe fn EXTI7_0() { -- on_irq(); -+ pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -+ use crate::pac::Interrupt; -+ -+ qingke::pfic::enable_interrupt(Interrupt::EXTI0 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI1 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI2 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI3 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI4 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI9_5 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI15_10 as u8); -+ } - } - -- #[interrupt] -- unsafe fn EXTI15_8() { -- on_irq(); -+ #[cfg(gpio_v0)] -+ mod irq_impl { -+ use super::*; -+ -+ #[interrupt] -+ unsafe fn EXTI7_0() { -+ on_irq(); -+ } -+ -+ pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -+ use crate::pac::Interrupt; -+ -+ qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); -+ } - } - -- pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -- use crate::pac::Interrupt; -+ #[cfg(all(gpio_v3, ch641))] -+ mod irq_impl { -+ use super::*; -+ -+ #[interrupt] -+ unsafe fn EXTI7_0() { -+ on_irq(); -+ } -+ -+ #[interrupt] -+ unsafe fn EXTI15_8() { -+ on_irq(); -+ } -+ -+ pub(crate) unsafe fn init(_cs: critical_section::CriticalSection) { -+ use crate::pac::Interrupt; - -- qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); -- qingke::pfic::enable_interrupt(Interrupt::EXTI15_8 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); -+ qingke::pfic::enable_interrupt(Interrupt::EXTI15_8 as u8); -+ } - } -+ pub(crate) use irq_impl::*; - } -- --pub(crate) use irq_impl::*; -diff --git a/src/lib.rs b/src/lib.rs -index 997da34..b451a55 100644 ---- a/src/lib.rs -+++ b/src/lib.rs -@@ -140,6 +140,7 @@ pub fn init(config: Config) -> Peripherals { - ::critical_section::with(|cs| unsafe { - gpio::init(cs); - dma::init(cs, config.dma_interrupt_priority); -+ #[cfg(feature = "exti")] - exti::init(cs); - }); - - diff --git a/ch32v-insert-coin/ext/qingke b/ch32v-insert-coin/ext/qingke deleted file mode 160000 index 2443891..0000000 --- a/ch32v-insert-coin/ext/qingke +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2443891811d7351d62e78085bcf60fa78c063c08 diff --git a/ch32v-insert-coin/ext/wavetable-synth b/ch32v-insert-coin/ext/wavetable-synth deleted file mode 160000 index 30033e1..0000000 --- a/ch32v-insert-coin/ext/wavetable-synth +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 30033e1438c25aed4ea506cdbd69cc4ceffa0b4e diff --git a/ch32v-insert-coin/init.sh b/ch32v-insert-coin/init.sh deleted file mode 100755 index bf063fc..0000000 --- a/ch32v-insert-coin/init.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -DIR=${PWD} -mkdir ${PWD}/tmp -cd tmp -git clone ssh://git@git.glyphs.tech:222/taproot-tech/docker-devtools.git -cd docker-devtools/ch32 -ls -./build.sh -cd $DIR -rm -rf tmp diff --git a/ch32v-insert-coin/launch.sh b/ch32v-insert-coin/launch.sh deleted file mode 100755 index ae7aa33..0000000 --- a/ch32v-insert-coin/launch.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -podman run --privileged -it --rm -v "$PWD":/usr/src/app -w /usr/src/app ch32-rust:latest /bin/bash diff --git a/ch32v-insert-coin/riscv32ec-unknown-none-elf.json b/ch32v-insert-coin/riscv32ec-unknown-none-elf.json deleted file mode 100644 index b2022a5..0000000 --- a/ch32v-insert-coin/riscv32ec-unknown-none-elf.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "arch": "riscv32", - "atomic-cas": false, - "cpu": "generic-rv32", - "crt-objects-fallback": "false", - "data-layout": "e-m:e-p:32:32-i64:64-n32-S32", - "eh-frame-header": false, - "emit-debug-gdb-scripts": false, - "features": "+e,+c,+forced-atomics", - "linker": "rust-lld", - "linker-flavor": "gnu-lld", - "llvm-target": "riscv32", - "llvm-abiname": "ilp32e", - "max-atomic-width": 32, - "panic-strategy": "abort", - "relocation-model": "static", - "target-pointer-width": 32 -} diff --git a/ch32v-insert-coin/src/app.rs b/ch32v-insert-coin/src/app.rs deleted file mode 100644 index a8fdbb8..0000000 --- a/ch32v-insert-coin/src/app.rs +++ /dev/null @@ -1,705 +0,0 @@ -#[derive(Default, Clone, Copy)] -pub enum State { - // system is asleep, waiting for wake from coin insertion - DeepSleep, - // system is in low-power mode, dimmed lights, waiting for interaction - Idle, - // system is active. on entry: play coin sound. on button press: play different sound - #[default] - Active, -} - -pub mod settings { - - #[derive(Debug, Default, Clone, Copy)] - pub enum Level { - Off, - Low, - #[default] - Medium, - High, - Maximum, - } - - impl Level { - pub fn next(&mut self) { - *self = match self { - Self::Off => Self::Low, - Self::Low => Self::Medium, - Self::Medium => Self::High, - Self::High => Self::Maximum, - Self::Maximum => Self::Off, - }; - } - } - - // volume control - impl Level { - pub fn as_volume_divisor(&self) -> u8 { - match self { - Self::Off => u8::MAX, - Self::Low => 4, - Self::Medium => 3, - Self::High => 2, - Self::Maximum => 1, - } - } - - pub fn as_brightness_divisor(&self) -> u8 { - match self { - Self::Off => u8::MAX, - Self::Low => 8, - Self::Medium => 6, - Self::High => 4, - Self::Maximum => 2, - } - } - } - - #[derive(Clone, Copy)] - pub struct Settings { - pub brightness: Level, - pub volume: Level, - pub button_sound_index: usize, - } - - impl Default for Settings { - fn default() -> Self { - Self { - brightness: Level::Medium, - volume: Level::Medium, - button_sound_index: 0, - } - } - } -} - -pub mod sequencer { - pub struct BasicSequence<'a> { - sequence: &'a [u8], - index: usize, - } - impl<'a> BasicSequence<'a> { - pub fn new(sequence: &'a [u8]) -> Self { - Self { sequence, index: 0 } - } - pub fn next(&mut self) { - self.index += 1; - if self.index > self.sequence.len() - 1 { - self.index = 0; - } - } - pub fn get_value(&self) -> u8 { - self.sequence[self.index] - } - } - - pub struct SequenceEntry { - pub frequency_hz: u16, - pub duration_ms: u16, - } - - pub struct DynamicSequence<'a> { - sequence: &'a [SequenceEntry], - index: usize, - - // timer stuff - system_tick_rate_hz: usize, - ticks_remaining: usize, - - // playback stuff - num_loops: usize, - loop_count: usize, - - // misc - enabled: bool, - } - - impl<'a> DynamicSequence<'a> { - pub fn new(sequence: &'a [SequenceEntry], system_tick_rate_hz: usize) -> Self { - Self { - sequence, - index: 0, - system_tick_rate_hz, - ticks_remaining: 0, - num_loops: 1, - loop_count: 0, - enabled: false, - } - } - - pub fn play_sequence(&mut self, sequence: &'a [SequenceEntry], num_loops: usize) { - self.sequence = sequence; - self.num_loops = num_loops; - self.loop_count = 0; - self.enabled = true; - self.index = 0; - self.ticks_remaining = 0; - } - - pub fn enable(&mut self) { - self.enabled = true; - } - - pub fn disable(&mut self) { - self.enabled = false; - } - - pub fn tick(&mut self) { - if self.enabled { - self.ticks_remaining = self.ticks_remaining.saturating_sub(1); - } - } - - pub fn need_service(&self) -> bool { - self.enabled && self.ticks_remaining == 0 - } - - pub fn service(&mut self) -> Option { - let entry = &self.sequence[self.index]; - self.ticks_remaining = self.system_tick_rate_hz * (entry.duration_ms as usize) / 1000; - self.index = self.index.saturating_add(1); - - let out = if self.loop_count > self.num_loops { - None - } else { - Some(entry.frequency_hz) - }; - - if self.index > self.sequence.len() - 1 { - self.index = 0; - self.loop_count = self.loop_count.saturating_add(1); - } - - out - } - } -} - -use crate::insert_coin::{ - DacService, LedService, Service, SimplePwmCore, TickService, TickServiceData, TickTimerService, -}; -use crate::synthesizer::SynthesizerService; - -pub use settings::Settings; - -// #[cfg(feature = "enable_print")] -use ch32_hal::println; - -pub struct TimerConfig { - pub sp_timer_ms: usize, - pub lp_timer_ms: usize, - pub batt_adc_timer_ms: usize, - pub usb_adc_timer_ms: usize, - pub led0_timer_ms: usize, - pub led1_timer_ms: usize, - pub shutdown_timer_s: usize, - // pub led2_timer_ms: usize, -} - -pub struct Timers { - sp_timer: TickTimerService, - lp_timer: TickTimerService, - batt_adc_timer: TickTimerService, - usb_adc_timer: TickTimerService, - led0_timer: TickTimerService, - led1_timer: TickTimerService, - shutdown_timer: TickTimerService, - pps_timer: TickTimerService, - // led2_timer: TickTimerService, -} - -impl Timers { - pub fn new(config: TimerConfig, system_tick_rate_hz: usize) -> Self { - Self { - sp_timer: TickTimerService::new( - TickServiceData::new(config.sp_timer_ms * system_tick_rate_hz / 1000), - false, - ), - lp_timer: TickTimerService::new( - TickServiceData::new(config.lp_timer_ms * system_tick_rate_hz / 1000), - false, - ), - batt_adc_timer: TickTimerService::new( - TickServiceData::new(config.batt_adc_timer_ms * system_tick_rate_hz / 1000), - false, - ), - usb_adc_timer: TickTimerService::new( - TickServiceData::new(config.usb_adc_timer_ms * system_tick_rate_hz / 1000), - false, - ), - led0_timer: TickTimerService::new( - TickServiceData::new(config.led0_timer_ms * system_tick_rate_hz / 1000), - true, - ), - led1_timer: TickTimerService::new( - TickServiceData::new(config.led1_timer_ms * system_tick_rate_hz / 1000), - true, - ), - shutdown_timer: TickTimerService::new( - TickServiceData::new(config.shutdown_timer_s), - false, - ), - pps_timer: TickTimerService::new(TickServiceData::new(system_tick_rate_hz), true), - // led2_timer: TickTimerService::new( - // TickServiceData::new(config.led2_timer_ms * system_tick_rate_hz / 1000), - // true, - // ), - } - } - pub fn tick(&mut self) { - self.sp_timer.tick(); - self.lp_timer.tick(); - self.batt_adc_timer.tick(); - self.usb_adc_timer.tick(); - self.led0_timer.tick(); - self.led1_timer.tick(); - self.pps_timer.tick(); - // self.led2_timer.tick(); - } - pub fn need_service(&self) -> bool { - self.sp_timer.need_service() - | self.lp_timer.need_service() - | self.batt_adc_timer.need_service() - | self.usb_adc_timer.need_service() - | self.led0_timer.need_service() - | self.led1_timer.need_service() - | self.shutdown_timer.need_service() - | self.pps_timer.need_service() - // | self.led2_timer.need_service() - } - pub fn init(&mut self) { - self.led0_timer.reset(); - self.led0_timer.enable(true); - } -} - -// pub struct ServiceConfigs { - -// } -// things that sort of don't touch hardware but also do? -// TODO: make this merged with the interfaces maybe -// but also maybe not, since these are things that require servicing -pub struct Services { - pub led0: LedService, - pub led1: LedService, - // pub led2: LedService, - pub synth0: SynthesizerService, - pub sample_player: DacService<'static>, - pub sequencer: sequencer::DynamicSequence<'static>, -} - -impl Services { - pub fn tick(&mut self) { - self.synth0.tick(); - self.sample_player.tick(); - self.sequencer.tick(); - } -} - -pub struct Config { - pub system_tick_rate_hz: usize, - pub timers: TimerConfig, -} - -pub struct Sequences { - pub led0: sequencer::BasicSequence<'static>, - pub led1: sequencer::BasicSequence<'static>, - // pub led2: sequencer::BasicSequence<'static>, - pub audio: &'static [(&'static [sequencer::SequenceEntry], usize)], -} - -// things that touch hardware -pub struct Interfaces { - pub pwm_core: SimplePwmCore<'static, ch32_hal::peripherals::TIM1>, - pub adc_core: crate::AdcCore, - pub amp: crate::Amplifier, - pub usb: crate::Usb, -} - -pub struct App { - state: State, - pub settings: Settings, - timers: Timers, - services: Services, - sequences: Sequences, - interfaces: Interfaces, -} - -use settings::Level; -impl App { - pub fn new( - config: Config, - services: Services, - sequences: Sequences, - interfaces: Interfaces, - settings: Settings, - ) -> Self { - Self { - state: State::default(), - settings, - timers: Timers::new(config.timers, config.system_tick_rate_hz), - services, - sequences, - interfaces, - } - } - - pub fn init(&mut self) { - // self.timers.init(); - self.interfaces.amp.enable(); - - self.timers.batt_adc_timer.reset(); - self.timers.batt_adc_timer.enable(true); - - self.timers.usb_adc_timer.reset(); - self.timers.usb_adc_timer.enable(true); - - self.timers.led0_timer.reset(); - self.timers.led0_timer.enable(true); - - self.timers.led1_timer.reset(); - self.timers.led1_timer.enable(true); - - self.timers.shutdown_timer.reset(); - self.timers.shutdown_timer.enable(true); - - self.timers.pps_timer.reset(); - self.timers.pps_timer.enable(true); - - // self.timers.led2_timer.reset(); - // self.timers.led2_timer.enable(true); - - // self.services.synth0.set_freq(1); - self.services.synth0.disable(); - self.services.sequencer.disable(); - - crate::riscv::asm::delay(2_500_000); - } - - pub fn set_state(&mut self, state: State) { - self.state = state - } - - pub fn state(&self) -> State { - self.state - } - - pub fn settings(&self) -> Settings { - self.settings - } - - pub fn tick(&mut self) { - self.timers.tick(); - self.services.tick(); - } - - pub fn service(&mut self) { - // timers - if self.timers.sp_timer.need_service() { - self.timers.sp_timer.service(); - #[cfg(feature = "enable_print")] - println!("sp service"); - self.timers.sp_timer.reset(); - self.main_button_short_press(); - } - if self.timers.lp_timer.need_service() { - self.timers.lp_timer.service(); - #[cfg(feature = "enable_print")] - println!("lp service"); - self.timers.lp_timer.reset(); - self.main_button_long_press(); - } - if self.timers.batt_adc_timer.need_service() { - self.timers.batt_adc_timer.service(); - if !self.interfaces.usb.powered() { - let bv = self.interfaces.adc_core.get_battery_voltage(); - let avg = self.interfaces.adc_core.get_average(); - // #[cfg(feature = "enable_print")] - // println!("batt adc service: {bv}, {avg}"); - // println!("none USB"); - if avg < 421 { - self.set_state(State::DeepSleep); - } - } - } - if self.timers.usb_adc_timer.need_service() { - self.timers.usb_adc_timer.service(); - #[cfg(feature = "enable_print")] - println!("usb adc service"); - } - if self.timers.led0_timer.need_service() { - let out = match self.settings.brightness { - Level::Off => 0, - Level::Low => 5, - Level::Medium => 25, - Level::High => 75, - Level::Maximum => { - self.sequences.led0.next(); - self.sequences.led0.get_value() / 6 - } - }; - - self.timers.led0_timer.service(); - self.services.led0.set_amplitude(out); - // #[cfg(feature = "enable_print")] - // println!("led0 sevice {}", self.sequences.led0.get_value()); - } - if self.timers.led1_timer.need_service() { - let out = match self.settings.brightness { - Level::Off => 0, - Level::Low => 5, - Level::Medium => 25, - Level::High => 75, - Level::Maximum => { - self.sequences.led1.next(); - self.sequences.led1.get_value() / 6 - } - }; - self.timers.led1_timer.service(); - self.services.led1.set_amplitude(out); - - // #[cfg(feature = "enable_print")] - // println!("led1 service"); - } - if self.timers.pps_timer.need_service() { - self.timers.pps_timer.service(); - self.timers.shutdown_timer.tick(); - } - if self.timers.shutdown_timer.need_service() { - self.timers.shutdown_timer.service(); - self.timers.shutdown_timer.reset(); - // println!("eepy"); - self.set_state(State::DeepSleep); - } - // if self.timers.led2_timer.need_service() { - // let out = match self.settings.brightness { - // Level::Off => 0, - // Level::Low => 5, - // Level::Medium => 25, - // Level::High => 75, - // Level::Maximum => { - // self.sequences.led2.next(); - // self.sequences.led2.get_value() / 6 - // } - // }; - // self.timers.led2_timer.service(); - // self.services.led2.set_amplitude(out); - - // // #[cfg(feature = "enable_print")] - // // println!("led2 service"); - // } - - // services - if self.services.led0.need_service() { - self.interfaces - .pwm_core - .write_amplitude(self.services.led0.channel, self.services.led0.amplitude); - self.services.led0.service(); - } - if self.services.led1.need_service() { - self.interfaces - .pwm_core - .write_amplitude(self.services.led1.channel, self.services.led1.amplitude); - self.services.led1.service(); - } - // if self.services.led2.need_service() { - // self.interfaces - // .pwm_core - // .write_amplitude(self.services.led2.channel, self.services.led2.amplitude); - // self.services.led2.service(); - // } - - // TODO: disable when you get to the end automatically - // in the sequencer, not here - if self.services.sequencer.need_service() { - if let Some(out) = self.services.sequencer.service() { - if out == 0 { - self.services.synth0.disable(); - } else { - self.services.synth0.enable(); - self.services.synth0.set_freq(out.into()); - } - } else { - self.services.sequencer.disable(); - self.services.synth0.disable(); - } - } - - if self.services.synth0.need_service() { - let out = match self.services.synth0.service() { - Some(value) => value / 6 / self.settings.volume.as_volume_divisor(), - None => 0, - }; - self.interfaces - .pwm_core - .write_amplitude(ch32_hal::timer::Channel::Ch4, out); - } - - if self.services.sample_player.need_service() { - self.services.sample_player.service(); - let out = self.services.sample_player.get_amplitude() / 2; - self.interfaces - .pwm_core - .write_amplitude(ch32_hal::timer::Channel::Ch4, out as u8); - } - } -} - -// interfaces to the app (for buttons, etc.) -impl App { - pub fn shut_down(&mut self) { - self.interfaces - .pwm_core - .write_amplitude(self.services.led0.channel, 0); - self.interfaces - .pwm_core - .write_amplitude(self.services.led1.channel, 0); - crate::riscv::asm::delay(10_000_000); - - self.interfaces.pwm_core.pwm.borrow().shutdown(); - self.interfaces.adc_core.shutdown(); - - self.interfaces.amp.disable(); - } - pub fn volume_button(&mut self) { - self.settings.volume.next(); - #[cfg(feature = "enable_print")] - println!("new volume: {:?}", self.settings.volume); - self.services - .sequencer - .play_sequence(&crate::sequences::COIN_CHIRP, 0); - self.timers.shutdown_timer.reset(); - self.timers.shutdown_timer.enable(true); - } - pub fn brightness_button(&mut self) { - self.settings.brightness.next(); - #[cfg(feature = "enable_print")] - println!("new brightness: {:?}", self.settings.brightness); - self.timers.shutdown_timer.reset(); - self.timers.shutdown_timer.enable(true); - } - pub fn main_button_press(&mut self) { - // TODO - #[cfg(feature = "enable_print")] - println!("main button press"); - self.timers.sp_timer.reset(); - self.timers.lp_timer.reset(); - self.timers.shutdown_timer.reset(); - self.timers.sp_timer.enable(true); - self.timers.lp_timer.enable(true); - self.timers.shutdown_timer.enable(true); - self.main_button_click(); - } - pub fn main_button_release(&mut self) { - // TODO - // #[cfg(feature = "enable_print")] - // println!("main button release"); - // let timers = ( - // self.timers.sp_timer.is_enabled(), - // self.timers.lp_timer.is_enabled(), - // ); - - self.timers.sp_timer.reset(); - self.timers.lp_timer.reset(); - // match timers { - // // click - // (true, true) => self.main_button_click(), - // // short press - // (false, true) => self.main_button_short_press(), - // // long press - // (false, false) => self.main_button_long_press(), - // // anything else is not possible - // _ => {} - // } - } - pub fn coin_detect(&mut self) { - #[cfg(feature = "enable_print")] - println!("coin detect"); - // self.services.sample_player.play_sample(); - self.services - .sequencer - .play_sequence(&crate::sequences::COIN_CHIRP, 0); - self.timers.shutdown_timer.reset(); - self.timers.shutdown_timer.enable(true); - } -} - -// Events -impl App { - pub fn main_button_click(&mut self) { - // TODO - #[cfg(feature = "enable_print")] - println!("click"); - let data = self.sequences.audio[self.settings.button_sound_index]; - self.services.sequencer.play_sequence(data.0, data.1); - - self.settings.button_sound_index += 1; - if self.settings.button_sound_index > self.sequences.audio.len() - 1 { - self.settings.button_sound_index = 0; - } - - self.services.synth0.enable(); - - // TODO: - // this is a hack to stop the coin thing from playing. - self.services.sample_player.disable(); - } - fn main_button_short_press(&self) { - // TODO - #[cfg(feature = "enable_print")] - println!("short press"); - } - fn main_button_long_press(&mut self) { - // TODO - #[cfg(feature = "enable_print")] - println!("long press"); - self.set_state(State::DeepSleep); - } -} - -// Getters -impl App { - pub fn get_state(&self) -> State { - self.state - } - pub fn get_settings(&self) -> Settings { - self.settings - } - pub fn should_wake(&self) -> bool { - if self.interfaces.usb.powered() { - return true; - } else { - if self.interfaces.adc_core.get_average() >= 421 { - return true; - } - } - return false; - } -} - -// TODO LIST -// BROKEN: -// 1. audio scaling causes crash -// 2. popping on sample playback -// 3. actual app sequence (start at idle?) -// -// AUDIO: -// 3. amp_en control -// -// LED: -// -// INTERFACE: -// 1. short press handling -// 2. long press handling -// -// SYSTEM: -// 1. deep sleep -// 2. battery voltage monitoring -// 3. battery voltage cutoff -// -// STRETCH TODO LIST -// 1. clean up edge detector -// 2. better handling for pwm scaling (brightness / volume) -// 3. better interrupt handling structs -// 4. led DynamicSequence diff --git a/ch32v-insert-coin/src/debounced_gpio.rs b/ch32v-insert-coin/src/debounced_gpio.rs deleted file mode 100644 index 784c3fd..0000000 --- a/ch32v-insert-coin/src/debounced_gpio.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::insert_coin::{TickService, TickServiceData, TickTimerService}; -use ch32_hal::gpio::{AnyPin, Input, Pull}; - -pub struct DebouncedGPIO<'a> { - input: Input<'a>, - // value of the GPIO - value: bool, - // GPIO is ready (debounced) - ready: bool, - // debouncer is active - active: bool, - // debounce timer - timer: TickTimerService, -} - -impl<'a> DebouncedGPIO<'a> { - pub fn new(pin: AnyPin, system_tick_rate_hz: usize, debounce_time_ms: usize) -> Self { - // coin debounce timer (100ms) - Self { - input: Input::new(pin, Pull::None), - value: false, - ready: false, - active: false, - timer: TickTimerService::new( - TickServiceData::new(system_tick_rate_hz * debounce_time_ms / 1000), - false, - ), - } - } - - pub fn ready(&self) -> bool { - self.ready - } - - pub fn active(&self) -> bool { - self.active - } - - pub fn value(&self) -> bool { - self.value - } - - pub fn begin(&mut self) { - self.reset(); - self.timer.enable(true); - self.active = true; - } - - pub fn reset(&mut self) { - self.timer.reset(); - self.ready = false; - self.active = false; - } - - pub fn service(&mut self) { - self.timer.tick(); - if self.timer.need_service() { - self.timer.reset(); - self.value = self.input.is_high(); - self.ready = true; - } - } - pub fn is_high_immediate(&self) -> bool { - self.input.is_high() - } -} diff --git a/ch32v-insert-coin/src/insert_coin/insert_coin.rs b/ch32v-insert-coin/src/insert_coin/insert_coin.rs deleted file mode 100644 index 8c0a606..0000000 --- a/ch32v-insert-coin/src/insert_coin/insert_coin.rs +++ /dev/null @@ -1,183 +0,0 @@ -use ch32_hal::timer::simple_pwm::SimplePwm; -use ch32_hal::timer::Channel; -use ch32_hal::timer::GeneralInstance16bit; - -use crate::insert_coin::services::{DacService, LedService, Service, TickService, TickServiceData}; - -// static mut led0_index: usize = 0; -// static LED0: [u8; 8] = [0u8, 25u8, 50u8, 75u8, 100u8, 75u8, 50u8, 25u8]; - -// static mut LED1_INDEX: usize = 0; -// static LED1_DCS: [u8; 5] = [0u8, 25u8, 50u8, 75u8, 100u8]; - -pub struct SimplePwmCore<'d, T: GeneralInstance16bit> { - pub pwm: core::cell::RefCell>, -} - -impl<'d, T: GeneralInstance16bit> SimplePwmCore<'d, T> { - pub fn new(pwm: SimplePwm<'d, T>) -> Self { - Self { - pwm: core::cell::RefCell::new(pwm), - } - } - - // pub fn get_handle(&'d self, ch: Channel) -> SimplePwmHandle<'d, '_, T> { - // SimplePwmHandle { - // core: &self, - // channel: ch, - // } - // } - - pub fn write_amplitude(&self, ch: Channel, amplitude: u8) { - if !self.pwm.borrow().is_enabled(ch) { - self.pwm.borrow_mut().enable(ch); - } - let max_duty = self.pwm.borrow().get_max_duty(); - let dc = amplitude as u32 * max_duty / 100; - self.pwm.borrow_mut().set_duty(ch, dc); - } - - pub fn disable(&self, ch: Channel) { - self.pwm.borrow_mut().disable(ch); - } -} - -// pub struct SimplePwmHandle { -// core: &'static SimplePwmCore<'_, T: GeneralInstance16Bit>, -// channel: Channel, -// } - -// impl SimplePwmHandle { -// pub fn set_amplitude(&self, amplitude: u8) {} -// } - -pub struct CoreConfig { - pub tick_rate_hz: usize, -} -impl CoreConfig { - pub fn new(tick_rate_hz: usize) -> Self { - Self { tick_rate_hz } - } -} - -#[derive(Default)] -struct Core { - _tick: usize, - active: bool, -} - -pub struct InsertCoin<'a, T: GeneralInstance16bit> { - core: Core, - pub config: CoreConfig, - pwm_core: SimplePwmCore<'a, T>, - pub led0: LedService, - pub led1: LedService, - // led2: LedService, - pub dac: DacService<'a>, -} - -impl<'a, T: GeneralInstance16bit> InsertCoin<'a, T> { - pub fn new(config: CoreConfig, pwm_core: SimplePwmCore<'a, T>) -> Self { - // LED0 servicer setup - let led0 = LedService::new(ch32_hal::timer::Channel::Ch3); - - // LED1 servicer setup - let led1 = LedService::new(ch32_hal::timer::Channel::Ch1); - - // DAC servicer setup - let dac_sample_rate_hz = 4000; - let dac_tick_per_service = config.tick_rate_hz / (dac_sample_rate_hz); - let dac_service_data = TickServiceData::new(dac_tick_per_service); - let dac = DacService::new(ch32_hal::timer::Channel::Ch4, dac_service_data); - - Self { - config, - core: Default::default(), - pwm_core, - led0, - led1, - // led2, - dac, - } - } - - /// takes self reference and runs - pub fn service(&mut self) { - if self.is_active() { - self.dac.tick(); - - if self.led0.need_service() { - self.pwm_core - .write_amplitude(self.led0.channel, self.led0.amplitude); - self.led0.service(); - } - - if self.led1.need_service() { - self.pwm_core - .write_amplitude(self.led1.channel, self.led1.amplitude); - self.led1.service(); - } - - if self.dac.need_service() { - self.dac.service(); - // TODO: adpcm-pwm-dac:e4c811653781e69e40b63fd27a8c1e20 - self.pwm_core - .write_amplitude(self.dac.channel, self.dac.get_amplitude() as u8); - } - } - } - - // /// consumes self and runs - // pub fn run(mut self) -> ! { - // let mut delay = Delay; - // let tick_interval_us = 1000000/self.config.tick_rate_hz; - - // let mut led0_index = 0; - // let led0_dcs = [0u8, 25u8, 50u8, 75u8, 100u8, 75u8, 50u8, 25u8]; - - // let mut led1_index = 0; - // let led1_dcs = [0u8, 25u8, 50u8, 75u8, 100u8]; - - // loop { - // self.dac.tick(); - - // if(self.led0.need_service()) { - // self.led0.set_amplitude(led0_dcs[led0_index]); - // self.pwm_core.write_amplitude(self.led0.channel, self.led0.amplitude); - - // led0_index += 1; - // if led0_index > led0_dcs.len() - 1 { - // led0_index = 0; - // } - // self.led0.service(); - // } - - // if(self.led1.need_service()) { - // self.led1.set_amplitude(led1_dcs[led1_index]); - // self.pwm_core.write_amplitude(self.led1.channel, self.led1.amplitude); - - // led1_index += 1; - // if led1_index > led1_dcs.len() - 1 { - // led1_index = 0; - // } - // self.led1.service(); - // } - - // if(self.dac.need_service()) { - // self.dac.service(); - // // TODO: adpcm-pwm-dac:e4c811653781e69e40b63fd27a8c1e20 - // self.pwm_core.write_amplitude(self.dac.channel, self.dac.get_amplitude() as u8); - // } - - // delay.delay_us(tick_interval_us as u32); - // } - // } - - pub fn is_active(&self) -> bool { - self.core.active - } - - pub fn set_active(&mut self, active: bool) { - self.core.active = active; - } -} diff --git a/ch32v-insert-coin/src/insert_coin/mod.rs b/ch32v-insert-coin/src/insert_coin/mod.rs deleted file mode 100644 index 766dcca..0000000 --- a/ch32v-insert-coin/src/insert_coin/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod insert_coin; -mod services; - -pub use services::{DacService, LedService, Service, TickTimerService}; - -pub use insert_coin::{CoreConfig, InsertCoin, SimplePwmCore}; -pub use services::{TickService, TickServiceData}; diff --git a/ch32v-insert-coin/src/insert_coin/services/dac.rs b/ch32v-insert-coin/src/insert_coin/services/dac.rs deleted file mode 100644 index 0a3b364..0000000 --- a/ch32v-insert-coin/src/insert_coin/services/dac.rs +++ /dev/null @@ -1,68 +0,0 @@ -use crate::insert_coin::services::{TickService, TickServiceData}; - -use adpcm_pwm_dac::dac::DpcmDecoder; -use ch32_hal::timer::Channel; - -pub struct DacService<'a> { - service_data: core::cell::RefCell, - dpcm_decoder: core::cell::RefCell>, - amplitude: core::cell::RefCell, - pub channel: Channel, - enabled: bool, -} - -impl<'a> DacService<'a> { - pub fn new(channel: Channel, service_data: TickServiceData) -> Self { - Self { - service_data: core::cell::RefCell::new(service_data), - dpcm_decoder: core::cell::RefCell::new(DpcmDecoder::new()), - amplitude: core::cell::RefCell::new(0), - channel, - enabled: false, - } - } - - pub fn play_sample(&mut self) { - self.dpcm_decoder.borrow_mut().seek_to_sample(0); - self.enabled = true; - } - - pub fn disable(&mut self) { - self.enabled = false; - } - - pub fn load_data(&self, data: &'a [u8]) { - self.dpcm_decoder.borrow_mut().load_data(data); - self.dpcm_decoder.borrow_mut().seek_to_sample(0); - } - - pub fn set_amplitude(&self, amplitude: usize) { - self.amplitude.replace(amplitude); - } - pub fn get_amplitude(&self) -> usize { - *self.amplitude.borrow() - } -} - -impl<'a> TickService for DacService<'a> { - fn tick(&self) { - if self.enabled { - let mut tc = self.service_data.borrow_mut(); - tc.ticks_remaining = tc.ticks_remaining.saturating_sub(1); - } - } - - fn need_service(&self) -> bool { - self.enabled && self.service_data.borrow().ticks_remaining == 0 - } - - fn service(&self) { - let mut tc = self.service_data.borrow_mut(); - tc.ticks_remaining = tc.ticks_per_service; - if (self.dpcm_decoder.borrow().is_done()) { - self.set_amplitude(0); - } else { - self.set_amplitude(self.dpcm_decoder.borrow_mut().output_next()); - } - } -} diff --git a/ch32v-insert-coin/src/insert_coin/services/led.rs b/ch32v-insert-coin/src/insert_coin/services/led.rs deleted file mode 100644 index c1bf890..0000000 --- a/ch32v-insert-coin/src/insert_coin/services/led.rs +++ /dev/null @@ -1,36 +0,0 @@ -use ch32_hal::timer::Channel; - -use crate::insert_coin::services::Service; - -pub struct LedService { - // need_service: core::cell::RefCell, - need_service: bool, - pub channel: Channel, - pub amplitude: u8, -} - -impl LedService { - pub fn new(channel: Channel) -> Self { - Self { - // service_data: core::cell::RefCell::new(service_data), - need_service: false, - channel, - amplitude: 0, - } - } - - pub fn set_amplitude(&mut self, amplitude: u8) { - self.amplitude = amplitude; - self.need_service = true; - } -} - -impl Service for LedService { - fn need_service(&self) -> bool { - self.need_service - } - - fn service(&mut self) { - self.need_service = false; - } -} diff --git a/ch32v-insert-coin/src/insert_coin/services/mod.rs b/ch32v-insert-coin/src/insert_coin/services/mod.rs deleted file mode 100644 index a761548..0000000 --- a/ch32v-insert-coin/src/insert_coin/services/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -mod services; -pub use services::{TickService, TickServiceData, Service}; - -mod led; -pub use led::LedService; - -mod dac; -pub use dac::DacService; - -mod tick_timer; -pub use tick_timer::TickTimerService; \ No newline at end of file diff --git a/ch32v-insert-coin/src/insert_coin/services/services.rs b/ch32v-insert-coin/src/insert_coin/services/services.rs deleted file mode 100644 index e2c86e2..0000000 --- a/ch32v-insert-coin/src/insert_coin/services/services.rs +++ /dev/null @@ -1,31 +0,0 @@ -pub struct TickServiceData { - pub ticks_per_service: usize, - pub ticks_remaining: usize, -} - -impl TickServiceData { - pub fn new(ticks_per_service: usize) -> Self { - Self { - ticks_per_service, - ticks_remaining: ticks_per_service, - } - } -} - -pub trait TickService { - /// indicate to the service that a tick has occurred - fn tick(&self); - - /// return true if service needs the service() routine run - fn need_service(&self) -> bool; - - /// service routine - handle what needs to be done (non blocking) when - /// the service needs to be serviced here - fn service(&self); -} - - -pub trait Service { - fn need_service(&self) -> bool; - fn service(&mut self); -} \ No newline at end of file diff --git a/ch32v-insert-coin/src/insert_coin/services/tick_timer.rs b/ch32v-insert-coin/src/insert_coin/services/tick_timer.rs deleted file mode 100644 index 863314a..0000000 --- a/ch32v-insert-coin/src/insert_coin/services/tick_timer.rs +++ /dev/null @@ -1,49 +0,0 @@ -use crate::insert_coin::services::{TickService, TickServiceData}; - -pub struct TickTimerService { - service_data: core::cell::RefCell, - _auto_reset: bool, - enabled: bool, -} - -impl TickTimerService { - pub fn new(service_data: TickServiceData, auto_reset: bool) -> Self { - Self { - service_data: core::cell::RefCell::new(service_data), - _auto_reset: auto_reset, - enabled: false, - } - } - - pub fn is_enabled(&self) -> bool { - self.enabled - } - - pub fn reset(&mut self) { - let mut sd = self.service_data.borrow_mut(); - sd.ticks_remaining = sd.ticks_per_service; - self.enabled = false; - } - - pub fn enable(&mut self, enable: bool) { - self.enabled = enable; - } -} - -impl TickService for TickTimerService { - fn tick(&self) { - if self.enabled { - let mut tc = self.service_data.borrow_mut(); - tc.ticks_remaining = tc.ticks_remaining.saturating_sub(1); - } - } - - fn need_service(&self) -> bool { - self.enabled && self.service_data.borrow().ticks_remaining == 0 - } - - fn service(&self) { - let mut tc = self.service_data.borrow_mut(); - tc.ticks_remaining = tc.ticks_per_service; - } -} diff --git a/ch32v-insert-coin/src/main.rs b/ch32v-insert-coin/src/main.rs deleted file mode 100644 index 694ce75..0000000 --- a/ch32v-insert-coin/src/main.rs +++ /dev/null @@ -1,648 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] -#![feature(impl_trait_in_assoc_type)] - -// app stuff -mod insert_coin; - -// system stuff -mod system; - -mod debounced_gpio; -use debounced_gpio::DebouncedGPIO; - -// synthesizer :3 -mod synthesizer; -use synthesizer::SynthesizerService; - -// sequences -mod sequences; -use sequences::SEQUENCE_LIST; - -mod app; -use app::{ - sequencer::BasicSequence, App, Config, Interfaces, Sequences, Services, State, TimerConfig, -}; - -use ch32_hal::{adc::AdcChannel, interrupt::typelevel::Handler, timer::low_level::OutputPolarity}; -use insert_coin::{CoreConfig, DacService, InsertCoin, LedService, SimplePwmCore}; - -use ch32_hal as hal; -use hal::bind_interrupts; -use hal::delay::Delay; -use hal::gpio::{AnyPin, Input, Level, Output, OutputOpenDrain, Pin, Pull}; -use hal::time::Hertz; -use hal::timer::low_level::CountingMode; -use hal::timer::simple_pwm::{PwmPin, SimplePwm}; - -use hal::println; - -use qingke::riscv; - -use crate::app::sequencer::{DynamicSequence, SequenceEntry}; - -static LED0_SEQ: [u8; 8] = [0u8, 25u8, 50u8, 75u8, 100u8, 75u8, 50u8, 25u8]; - -pub struct Usb { - usb_pin: Input<'static>, -} - -impl Usb { - pub fn new(usb_pin: Input<'static>) -> Self { - Self { usb_pin } - } - pub fn powered(&self) -> bool { - self.usb_pin.is_high() - } - // pub fn enable(&mut self) { - // self.usb_pin.set_as_input(Pull::Up); - // } - // pub fn disable(&mut self) { - // self.usb_pin.set_as_input(Pull::None); - // } -} - -pub struct Amplifier { - amp_en: OutputOpenDrain<'static>, -} - -impl Amplifier { - pub fn new(amp_en: OutputOpenDrain<'static>) -> Self { - let mut amp = Self { amp_en }; - amp.disable(); - amp - } - pub fn enable(&mut self) { - self.amp_en.set_low(); - } - pub fn disable(&mut self) { - self.amp_en.set_high(); - } - pub fn enabled(&self) -> bool { - !self.amp_en.is_set_high() - } -} - -use hal::adc::Adc; -use hal::peripherals::{ADC1, PD4}; - -pub struct AdcCore { - adc: Adc<'static, ADC1>, - battery_pin: PD4, - batt_values: [u16; 10], - index: usize, -} - -impl AdcCore { - pub fn new(mut adc: Adc<'static, ADC1>, pin: PD4) -> Self { - riscv::asm::delay(20_000); - adc.calibrate(); - Self { - adc, - battery_pin: pin, - batt_values: [1024; 10], - index: 0, - } - } - - // TODO make this a float or something - pub fn get_battery_voltage(&mut self) -> u16 { - let val = self - .adc - .convert(&mut self.battery_pin, hal::adc::SampleTime::CYCLES241); - self.batt_values[self.index] = val; - self.index += 1; - if self.index > &self.batt_values.len() - 1 { - self.index = 0; - } - val - } - - pub fn get_average(&self) -> u16 { - let mut sum = 0; - for value in &self.batt_values { - sum += value; - } - sum / self.batt_values.len() as u16 - } - - pub fn shutdown(&mut self) { - self.adc.shutdown() - } -} - -#[derive(Debug)] -struct Flag { - value: bool, -} -impl Flag { - pub fn active(&self) -> bool { - unsafe { core::ptr::read_volatile(&raw const self.value as *const bool) } - } - pub fn set(&mut self) { - unsafe { core::ptr::write_volatile(&raw mut self.value as *mut bool, true) } - } - pub fn clear(&mut self) { - unsafe { core::ptr::write_volatile(&raw mut self.value as *mut bool, false) } - } -} - -#[derive(Debug)] -struct InputFlags { - sense_coin_flag: Flag, - main_btn_flag: Flag, - volume_btn_flag: bool, - light_ctrl_btn_flag: bool, - systick_flag: Flag, -} - -impl Default for InputFlags { - fn default() -> Self { - Self { - sense_coin_flag: Flag { value: false }, - main_btn_flag: Flag { value: false }, - volume_btn_flag: false, - light_ctrl_btn_flag: false, - systick_flag: Flag { value: false }, - } - } -} - -static mut INPUT_FLAGS: InputFlags = InputFlags { - sense_coin_flag: Flag { value: false }, - main_btn_flag: Flag { value: false }, - volume_btn_flag: false, - light_ctrl_btn_flag: false, - systick_flag: Flag { value: false }, -}; - -struct Test {} -impl Handler for Test { - unsafe fn on_interrupt() { - // #[cfg(feature = "enable_print")] - // println!("on_interrupt()"); - critical_section::with(|_| unsafe { - let flags = system::clear_interrupt(2, 6); - if flags[0] { - // safe because single-threaded - #[allow(static_mut_refs)] - INPUT_FLAGS.sense_coin_flag.set(); - } - if flags[1] { - #[allow(static_mut_refs)] - INPUT_FLAGS.main_btn_flag.set(); - } - }); - } -} - -#[qingke_rt::interrupt(core)] -fn SysTick() { - let r = &ch32_hal::pac::SYSTICK; - - // Clear interrupt flag - r.sr().write(|w| w.set_cntif(false)); - - unsafe { - // safe because single-threaded - #[allow(static_mut_refs)] - INPUT_FLAGS.systick_flag.set(); - } -} - -fn systick_init(tick_freq_hz: usize) { - let r = &ch32_hal::pac::SYSTICK; - - // Calculate counts per millisecond using HCLK/8 as clock source - // HCLK/8 = 48MHz/8 = 6MHz - // For tick_freq_hz interrupt: 6MHz / tick_freq_hz - let systick_per_tick = (48_000_000 / 8 / tick_freq_hz) as u32; - - // Reset SysTick - r.ctlr().write(|w| { - // Start with everything disabled - }); - - // Set compare register and reset counter - r.cmp().write_value(systick_per_tick - 1); - r.cnt().write_value(0); - - // Clear interrupt flag - r.sr().write(|w| w.set_cntif(false)); - - // Configure and start SysTick - r.ctlr().write(|w| { - w.set_ste(true); // Enable counter - w.set_stie(true); // Enable interrupt - w.set_stre(true); // Auto reload enable - w.set_stclk(ch32_hal::pac::systick::vals::Stclk::HCLK_DIV8); // HCLK/8 clock source - }); -} -fn systick_stop() { - let r = &ch32_hal::pac::SYSTICK; - // Reset SysTick - r.ctlr().write(|w| { - // Start with everything disabled - }); -} - -bind_interrupts!(struct Irqs { - EXTI7_0 => Test; -}); - -// TODO: remove -use app::settings::Settings; -use insert_coin::TickTimerService; -use insert_coin::{TickService, TickServiceData}; - -fn app_main(mut p: hal::Peripherals, app_settings: Settings) -> Settings { - // initialize ADC core first, and exit if battery is too low - let mut adc = hal::adc::Adc::new(p.ADC1, Default::default()); - let mut batt_monitor_pin = p.PD4; - let mut adc_core = AdcCore::new(adc, batt_monitor_pin); - - let mut usb_detect_pin = p.PD5; - let usb_detect_input = Input::new(usb_detect_pin, Pull::Up); - let usb = Usb::new(usb_detect_input); - - let bv = adc_core.get_battery_voltage(); - - // if we don't have USB power, and the batt ADC reads under 421, don't wake - if !usb.powered() && bv < 421 { - adc_core.shutdown(); - return app_settings; - } - // === output setup === - - // LED0 output setup - let led0_pin = PwmPin::new_ch3::<0>(p.PC3); - let led0_ch = hal::timer::Channel::Ch3; - - // LED1 output setup - let led1_pin = PwmPin::new_ch1::<0>(p.PD2); - let led1_ch = hal::timer::Channel::Ch1; - - // DAC output setup - let dac_pin = PwmPin::new_ch4::<0>(p.PC4); - // let dac_ch = hal::timer::Channel::Ch4; - - // PWM timer setup - let mut pwm = SimplePwm::new( - p.TIM1, - Some(led1_pin), - // Some(led2_pin), - None, - Some(led0_pin), - Some(dac_pin), - Hertz::khz(200), - CountingMode::default(), - ); - - pwm.set_polarity(led0_ch, OutputPolarity::ActiveHigh); - pwm.set_polarity(led1_ch, OutputPolarity::ActiveLow); - let mut pwm_core = SimplePwmCore::new(pwm); - pwm_core.write_amplitude(led0_ch, 0); - pwm_core.write_amplitude(led1_ch, 0); - - // pwm.set_polarity(led2_ch, OutputPolarity::ActiveLow); - - let tick_rate_hz = 50000; - - let core_config = CoreConfig::new(tick_rate_hz); - - // === input setup === - - // adc - // let mut adc = hal::adc::Adc::new(p.ADC1, Default::default()); - // let mut batt_monitor_pin = p.PD4; - // let adc_core = AdcCore::new(adc, batt_monitor_pin); - - // adc2 - // let mut usb_detect_dc = hal::adc::Adc::new(p.ADC1, Default::default()); - - // println!("ADC_PIN CHANNEL: {}", adc_pin.channel().channel()); - - // #[cfg(feature = "enable_print")] - // println!("ADC calibration value: {}", adc_cal); - - // definitions - let sense_coin_pin = p.PC2; - let main_btn_pin = p.PD6; - let volume_btn_pin = p.PC6; - let light_ctrl_btn_pin = p.PC7; - let amp_en = p.PC5; - // let extra_io_1 = p.PD0; - // let extra_io_2 = p.PD3; - - let mut amp_en_output = OutputOpenDrain::new(amp_en, Level::Low, Default::default()); - let amp = Amplifier::new(amp_en_output); - - // set up interrupts - unsafe { system::init_gpio_irq(sense_coin_pin.pin(), sense_coin_pin.port(), true, false) }; - unsafe { system::init_gpio_irq(main_btn_pin.pin(), main_btn_pin.port(), true, true) }; - - // coin debouncer (100ms) - let mut sense_coin_input = - DebouncedGPIO::new(sense_coin_pin.degrade(), core_config.tick_rate_hz, 20); - // main button debouncer (100ms) - let mut main_btn_input = - DebouncedGPIO::new(main_btn_pin.degrade(), core_config.tick_rate_hz, 20); - // button debouncer (100ms) - let mut volume_btn_input = - DebouncedGPIO::new(volume_btn_pin.degrade(), core_config.tick_rate_hz, 100); - // button debouncer (100ms) - let mut light_ctrl_btn_input = - DebouncedGPIO::new(light_ctrl_btn_pin.degrade(), core_config.tick_rate_hz, 100); - - let timer_config = TimerConfig { - sp_timer_ms: 1000, - lp_timer_ms: 3000, - batt_adc_timer_ms: 1000, - usb_adc_timer_ms: 10000, - led0_timer_ms: 100, - led1_timer_ms: 100, - // 4 hours: - // shutdown_timer_s: 1, - shutdown_timer_s: 4 * 60 * 60 * 110 / 100, - // led2_timer_ms: 100, - }; - - let app_config = Config { - system_tick_rate_hz: tick_rate_hz, - timers: timer_config, - }; - - // DAC servicer setup - let dac_sample_rate_hz = 16000; - let dac_tick_per_service = tick_rate_hz / dac_sample_rate_hz; - let dac_service_data = TickServiceData::new(dac_tick_per_service); - - // let coin_sound = include_bytes!("../audio/coin5.raw"); - // let coin_sound = include_bytes!("../audio/coin2.raw"); - - let sample_player = DacService::new(ch32_hal::timer::Channel::Ch4, dac_service_data); - // sample_player.load_data(coin_sound); - - let sequencer = app::sequencer::DynamicSequence::new(&SEQUENCE_LIST[0].0, tick_rate_hz); - - let app_services = Services { - led0: LedService::new(led0_ch), - led1: LedService::new(led1_ch), - // led2: LedService::new(led2_ch), - synth0: SynthesizerService::new(tick_rate_hz), - sample_player, - sequencer, - }; - - let app_sequences = Sequences { - led0: BasicSequence::new(&LED0_SEQ), - led1: BasicSequence::new(&LED0_SEQ), - // led2: BasicSequence::new(&LED0_SEQ), - audio: &SEQUENCE_LIST, - }; - - let app_interfaces = Interfaces { - pwm_core, - adc_core, - amp, - usb, - }; - - let mut app = App::new( - app_config, - app_services, - app_sequences, - app_interfaces, - app_settings, - ); - - let need_sound = unsafe { - #[allow(static_mut_refs)] - if INPUT_FLAGS.main_btn_flag.active() { - #[allow(static_mut_refs)] - INPUT_FLAGS.main_btn_flag.clear(); - true - } else { - false - } - }; - - // init systick - systick_init(tick_rate_hz); - - // set up interrupts - unsafe { - use hal::pac::Interrupt; - use qingke::interrupt::Priority; - use qingke_rt::CoreInterrupt; - - system::clear_interrupt(2, 6); - - qingke::pfic::set_priority(CoreInterrupt::SysTick as u8, Priority::P15 as u8); - - qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); - qingke::pfic::enable_interrupt(CoreInterrupt::SysTick as u8); - } - - // MAIN APPLICATION - // process - // -depress big button (insert coin button) and it wakes up and turns on led one led at a fixed brightness - // -we will want one sound, the coin insert sound, to play when coin button is pressed. (This is when they insert a coin) - // -We will want a different sound or potentially multiple different sounds played in a rotating fashion when someone presses the button. Probably do some led blinking as well.(This is when they depress the big insert to play button) - // -depress the big button for approx 2s and it puts the led into low light mode. Just making it dimmer than usual. - // -depress the big button for 5s and it goes into deep sleep, everything off with the low sleep current draw - - // #[cfg(feature = "enable_print")] - // println!("begin"); - let mut volume_btn_prev = volume_btn_input.is_high_immediate(); - let mut light_ctrl_btn_prev = light_ctrl_btn_input.is_high_immediate(); - - app.init(); - if need_sound { - app.main_button_click(); - } - loop { - // system servicing - - // volume edge detector - if !volume_btn_input.active() { - let volume_btn_curr = volume_btn_input.is_high_immediate(); - if volume_btn_prev != volume_btn_curr { - volume_btn_input.begin(); - volume_btn_prev = volume_btn_curr; - } - } - - volume_btn_input.service(); - if volume_btn_input.ready() { - // #[cfg(feature = "enable_print")] - // println!("volume btn value: {}", volume_btn_input.value()); - if !volume_btn_input.value() { - app.volume_button(); - } - volume_btn_input.reset(); - } - - // brightness edge detector - if !light_ctrl_btn_input.active() { - let light_ctrl_btn_curr = light_ctrl_btn_input.is_high_immediate(); - if light_ctrl_btn_prev != light_ctrl_btn_curr { - light_ctrl_btn_input.begin(); - light_ctrl_btn_prev = light_ctrl_btn_curr; - } - } - - light_ctrl_btn_input.service(); - if light_ctrl_btn_input.ready() { - #[cfg(feature = "enable_print")] - println!("brightness btn value: {}", light_ctrl_btn_input.value()); - if !light_ctrl_btn_input.value() { - app.brightness_button(); - } - light_ctrl_btn_input.reset(); - } - - // coin_detect interrupt - - unsafe { - #[allow(static_mut_refs)] - if INPUT_FLAGS.sense_coin_flag.active() { - #[allow(static_mut_refs)] - INPUT_FLAGS.sense_coin_flag.clear(); - sense_coin_input.begin(); - } - sense_coin_input.service(); - if sense_coin_input.ready() { - sense_coin_input.reset(); - app.coin_detect(); - } - } - - // main button handling - unsafe { - #[allow(static_mut_refs)] - if INPUT_FLAGS.main_btn_flag.active() { - #[allow(static_mut_refs)] - INPUT_FLAGS.main_btn_flag.clear(); - main_btn_input.begin(); - } - } - main_btn_input.service(); - if main_btn_input.ready() { - let value = main_btn_input.value(); - main_btn_input.reset(); - // #[cfg(feature = "enable_print")] - // println!("main button", value); - - match value { - true => app.main_button_press(), - false => app.main_button_release(), - } - } - - // systick tick - if unsafe { - #[allow(static_mut_refs)] - INPUT_FLAGS.systick_flag.active() - } { - unsafe { - #[allow(static_mut_refs)] - INPUT_FLAGS.systick_flag.clear(); - } - // app tick - app.tick(); - } - - app.service(); - - match app.get_state() { - // enter standby - app::State::DeepSleep => { - app.shut_down(); - return app.get_settings(); - } - _ => {} - } - } -} - -use ch32_hal::timer::low_level::{OutputCompareMode, Timer}; -use ch32_hal::timer::Channel; - -// fn shutdown_main(p: Peripherals) { -fn shutdown_main(p: hal::Peripherals) { - systick_stop(); - // LED0 output setup - let led0_pin = OutputOpenDrain::new(p.PC3, Level::Low, Default::default()); - let led1_pin = OutputOpenDrain::new(p.PD2, Level::High, Default::default()); - let led2_pin = OutputOpenDrain::new(p.PA1, Level::High, Default::default()); - let dac_pin = OutputOpenDrain::new(p.PC4, Level::Low, Default::default()); - let mut amp_pin = OutputOpenDrain::new(p.PC5, Level::Low, Default::default()); - amp_pin.set_high(); - let volume_btn_pin = OutputOpenDrain::new(p.PC6, Level::Low, Default::default()); - let light_ctrl_btn_pin = OutputOpenDrain::new(p.PC7, Level::Low, Default::default()); - let usb_detect_input = OutputOpenDrain::new(p.PD5, Level::Low, Default::default()); - - let sense_coin_pin = p.PC2; - let main_btn_pin = p.PD6; - - unsafe { system::init_gpio_irq(sense_coin_pin.pin(), sense_coin_pin.port(), true, false) }; - unsafe { system::init_gpio_irq(main_btn_pin.pin(), main_btn_pin.port(), true, false) }; - - let sense_coin_pin = Input::new(sense_coin_pin, Pull::None); - let main_btn_pin = Input::new(main_btn_pin, Pull::None); - - riscv::asm::delay(1_000_000); - - loop { - unsafe { system::enter_standby() }; - riscv::asm::wfi(); - unsafe { - #[allow(static_mut_refs)] - if (INPUT_FLAGS.sense_coin_flag.active() || INPUT_FLAGS.main_btn_flag.active()) - // && app.should_wake() - { - break; - } - } - } -} - -#[qingke_rt::entry] -fn main() -> ! { - #[cfg(feature = "enable_print")] - hal::debug::SDIPrint::enable(); - - let mut config = hal::Config::default(); - config.rcc = hal::rcc::Config::SYSCLK_FREQ_48MHZ_HSI; - let mut p = hal::init(config); - - // delay to let the debugger attach - // println!("pre"); - riscv::asm::delay(20_000_000); - // println!("post"); - // debug_main(p); - - let mut app_settings = Settings::default(); - - loop { - unsafe { - hal::rcc::init(hal::rcc::Config::SYSCLK_FREQ_48MHZ_HSI); - } - let mut p = unsafe { hal::Peripherals::steal() }; - app_settings = app_main(p, app_settings); - - unsafe { - hal::rcc::init(hal::rcc::Config::SYSCLK_FREQ_48MHZ_HSI); - } - let mut p = unsafe { hal::Peripherals::steal() }; - shutdown_main(p); - } -} - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - // println!("panic: {info:?}"); - loop {} -} diff --git a/ch32v-insert-coin/src/sequences.rs b/ch32v-insert-coin/src/sequences.rs deleted file mode 100644 index 4cf6e4c..0000000 --- a/ch32v-insert-coin/src/sequences.rs +++ /dev/null @@ -1,346 +0,0 @@ -use crate::app::sequencer::SequenceEntry; - -pub static TEST_SEQ: [SequenceEntry; 2] = [ - SequenceEntry { - frequency_hz: 440, - duration_ms: 1000, - }, - SequenceEntry { - frequency_hz: 220, - duration_ms: 1000, - }, -]; - -pub static TEST_SEQ1: [SequenceEntry; 2] = [ - SequenceEntry { - frequency_hz: 440, - duration_ms: 100, - }, - SequenceEntry { - frequency_hz: 220, - duration_ms: 100, - }, -]; - -// play twice -pub static WAHWAH: [SequenceEntry; 9] = [ - SequenceEntry { - frequency_hz: 100, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 200, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 300, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 400, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 500, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 600, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 700, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 800, - duration_ms: 25, - }, - SequenceEntry { - frequency_hz: 900, - duration_ms: 25, - }, -]; - -pub static DECENDING_TONES: [SequenceEntry; 21] = [ - SequenceEntry { - frequency_hz: 1100, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1050, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1000, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 950, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 900, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 850, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 800, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 750, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 700, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 650, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 600, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 550, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 500, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 450, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 400, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 350, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 300, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 250, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 200, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 150, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 100, - duration_ms: 50, - }, -]; - -// PLAY ONCE -pub static COIN_CHIRP: [SequenceEntry; 2] = [ - SequenceEntry { - frequency_hz: 1000, - duration_ms: 100, - }, - SequenceEntry { - frequency_hz: 1500, - duration_ms: 500, - }, -]; - -// PLAY ONCE -pub static SOUND_8_BIT_GAME_4: [SequenceEntry; 4] = [ - SequenceEntry { - frequency_hz: 220, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 440, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 660, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 880, - duration_ms: 50, - }, -]; - -// PLAY TWICE -// TODO: this isn't working quite right with the 0hz "non note" for a rest... -pub static SOUND_8_BIT_GAME_1: [SequenceEntry; 3] = [ - SequenceEntry { - frequency_hz: 440, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1500, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 0, - duration_ms: 50, - }, -]; - -// PLAY 3 TIMES -pub static SOUND_8_BIT_GAME_3: [SequenceEntry; 3] = [ - SequenceEntry { - frequency_hz: 440, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 660, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1000, - duration_ms: 50, - }, -]; - -// PLAY 1 TIMES -pub static ASCENDING_TONES: [SequenceEntry; 29] = [ - SequenceEntry { - frequency_hz: 100, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 150, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 200, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 250, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 300, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 350, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 400, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 450, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 500, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 550, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 600, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 650, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 700, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 750, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 800, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 850, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 900, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 950, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1000, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1050, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1100, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1150, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1200, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1250, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1300, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1350, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1400, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1450, - duration_ms: 50, - }, - SequenceEntry { - frequency_hz: 1500, - duration_ms: 1000, - }, -]; - -pub static SEQUENCE_LIST: [(&'static [SequenceEntry], usize); 7] = [ - (&SOUND_8_BIT_GAME_3, 2), - (&SOUND_8_BIT_GAME_4, 0), - (&ASCENDING_TONES, 0), - (&COIN_CHIRP, 0), - (&WAHWAH, 5), - (&DECENDING_TONES, 0), - (&SOUND_8_BIT_GAME_1, 1), - // &TEST_SEQ, -]; diff --git a/ch32v-insert-coin/src/synthesizer.rs b/ch32v-insert-coin/src/synthesizer.rs deleted file mode 100644 index 810336e..0000000 --- a/ch32v-insert-coin/src/synthesizer.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::insert_coin::SimplePwmCore; -use ch32_hal::println; -use ch32_hal::timer::GeneralInstance16bit; -use wavetable_synth::{synthesizer::SimpleWavetableSynthesizer, wavetable::SimpleWavetable}; - -const SQUARE_WAVETABLE: [u8; 2] = [0, 100]; -// const SQUARE_WAVETABLE: [u8; 32] = [ -// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 100, 100, 100, 100, 100, 100, 100, 100, -// 100, 100, 100, 100, 100, 100, 100, -// ]; - -pub struct SynthesizerService { - pub synth: SimpleWavetableSynthesizer>, - pub enabled: bool, - pub need_service: bool, -} - -impl SynthesizerService { - pub fn new(clock_freq_hz: usize) -> Self { - let square_wt = SimpleWavetable::new(&SQUARE_WAVETABLE); - let synth = SimpleWavetableSynthesizer::new(square_wt, clock_freq_hz); - - Self { - synth, - enabled: true, - need_service: false, - } - } - - pub fn tick(&mut self) { - if self.enabled { - self.synth.tick(); - } - } - - pub fn need_service(&self) -> bool { - self.need_service || (self.enabled && self.synth.has_new_output()) - } - - pub fn service(&mut self) -> Option { - self.need_service = false; - if self.enabled { - Some(self.synth.get_output()) - } else { - None - } - } -} - -impl SynthesizerService { - pub fn set_freq(&mut self, freq_hz: usize) { - self.synth.set_freq(freq_hz); - } - - pub fn enable(&mut self) { - self.enabled = true; - self.need_service = true; - // TODO: write the enable function - } - - pub fn disable(&mut self) { - self.enabled = false; - self.need_service = true; - // TODO: write the disable function - } -} diff --git a/ch32v-insert-coin/src/system.rs b/ch32v-insert-coin/src/system.rs deleted file mode 100644 index 484d513..0000000 --- a/ch32v-insert-coin/src/system.rs +++ /dev/null @@ -1,134 +0,0 @@ -use ch32_hal as hal; -use hal::println; - -pub unsafe fn init_gpio_irq(pin: u8, port: u8, rising: bool, falling: bool) { - critical_section::with(|_| { - #[cfg(feature = "enable_print")] - println!("init_gpio_irq {pin}:{port}"); - let exti = &hal::pac::EXTI; - let afio = &hal::pac::AFIO; - - let port = port as u8; - let pin = pin as usize; - - // let b = afio.exticr().read(); - afio.exticr().modify(|w| w.set_exti(pin, port)); - - exti.intenr().modify(|w| w.set_mr(pin, true)); // enable interrupt - exti.rtenr().modify(|w| w.set_tr(pin, rising)); - exti.ftenr().modify(|w| w.set_tr(pin, falling)); - }); -} - -pub fn clear_interrupt(coin_pin: u8, button_pin: u8) -> [bool; 2] { - let mut output = [false, false]; - - let exti = &hal::pac::EXTI; - - let coin_pin = coin_pin as usize; - let button_pin = button_pin as usize; - - exti.intenr().modify(|w| w.set_mr(coin_pin, false)); // disable interrupt - exti.intenr().modify(|w| w.set_mr(button_pin, false)); // disable interrupt - - let bits = exti.intfr().read(); - - // We don't handle or change any EXTI lines above 24. - let bits = bits.0 & 0x00FFFFFF; - #[cfg(feature = "enable_print")] - println!("bits: {bits:08x}"); - - // coin_flag - if (bits & (0x1 << coin_pin)) != 0x0 { - #[cfg(feature = "enable_print")] - println!("coin irq!"); - output[0] = true; - } - - // button_flag - if (bits & (0x1 << button_pin)) != 0x0 { - #[cfg(feature = "enable_print")] - println!("main_btn irq!"); - output[1] = true; - } - - // Clear pending - Clears the EXTI's line pending bits. - exti.intfr().write(|w| w.0 = bits); - - use hal::pac::Interrupt; - unsafe { - qingke::pfic::unpend_interrupt(Interrupt::EXTI7_0 as u8); - }; - - // exti.intenr().modify(|w| w.0 = w.0 & !bits); - exti.intenr().modify(|w| w.set_mr(coin_pin, true)); // enable interrupt - exti.intenr().modify(|w| w.set_mr(button_pin, true)); // enable interrupt - - output -} - -/// enter standby (SLEEPDEEP) mode, with WFE enabled. -/// from CH32V003 reference manual 2.3.1: -/// entry: -/// 1. configure core register control bit: SLEEPDEEP=1 | PDDS = 1 -/// 2. configure external interrupt register to mask all but EXTI7_0 -/// 3. execute WFI or WFE (optionally SEVONPEND) and SLEEPONEXIT -/// * (probably WFI?) -/// exit: -/// 1. any interrupt/event (set in external interrupt register) -pub unsafe fn enter_standby() { - critical_section::with(|_| { - use hal::pac::Interrupt; - use qingke_rt::CoreInterrupt; - - // configure core register control bit (SLEEPDEEP=1 | PDDS=1) - let pfic = &hal::pac::PFIC; - pfic.sctlr().modify(|w| { - // we only want to wake on enabled interrupts - w.set_sevonpend(false); - // we want to enable deep sleep - w.set_sleepdeep(true); - w.set_wfitowfe(false); - w.set_sleeponexit(false); - }); - - // set PDDS=1: - // get current value of PWR_CTLR - let mut reg: u32 = 0x4000_7000; - let mut val: u32 = unsafe { (reg as *mut u32).read_volatile() }; - // modify PDDS - val |= 1 << 1; // PWR_CTLR[1] -> PDDS - unsafe { - (reg as *mut u32).write_volatile(val); - } - - // // disable all exti interrupts - let exti = &hal::pac::EXTI; - // exti.intenr().write(| w| { - // w.0 = 0x00000000; - // // w.set_mr(pin, true); - // // w.set_mr(pin, true); - // }); - - // clear all pending exti interrupts - let bits = 0xFFFFFFFF; - exti.intfr().write(|w| w.0 = bits); - - // enable all exti interrupts - let exti = &hal::pac::EXTI; - exti.intenr().write(|w| { - w.0 = 0x00FFFFFF; - // w.set_mr(pin, true); - // w.set_mr(pin, true); - }); - - unsafe { - qingke::pfic::disable_interrupt(CoreInterrupt::SysTick as u8); - qingke::pfic::enable_interrupt(Interrupt::EXTI7_0 as u8); - } - - // execute WFI - #[cfg(feature = "enable_print")] - println!("WFI CONFIGURED HOPEFULLY"); - }); -} diff --git a/d5a78ca0e0e0591dbd312378abcc82a1/description b/d5a78ca0e0e0591dbd312378abcc82a1/description new file mode 100644 index 0000000..3ca9329 --- /dev/null +++ b/d5a78ca0e0e0591dbd312378abcc82a1/description @@ -0,0 +1,5 @@ +embassy hangs + +noted that embassy hangs on the ch32v003 - even on the templated example. + +for now, we will not use embassy. diff --git a/d5a78ca0e0e0591dbd312378abcc82a1/tags b/d5a78ca0e0e0591dbd312378abcc82a1/tags new file mode 100644 index 0000000..93f371e --- /dev/null +++ b/d5a78ca0e0e0591dbd312378abcc82a1/tags @@ -0,0 +1 @@ +bug diff --git a/e9e2d173359f7a1ef441f8d5cc9af0c1/dependencies/8b98f887e6f027890908edf066debce1 b/e9e2d173359f7a1ef441f8d5cc9af0c1/dependencies/8b98f887e6f027890908edf066debce1 new file mode 100644 index 0000000..e69de29 diff --git a/e9e2d173359f7a1ef441f8d5cc9af0c1/description b/e9e2d173359f7a1ef441f8d5cc9af0c1/description new file mode 100644 index 0000000..67d6a92 --- /dev/null +++ b/e9e2d173359f7a1ef441f8d5cc9af0c1/description @@ -0,0 +1,9 @@ +phase 1: init + +REQUIREMENTS +* PWM DAC +* GPIO input +* interrupts +* PWM outputs + * bit-banged + * hardware diff --git a/e9e2d173359f7a1ef441f8d5cc9af0c1/state b/e9e2d173359f7a1ef441f8d5cc9af0c1/state new file mode 100644 index 0000000..9e3b09d --- /dev/null +++ b/e9e2d173359f7a1ef441f8d5cc9af0c1/state @@ -0,0 +1 @@ +wontdo \ No newline at end of file diff --git a/f00aa7a5559d50ec2b47b76369adde1b/comments/c89eb1f378c37bfd6c9b369e69b1219a/description b/f00aa7a5559d50ec2b47b76369adde1b/comments/c89eb1f378c37bfd6c9b369e69b1219a/description new file mode 100644 index 0000000..57d10ef --- /dev/null +++ b/f00aa7a5559d50ec2b47b76369adde1b/comments/c89eb1f378c37bfd6c9b369e69b1219a/description @@ -0,0 +1 @@ +was able to compile the blinky.rs example out of the ch32v-hal repository diff --git a/f00aa7a5559d50ec2b47b76369adde1b/description b/f00aa7a5559d50ec2b47b76369adde1b/description new file mode 100644 index 0000000..7064c22 --- /dev/null +++ b/f00aa7a5559d50ec2b47b76369adde1b/description @@ -0,0 +1 @@ +compile code diff --git a/f00aa7a5559d50ec2b47b76369adde1b/state b/f00aa7a5559d50ec2b47b76369adde1b/state new file mode 100644 index 0000000..348ebd9 --- /dev/null +++ b/f00aa7a5559d50ec2b47b76369adde1b/state @@ -0,0 +1 @@ +done \ No newline at end of file diff --git a/f00aa7a5559d50ec2b47b76369adde1b/tags b/f00aa7a5559d50ec2b47b76369adde1b/tags new file mode 100644 index 0000000..970be2b --- /dev/null +++ b/f00aa7a5559d50ec2b47b76369adde1b/tags @@ -0,0 +1 @@ +phase-0 diff --git a/f311060330813a8833ab4bc82835aefa/description b/f311060330813a8833ab4bc82835aefa/description new file mode 100644 index 0000000..d2ede00 --- /dev/null +++ b/f311060330813a8833ab4bc82835aefa/description @@ -0,0 +1 @@ +enter deep sleep when adc battery voltage reading is low diff --git a/f311060330813a8833ab4bc82835aefa/tags b/f311060330813a8833ab4bc82835aefa/tags new file mode 100644 index 0000000..a7453f0 --- /dev/null +++ b/f311060330813a8833ab4bc82835aefa/tags @@ -0,0 +1 @@ +feature diff --git a/notes.md b/notes.md deleted file mode 100644 index 65e9ae5..0000000 --- a/notes.md +++ /dev/null @@ -1,97 +0,0 @@ -# ENVIRONMENT -there is a docker image that contains the entire toolchain + flashing utility. first, you need to build the base docker image with the following script located in the ch32v-insert-coin directory: -```shell -$ ./init.sh -``` -once built, you won't need to build this again. for the remainder of your development, you can use the following script to launch the environment shell: -```shell -$ ./launch.sh -``` - -this will launch the docker image and give you a shell which has all of the toolchains and flashing utilities installed. to build the firmware image and flash it to the ch32 (assuming you have a wch-linke attached) run the following from inside the env shell: - -```shell -$ ./build-run.sh -``` -this will build the firmware image, and attempt to upload it to the board using `wlink`. once uploaded, it will attach a serial debugger. - -to exit the serial debugger simply use `ctrl-c`. to exit the environment shell use: - -```shell -$ exit -``` - -# FLASHING -flashing is done using the [`wlink`](https://github.com/ch32-rs/wlink?tab=readme-ov-file#install) utility. `probe-rs` also works, but can be flaky, and does not support SDI prints very well. - -the `wlink` utility will automatically detect the correct chip, but if it doesn't you can specify it with an additional argument. - -`wlink --help` lists all the options to the `wlink` utility. - -## DEVELOPMENT -when building using the rust toolchain, you can simply add the following to your `.cargo/config.toml`: -`runner = "wlink -v flash` - -if you want to monitor prints via SDI, you can use the following instead: -`runner = "wlink -v flash --enable-sdi-print --watch-serial"` - -## STANDALONE -when flashing standalone with the `wlink` utility, you can simply run the following: -`wlink -v flash ` - - -# CH32V MISC NOTES -## SLEEP / DEEP SLEEP -it turns out you can not put the chip into deep sleep and have it wake up correctly until you power cycle it. WHAT THE FUCK. see page 36 of the [qingkev3 processor manual](https://www.wch-ic.com/download/file?id=368) at the bottom of section 6.1 Enter Sleep - - -# EVAL BOARD NOTES -## PINOUT -WCHLinkE SWDIO -> PD1 - - - -# AUDIO NOTES -## LIMITS -we have ~9-10kB of space remaining on the chip. -i can likely squeeze out _maybe_ another kB by dropping every print, but -that appears to cause some lockup, i think because the SDI peripheral is -trying to attach, but unable to. - -for how things sit currently, we have the following (conservative) limits -to fit within 9kB: - -16ksps, 4b depth -> 64kbps -> 1.125s -8ksps, 4b depth -> 32kbps -> 2.25s -6ksps, 4b depth -> 24kbps -> 3.0s -4ksps, 4b depth -> 16kbps -> 4.5s - -in reality, the numbers i have seen are a little smaller than this, likely due -to compiler optimizations when the dac is unloaded / there's no audio. - -a 16ksps file has an _experimental_ max of 0.75s. applying that offset -everywhere, we get empirical limits of: - -16ksps, 4b depth: 0.75s -8ksps, 4b depth: 1.875s -6ksps, 4b depth: 2.625s -4ksps, 4b depth: 4.225s - -## FFMPEG -use the following command to convert an input .wav to a raw mono pcm_u8 with 8ksps: -```shell -ffmpeg -i input.wav -f u8 -c:a pcm_u8 -ar 8000 -ac 1 output.raw -``` - - -# PINOUTS -LED0: PC3 -LED1: PD2 -DAC: PC4 -COIN SWITCH: PC2 -BUTTON SWITCH: PD6 -ADC: PD4 -GPIO: any remaining pin - -## FORBIDDEN: -PD1