From 72b19555dcdfdef36c47153b8dbdbb1edc6860bb Mon Sep 17 00:00:00 2001 From: Ayke van Laethem Date: Wed, 30 Apr 2025 14:13:04 +0200 Subject: [PATCH] machine: add simulated PWM/timer peripherals I will soon use these as part of the TinyGo tour, to explain the PWM peripherals on common chips. --- src/machine/machine_atsamd21_simulator.go | 45 +++++++++++ src/machine/machine_generic.go | 97 +++++++++++++++++++++++ src/machine/machine_nrf52840_simulator.go | 60 ++++++++++++++ src/machine/machine_rp2040_simulator.go | 96 ++++++++++++++++++++++ 4 files changed, 298 insertions(+) create mode 100644 src/machine/machine_atsamd21_simulator.go create mode 100644 src/machine/machine_nrf52840_simulator.go create mode 100644 src/machine/machine_rp2040_simulator.go diff --git a/src/machine/machine_atsamd21_simulator.go b/src/machine/machine_atsamd21_simulator.go new file mode 100644 index 000000000..4a0310b99 --- /dev/null +++ b/src/machine/machine_atsamd21_simulator.go @@ -0,0 +1,45 @@ +//go:build !baremetal && (gemma_m0 || qtpy || trinket_m0 || arduino_mkr1000 || arduino_mkrwifi1010 || arduino_nano33 || arduino_zero || circuitplay_express || feather_m0_express || feather_m0 || itsybitsy_m0 || p1am_100 || xiao) + +// Simulated atsamd21 chips. + +package machine + +// The timer channels/pins match the hardware, and encode the same information +// as pinTimerMapping but in a more generic (less efficient) way. + +var TCC0 = timerType{ + instance: 0, + frequency: 48e6, + bits: 24, + prescalers: []int{1, 2, 4, 8, 16, 64, 256, 1024}, + channelPins: [][]Pin{ + {PA04, PA08, PB10, PA14, PB16, PA22, PB30}, // channel 0 + {PA05, PA09, PB11, PA15, PB17, PA23, PB31}, // channel 1 + {PA10, PB12, PA12, PA16, PA18, PA20}, // channel 2 + {PA11, PB13, PA13, PA17, PA19, PA21}, // channel 3 + }, +} + +var TCC1 = timerType{ + instance: 1, + frequency: 48e6, + bits: 24, + prescalers: []int{1, 2, 4, 8, 16, 64, 256, 1024}, + channelPins: [][]Pin{ + {PA06, PA10, PA30}, // channel 0 + {PA07, PA11, PA31}, // channel 1 + {PA08, PA24, PB30}, // channel 2 + {PA09, PA25, PB31}, // channel 3 + }, +} + +var TCC2 = timerType{ + instance: 2, + frequency: 48e6, + bits: 16, + prescalers: []int{1, 2, 4, 8, 16, 64, 256, 1024}, + channelPins: [][]Pin{ + {PA00, PA12, PA16}, // channel 0 + {PA01, PA13, PA17}, // channel 1 + }, +} diff --git a/src/machine/machine_generic.go b/src/machine/machine_generic.go index 8bfa097f0..20bded88a 100644 --- a/src/machine/machine_generic.go +++ b/src/machine/machine_generic.go @@ -48,6 +48,103 @@ func gpioSet(pin Pin, value bool) //export __tinygo_gpio_get func gpioGet(pin Pin) bool +// Generic PWM/timer peripheral. Properties can be configured depending on the +// hardware. +type timerType struct { + // Static properties. + instance int32 + frequency uint64 + bits int + prescalers []int + channelPins [][]Pin + + // Configured 'top' value. + top uint32 +} + +// Configure the PWM/timer peripheral. +func (t *timerType) Configure(config PWMConfig) error { + // Note: for very large period values, this multiplication will overflow. + top := config.Period * t.frequency / 1e9 + if config.Period == 0 { + top = 0xffff // default for LEDs + } + + // The maximum value that can be stored with the given number of bits in + // this timer. + maxTop := uint64(1)<