: ExpressibleByStringInterpolation {
+ typealias StringInterpolation = StreamingInterpolation
+
+ init(printer: P, stringInterpolation: StreamingInterpolation
) {
+ self.interpolation = stringInterpolation
+ }
+
+ init(stringInterpolation: StreamingInterpolation
) {
+ self.interpolation = stringInterpolation
+ }
+
+ init(stringLiteral value: StaticString) {
+ self.interpolation = StreamingInterpolation(
+ literalCapacity: 0, interpolationCount: 0)
+ self.interpolation.appendLiteral(value)
+ }
+
+ var printer: P { interpolation.printer }
+
+ private var interpolation: StreamingInterpolation
+}
diff --git a/harmony/Sources/Application/Main.swift b/harmony/Sources/Application/Main.swift
new file mode 100644
index 00000000..23eb9897
--- /dev/null
+++ b/harmony/Sources/Application/Main.swift
@@ -0,0 +1,387 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// swift-format-ignore: AlwaysUseLowerCamelCase, NeverForceUnwrap
+
+struct A2DPStreamEndpoint {
+ var a2dp_local_seid: UInt8 = 0
+ var media_sbc_codec_configuration: (UInt8, UInt8, UInt8, UInt8) = (0, 0, 0, 0)
+}
+
+var hci_event_callback_registration = btstack_packet_callback_registration_t()
+var stream_endpoint = A2DPStreamEndpoint()
+
+// we support all configurations with bitpool 2-53
+var media_sbc_codec_capabilities: (UInt8, UInt8, UInt8, UInt8) = (
+ //(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
+ 0xFF,
+ //(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
+ 0xFF,
+ 2, 53
+)
+
+// FIXME: use Vector
+let sdp_avdtp_sink_service_buffer = UnsafeMutableRawBufferPointer.allocate(
+ byteCount: 150,
+ alignment: MemoryLayout.alignment)
+// FIXME: use Vector
+let sdp_avrcp_target_service_buffer = UnsafeMutableRawBufferPointer.allocate(
+ byteCount: 150,
+ alignment: MemoryLayout.alignment)
+// FIXME: use Vector
+let sdp_avrcp_controller_service_buffer =
+ UnsafeMutableRawBufferPointer.allocate(
+ byteCount: 200,
+ alignment: MemoryLayout.alignment)
+// FIXME: use Vector
+let device_id_sdp_service_buffer = UnsafeMutableRawBufferPointer.allocate(
+ byteCount: 100,
+ alignment: MemoryLayout.alignment)
+
+// FIXME: use `Vector`
+func buttonCallback(pin: UInt32, event: UInt32) {
+ guard event & UInt32(GPIO_IRQ_EDGE_FALL.rawValue) != 0 else { return }
+ Application.shared.buttonPressed(pin: pin)
+}
+
+let BUFFER_SAMPLE_CAPACITY = 512
+
+
+let LED_STRIP_LED_COUNT = 20
+
+let MUTE_BUTTON_PIN: UInt32 = 6
+let ROTARY_ENCODER_A_PIN : UInt32 = 7
+let ROTARY_ENCODER_B_PIN: UInt32 = 8
+let PLAY_PAUSE_BUTTON_PIN: UInt32 = 9
+let PREVIOUS_BUTTON_PIN: UInt32 = 10
+let NEXT_BUTTON_PIN: UInt32 = 11
+let LED_STRIP_PIN: UInt32 = 17
+let EM_DRIVE_PIN: UInt32 = 18
+
+let WIRELESS_LED_PIN = UInt32(CYW43_WL_GPIO_LED_PIN)
+
+struct Application: ~Copyable {
+ var audioEngine = AudioEngine()
+
+ var audioAnalyzer = AudioAnalyzer()
+
+ let wirelessLedBlinkPeriodMs: UInt32 = 1000
+ var wirelessLedBlinkTimer = btstack_timer_source_t()
+ var wirelessLedBlinkState = false
+
+ let ledStripUpdatePeriodMs: UInt32 = 1000
+ var ledStripUpdateTimer = btstack_timer_source_t()
+ var ledStrip = LEDStrip(
+ dataPin: LED_STRIP_PIN,
+ ledCount: LED_STRIP_LED_COUNT,
+ pio: 0,
+ pioSm: 1)
+
+ let volumeKnobSamplerPeriodMs: UInt32 = 100
+ var volumeKnobSamplerTimer = btstack_timer_source_t()
+ var volumeKnob = QuadratureEncoder(
+ pinA: ROTARY_ENCODER_A_PIN,
+ pinB: ROTARY_ENCODER_B_PIN,
+ pio: 1,
+ pioSm: 0)
+
+ var previousPressTimes = ButtonTimes()
+
+ var muteButton = Button(
+ pin: MUTE_BUTTON_PIN,
+ onPress: buttonCallback)
+ var nextButton = Button(
+ pin: NEXT_BUTTON_PIN,
+ onPress: buttonCallback)
+ var playPauseButton = Button(
+ pin: PLAY_PAUSE_BUTTON_PIN,
+ onPress: buttonCallback)
+ var previousButton = Button(
+ pin: PREVIOUS_BUTTON_PIN,
+ onPress: buttonCallback)
+
+ mutating func run() {
+ stdio_init_all()
+ i2c_init()
+
+ multicore_launch_core1 {
+ log("core1_main")
+ Application.shared.audioAnalyzer.run()
+ }
+
+ log("Hello!")
+ log("sys clock running at \(clock_get_hz(clk_sys)) Hz")
+ log("Initializing cyw43_driver")
+ precondition(cyw43_arch_init() == 0, "cyw43_arch_init failed")
+ wirelessLedBlink(count: 2)
+
+ gpio_init(EM_DRIVE_PIN)
+ gpio_set_dir(EM_DRIVE_PIN, true)
+
+ var sdp = ServiceDiscoveryProtocol()
+ _setup_demo(&sdp)
+
+
+ // turn on!
+ log("Starting BTstack ...")
+ hci_power_control(HCI_POWER_ON)
+ wirelessLedBlink(count: 2)
+ log("[main] Started, starting btstack run loop")
+
+ btstack_run_loop_set_timer_handler(&self.volumeKnobSamplerTimer) { timer in
+ guard let timer else { return }
+ Application.shared.volumeKnobSamplerHandler(&timer.pointee)
+ }
+ btstack_run_loop_set_timer(&self.volumeKnobSamplerTimer, volumeKnobSamplerPeriodMs)
+ btstack_run_loop_add_timer(&self.volumeKnobSamplerTimer)
+
+ btstack_run_loop_set_timer_handler(&self.ledStripUpdateTimer) { timer in
+ guard let timer else { return }
+ Application.shared.ledStripUpdateHandler(&timer.pointee)
+ }
+ btstack_run_loop_set_timer(&self.ledStripUpdateTimer, ledStripUpdatePeriodMs)
+ btstack_run_loop_add_timer(&self.ledStripUpdateTimer)
+
+ btstack_run_loop_set_timer_handler(&self.wirelessLedBlinkTimer) { timer in
+ guard let timer else { return }
+ Application.shared.wirelessLedBlinkHandler(&timer.pointee)
+ }
+ btstack_run_loop_set_timer(&self.wirelessLedBlinkTimer, wirelessLedBlinkPeriodMs)
+ btstack_run_loop_add_timer(&self.wirelessLedBlinkTimer)
+
+
+ btstack_run_loop_execute() // btstack_run_loop_execute never returns
+ _ = sdp // make sure SDP lives until the runloop exits
+ }
+}
+
+// Timer handlers
+extension Application {
+ mutating func volumeKnobSamplerHandler(_ timer: inout btstack_timer_source_t) {
+ let scaleFactor: Int32 = 5
+ audioEngine.adjustVolume(by: Application.shared.volumeKnob.delta() * scaleFactor)
+ btstack_run_loop_set_timer(&timer, volumeKnobSamplerPeriodMs)
+ btstack_run_loop_add_timer(&timer)
+ }
+
+ mutating func ledStripUpdateHandler(_ timer: inout btstack_timer_source_t) {
+ ledStrip.setColor(
+ red: .random(in: 0...255),
+ green: .random(in: 0...255),
+ blue: .random(in: 0...255))
+ btstack_run_loop_set_timer(&timer, ledStripUpdatePeriodMs)
+ btstack_run_loop_add_timer(&timer)
+ }
+
+ mutating func wirelessLedBlinkHandler(_ timer: inout btstack_timer_source_t) {
+ self.wirelessLedBlinkState.toggle()
+ cyw43_arch_gpio_put(WIRELESS_LED_PIN, self.wirelessLedBlinkState)
+ btstack_run_loop_set_timer(&timer, wirelessLedBlinkPeriodMs)
+ btstack_run_loop_add_timer(&timer)
+ }
+}
+
+// Button press callbacks
+extension Application {
+ // FIXME: use `time_us_64`
+ // This is a particularly large debounce time
+ static let buttonDebounceTimeMs = 150
+ mutating func buttonPressed(pin: UInt32) {
+ let currentTime = to_ms_since_boot(get_absolute_time())
+ guard currentTime - previousPressTimes[pin] > Self.buttonDebounceTimeMs else {
+ log("soft debounce \(pin)")
+ return
+ }
+ previousPressTimes[pin] = currentTime
+
+ switch pin {
+ case MUTE_BUTTON_PIN:
+ self.toggleMute()
+ case NEXT_BUTTON_PIN:
+ self.nextTrack()
+ case PLAY_PAUSE_BUTTON_PIN:
+ self.playPauseTrack()
+ case PREVIOUS_BUTTON_PIN:
+ self.previousTrack()
+ default:
+ // ignore
+ break
+ }
+ }
+
+ mutating func toggleMute() {
+ self.audioEngine.toggleMute()
+ }
+
+ mutating func nextTrack() {
+ log("avrcp_controller_forward")
+ avrcp_controller_forward(avrcp_connection.avrcp_cid)
+ }
+
+ mutating func playPauseTrack() {
+ // FIXME: this state management is almost certainly wrong
+ if audioEngine.running {
+ log("avrcp_controller_stop")
+ avrcp_controller_pause(avrcp_connection.avrcp_cid)
+ } else {
+ log("avrcp_controller_play")
+ avrcp_controller_play(avrcp_connection.avrcp_cid)
+ }
+ }
+
+ mutating func previousTrack() {
+ log("avrcp_controller_backward")
+ avrcp_controller_backward(avrcp_connection.avrcp_cid)
+ }
+}
+
+extension Application {
+ func wirelessLedBlink(count: UInt32) {
+ for _ in 0.. Int32 {
+ let value = quadrature_encoder_get_count(self.pioHw, self.pioSm)
+ self.previousValue = value
+ return value
+ }
+
+ mutating func delta() -> Int32 {
+ let value = quadrature_encoder_get_count(self.pioHw, self.pioSm)
+ // NOTE: Thanks to two's complement arithmetic `delta`` will always be
+ // correct even when `value`` wraps around `Int32.max` / `Int32.min`.
+ let delta = value &- self.previousValue
+ self.previousValue = value
+ return delta
+ }
+}
diff --git a/harmony/Sources/Application/Stubs.swift b/harmony/Sources/Application/Stubs.swift
new file mode 100644
index 00000000..b6e8deb0
--- /dev/null
+++ b/harmony/Sources/Application/Stubs.swift
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// Embedded Swift currently requires posix_memalign, but the C libraries in the
+// Pico SDK do not provide it. Let's implement it and forward the calls to
+// aligned_alloc(3).
+@_cdecl("posix_memalign")
+public func posix_memalign(
+ memptr: UnsafeMutablePointer,
+ alignment: size_t,
+ size: size_t
+) -> Int32 {
+ if let allocation = aligned_alloc(alignment, size) {
+ memptr.pointee = allocation
+ return 0
+ }
+ return _errno()
+}
+
+// FIXME: document
+@_cdecl("swift_isEscapingClosureAtFileLocation")
+func swift_isEscapingClosureAtFileLocation(
+ object: UnsafeRawPointer,
+ filename: UnsafePointer,
+ filenameLength: Int32,
+ line: Int32,
+ column: Int32,
+ type: UInt
+) -> Bool {
+ false
+}
diff --git a/harmony/Sources/Audio/AudioAnalyzer.swift b/harmony/Sources/Audio/AudioAnalyzer.swift
new file mode 100644
index 00000000..1939fd3f
--- /dev/null
+++ b/harmony/Sources/Audio/AudioAnalyzer.swift
@@ -0,0 +1,94 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+struct AnalyzedAudioBuffer: ~Copyable {
+ var enableMagnet: Bool
+ var buffer: AudioBuffer
+}
+
+struct AudioAnalyzer: ~Copyable {
+ // FIXME: add soft limit for time magnet can be enabled
+
+ var fft_instance: arm_rfft_instance_q15
+ // Used for both sample input and fft magnitude output
+ var dataBuffer0: UnsafeMutableBufferPointer
+ // Used for fft output
+ var dataBuffer1: UnsafeMutableBufferPointer
+
+ init() {
+ let audioBufferCapacity = BUFFER_SAMPLE_CAPACITY
+ let fftOutputBufferCapacity = BUFFER_SAMPLE_CAPACITY * 2 // real + complex
+
+ self.fft_instance = arm_rfft_instance_q15()
+ self.dataBuffer0 = .allocate(capacity: audioBufferCapacity)
+ self.dataBuffer1 = .allocate(capacity: fftOutputBufferCapacity)
+ // IMPORTANT: `bitReverseFlag` must be set. I don't understand why based on
+ // the documentation
+ arm_rfft_init_q15(&fft_instance, UInt32(audioBufferCapacity), 0, 1)
+ }
+
+ deinit {
+ self.dataBuffer1.deallocate()
+ self.dataBuffer0.deallocate()
+ }
+
+ mutating func run() {
+ while true {
+ guard let buffer = Application.shared.audioEngine.buffers.popFullBuffer() else { continue }
+
+ /// Copy data from buffer to dataBuffer0 (because the fft will modify the data)
+ precondition(self.dataBuffer0.update(from: buffer.storage).index == self.dataBuffer0.count)
+ // Perform the fft using the data in dataBuffer0 and store the result in dataBuffer1
+ arm_rfft_q15(&self.fft_instance, self.dataBuffer0.baseAddress, self.dataBuffer1.baseAddress)
+ // Calculate the magnitude of the fft output in dataBuffer1 and store the result in dataBuffer0
+ arm_cmplx_mag_q15(self.dataBuffer1.baseAddress, self.dataBuffer0.baseAddress, UInt32(self.dataBuffer0.count))
+
+ // NOTE: This is probably wrong becasue buffer.storage is stereo data
+
+ // Given we take an fft of audio data at 44100 Hz with a window of 512
+ // samples, each output bin of the fft represents a 172 Hz range
+ // (44100 Hz / 2 / 512 = ~172Hz)
+
+ // 1 Khz
+ let lowend =
+ self.dataBuffer0[00] +
+ self.dataBuffer0[01] +
+ self.dataBuffer0[02] +
+ self.dataBuffer0[03] +
+ self.dataBuffer0[04] +
+ self.dataBuffer0[05] +
+ self.dataBuffer0[06] +
+ self.dataBuffer0[07] +
+ self.dataBuffer0[08] +
+ self.dataBuffer0[09] +
+ self.dataBuffer0[10] +
+ self.dataBuffer0[10] +
+ self.dataBuffer0[11] +
+ self.dataBuffer0[12] +
+ self.dataBuffer0[13] +
+ self.dataBuffer0[14] +
+ self.dataBuffer0[15] +
+ self.dataBuffer0[16] +
+ self.dataBuffer0[17] +
+ self.dataBuffer0[18] +
+ self.dataBuffer0[19]
+
+
+
+ let avg = lowend / 20
+
+ let analyzedBuffer = AnalyzedAudioBuffer(
+ enableMagnet: avg > (1 << 8),
+ buffer: buffer)
+ Application.shared.audioEngine.buffers.pushAnalyzedBuffer(analyzedBuffer)
+ }
+ }
+}
diff --git a/harmony/Sources/Audio/AudioBuffer.swift b/harmony/Sources/Audio/AudioBuffer.swift
new file mode 100644
index 00000000..49431b52
--- /dev/null
+++ b/harmony/Sources/Audio/AudioBuffer.swift
@@ -0,0 +1,28 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+struct AudioBuffer: ~Copyable {
+ // FIXME: Raw
+ var storage: UnsafeMutableBufferPointer
+ var capacity: Int { self.storage.count }
+ var count: Int
+
+ init(capacity: Int) {
+ self.storage = .allocate(capacity: capacity)
+ self.storage.initialize(repeating: 0)
+ // FIXME: don't assume filled.
+ self.count = capacity
+ }
+
+ deinit {
+ self.storage.deallocate()
+ }
+}
diff --git a/harmony/Sources/Audio/AudioBufferTransport.swift b/harmony/Sources/Audio/AudioBufferTransport.swift
new file mode 100644
index 00000000..907637d3
--- /dev/null
+++ b/harmony/Sources/Audio/AudioBufferTransport.swift
@@ -0,0 +1,54 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+struct AudioBufferTransport: ~Copyable {
+ var emptyBuffers: Ring
+ var fullBuffers: Ring
+ var analyzedBuffers: Ring
+
+ init(bufferCount: Int, bufferCapacity: Int) {
+ // Ring buffer needs one extra slot to distinguish between empty and full.
+ self.emptyBuffers = Ring(capacity: bufferCount + 1)
+ self.fullBuffers = Ring(capacity: bufferCount + 1)
+ self.analyzedBuffers = Ring(capacity: bufferCount + 1)
+
+ for _ in 0.. AudioBuffer? {
+ self.emptyBuffers.pop()
+ }
+
+ mutating func pushFullBuffer(_ buffer: consuming AudioBuffer) {
+ self.fullBuffers.push(buffer)
+ }
+
+ mutating func popFullBuffer() -> AudioBuffer? {
+ self.fullBuffers.pop()
+ }
+
+ mutating func pushAnalyzedBuffer(_ buffer: consuming AnalyzedAudioBuffer) {
+ self.analyzedBuffers.push(buffer)
+ }
+
+ mutating func popAnalyzedBuffer() -> AnalyzedAudioBuffer? {
+ self.analyzedBuffers.pop()
+ }
+}
diff --git a/harmony/Sources/Audio/AudioEngine.swift b/harmony/Sources/Audio/AudioEngine.swift
new file mode 100644
index 00000000..660b2367
--- /dev/null
+++ b/harmony/Sources/Audio/AudioEngine.swift
@@ -0,0 +1,120 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+struct AudioEngine: ~Copyable {
+ var running: Bool
+ var mute: Bool
+ var volume: UInt8
+ var rawVolume: UInt8
+
+ var audio_pico: AudioPico
+ var audio_i2s: AudioI2S
+ var buffers: AudioBufferTransport
+ var amp: MAX9744
+
+ init() {
+ self.running = false
+ self.mute = false
+ self.volume = 0
+ self.rawVolume = 30
+
+ self.audio_pico = AudioPico()
+ self.audio_i2s = AudioI2S(
+ data_pin: PICO_AUDIO_I2S_DATA_PIN,
+ clock_pin_base: PICO_AUDIO_I2S_CLOCK_PIN_BASE,
+ pio: 0,
+ pio_sm: 0,
+ // FIXME: Dont claim on each `media_processing_init`??
+ dma_channel: UInt32(dma_claim_unused_channel(true)))
+ self.buffers = AudioBufferTransport(bufferCount: 8, bufferCapacity: BUFFER_SAMPLE_CAPACITY)
+ self.amp = MAX9744(i2c: i2c0_inst)
+
+ self.set(volume: 0)
+ }
+}
+
+extension AudioEngine {
+ mutating func `init`(_ configuration: MediaCodecConfigurationSBC) {
+ log(#function)
+ SBCDecoder.configure(mode: SBC_MODE_STANDARD)
+
+ // setup audio playback
+ // FIXME: update channel count in resampler
+ // FIXME: update output sample-rate
+
+ self.audio_i2s.update_pio_frequency(
+ UInt32(configuration.sampling_frequency))
+
+ self.running = false
+ }
+
+ mutating func toggleMute() {
+ self.mute.toggle()
+ if self.mute {
+ self.amp.set(rawVolume: 0)
+ } else {
+ self.amp.set(rawVolume: rawVolume)
+ }
+ }
+
+ mutating func set(volume: UInt8) {
+ guard self.volume != volume else { return }
+ self.volume = volume
+ // FIXME:
+ avrcp_target_volume_changed(avrcp_connection.avrcp_cid, volume >> 1)
+
+ // Map volume (0-255) to gain (0-63)
+ let rawVolume = UInt8((UInt32(volume) * 63) / 255)
+ guard self.rawVolume != rawVolume else { return }
+ self.rawVolume = rawVolume
+
+ guard !self.mute else { return }
+ self.amp.set(rawVolume: rawVolume)
+ }
+
+ mutating func adjustVolume(by delta: Int32) {
+ guard delta != 0 else { return }
+ let volume = Int32(self.volume) + delta
+ let clamped = UInt8(clamping: volume)
+ log("Adjust volume by \(delta) to \(clamped)")
+ self.set(volume: clamped)
+ }
+
+ mutating func start() {
+ guard !self.running else { return }
+ guard self.audio_pico.sbc_frames.count >= OPTIMAL_FRAMES_MIN else { return }
+ log(#function)
+ // start audio playback
+ self.audio_pico.start_stream()
+ self.audio_i2s.enable(true)
+ self.running = true
+ }
+
+ mutating func pause() {
+ guard self.running else { return }
+ log(#function)
+ self.close()
+ }
+
+ mutating func close() {
+ log(#function)
+
+ // stop audio playback
+ self.running = false
+ self.audio_pico.stop_stream()
+ self.audio_i2s.enable(false)
+
+ // discard pending data
+ self.audio_pico.decoded_audio.clear()
+ self.audio_pico.sbc_frame_size = 0
+ self.audio_pico.sbc_frames.clear()
+ }
+}
diff --git a/harmony/Sources/Audio/AudioI2S.swift b/harmony/Sources/Audio/AudioI2S.swift
new file mode 100644
index 00000000..52e4b96d
--- /dev/null
+++ b/harmony/Sources/Audio/AudioI2S.swift
@@ -0,0 +1,174 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+var zero: UInt32 = 0
+
+// FIXME: #define __time_critical_func(func_name) __not_in_flash_func(func_name)
+// irq handler for DMA
+@_cdecl("audio_i2s_dma_irq_handler")
+func audio_i2s_dma_irq_handler() {
+ Application.shared.audioEngine.audio_i2s.handle_dma_irq()
+}
+
+struct AudioI2S: ~Copyable {
+ var enabled: Bool
+ var freq: UInt32
+ var playing_buffer: AudioBuffer?
+
+ var pio: UInt32
+ var pio_sm: UInt32
+ var dma_channel: UInt32
+ var pioHw: PIO
+
+ init(
+ data_pin: UInt32,
+ clock_pin_base: UInt32,
+ pio: UInt32,
+ pio_sm: UInt32,
+ // FIXME: dma_channel is already claimed
+ dma_channel: UInt32,
+ ) {
+ self.enabled = false
+ self.freq = 0
+
+ self.pio = pio
+ self.pio_sm = pio_sm
+ self.dma_channel = dma_channel
+
+ let gpioFunc: gpio_function_rp2040
+ switch pio {
+ case 0:
+ self.pioHw = _pio0()
+ gpioFunc = GPIO_FUNC_PIO0
+ case 1:
+ self.pioHw = _pio1()
+ gpioFunc = GPIO_FUNC_PIO1
+ default:
+ fatalError("Invalid PIO index")
+ }
+
+ gpio_set_function(data_pin, gpioFunc)
+ gpio_set_function(clock_pin_base, gpioFunc)
+ gpio_set_function(clock_pin_base + 1, gpioFunc)
+
+ pio_sm_claim(self.pioHw, self.pio_sm)
+
+ let offset = withUnsafePointer(to: audio_i2s_program) {
+ pio_add_program(self.pioHw, $0)
+ }
+
+ audio_i2s_program_init(
+ self.pioHw, self.pio_sm, UInt32(offset), data_pin, clock_pin_base)
+
+ __mem_fence_release()
+
+ var dma_config = dma_channel_get_default_config(dma_channel)
+
+ channel_config_set_dreq(
+ &dma_config,
+ UInt32(DREQ_PIO0_TX0.rawValue) + self.pio_sm)
+
+ channel_config_set_transfer_data_size(&dma_config, i2s_dma_configure_size)
+ dma_channel_configure(
+ dma_channel,
+ &dma_config,
+ // FIXME: .advanced(by: Int(self.pio_sm))
+ self.pioHw.pointer(to: \.txf), // dest
+ nil, // src
+ 0, // count
+ false) // trigger
+
+ irq_add_shared_handler(
+ UInt32(DMA_IRQ_0.rawValue) + PICO_AUDIO_I2S_DMA_IRQ,
+ audio_i2s_dma_irq_handler,
+ UInt8(PICO_SHARED_IRQ_HANDLER_DEFAULT_ORDER_PRIORITY))
+ dma_irqn_set_channel_enabled(PICO_AUDIO_I2S_DMA_IRQ, dma_channel, true)
+ }
+
+ mutating func enable(_ enable: Bool) {
+ guard self.enabled != enable else { return }
+ self.enabled = enable
+
+ irq_set_enabled(UInt32(DMA_IRQ_0.rawValue) + PICO_AUDIO_I2S_DMA_IRQ, enable)
+
+ if enable {
+ self.audio_start_dma_transfer()
+ } else {
+ // if there was a buffer in flight, it will not be freed by DMA IRQ,
+ // let's do it manually
+ self.audio_finish_dma_transfer()
+ gpio_put(EM_DRIVE_PIN, false)
+ }
+
+ pio_sm_set_enabled(self.pioHw, self.pio_sm, enable)
+ }
+
+ mutating func update_pio_frequency(_ sample_freq: UInt32?) {
+ guard let sample_freq = sample_freq else { return }
+ guard sample_freq != self.freq else { return }
+
+ let system_clock_frequency = clock_get_hz(clk_sys)
+ precondition(system_clock_frequency < 0x4000_0000)
+ // avoid arithmetic overflow
+ let divider = system_clock_frequency * 4 / sample_freq
+ precondition(divider < 0x1000000)
+ pio_sm_set_clkdiv_int_frac(
+ self.pioHw, self.pio_sm, UInt16(divider >> 8), UInt8(divider & 0xff))
+ self.freq = sample_freq
+ }
+
+ mutating func handle_dma_irq() {
+ guard dma_irqn_get_channel_status(PICO_AUDIO_I2S_DMA_IRQ, self.dma_channel)
+ else { return }
+ dma_irqn_acknowledge_channel(PICO_AUDIO_I2S_DMA_IRQ, self.dma_channel)
+
+ // free the buffer we just finished
+ self.audio_finish_dma_transfer()
+ self.audio_start_dma_transfer()
+ }
+
+ mutating func audio_start_dma_transfer() {
+ precondition(self.playing_buffer == nil)
+
+ // FIXME: support dynamic frequency shifting
+
+ if let ab = Application.shared.audioEngine.buffers.popAnalyzedBuffer() {
+ gpio_put(EM_DRIVE_PIN, ab.enableMagnet)
+
+ let ab = ab.buffer
+ let buf = UnsafeMutableRawBufferPointer(ab.storage)
+ self.playing_buffer = consume ab
+
+ var c = dma_get_channel_config(self.dma_channel)
+ channel_config_set_read_increment(&c, true)
+ dma_channel_set_config(self.dma_channel, &c, false)
+ dma_channel_transfer_from_buffer_now(
+ self.dma_channel,
+ buf.baseAddress,
+ // FIXME: using capacity instead of ab count
+ UInt32(buf.count) / 4)
+ } else {
+ gpio_put(EM_DRIVE_PIN, false)
+ log("buffer pool low")
+ // just play some silence
+ var c = dma_get_channel_config(self.dma_channel)
+ channel_config_set_read_increment(&c, false)
+ dma_channel_set_config(self.dma_channel, &c, false)
+ dma_channel_transfer_from_buffer_now(
+ self.dma_channel, &zero, PICO_AUDIO_I2S_SILENCE_BUFFER_SAMPLE_LENGTH)
+ }
+ }
+
+ mutating func audio_finish_dma_transfer() {
+ guard let playingBuffer = self.playing_buffer.take() else { return }
+ Application.shared.audioEngine.buffers.pushEmptyBuffer(playingBuffer)
+ }
+}
diff --git a/harmony/Sources/Audio/AudioPico.swift b/harmony/Sources/Audio/AudioPico.swift
new file mode 100644
index 00000000..ef540daf
--- /dev/null
+++ b/harmony/Sources/Audio/AudioPico.swift
@@ -0,0 +1,181 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+extension UnsafeMutableBufferPointer where Element: ~Copyable {
+ func split(at index: Self.Index) -> (Self, Self) {
+ (self.extracting(..
+ var sbc_frames: RingBuffer
+ var sbc_frames_in_buffer: Int {
+ guard sbc_frame_size > 0 else { return 0 }
+ return self.sbc_frames.count / self.sbc_frame_size
+ }
+
+ // overflow buffer for not fully used sbc frames, with additional frames for resampling
+ let decoded_audio_buffer: UnsafeMutableBufferPointer
+ var decoded_audio: RingBuffer
+
+ init() {
+ let CHANNELS_PER_FRAME = 2
+ let capacity = (128 + 16) * CHANNELS_PER_FRAME
+
+ self.fill_timer = btstack_timer_source_t()
+ self.resampler = Resampler(channels: CHANNELS_PER_FRAME)
+
+ self.sbc_frame_size = 0
+ self.sbc_frame_buffer = UnsafeMutableBufferPointer.allocate(
+ capacity: MAX_SBC_FRAME_SIZE)
+ self.sbc_frames = RingBuffer(
+ capacity: (OPTIMAL_FRAMES_MAX + ADDITIONAL_FRAMES) * MAX_SBC_FRAME_SIZE)
+
+ self.decoded_audio_buffer = .allocate(capacity: capacity)
+ self.decoded_audio = RingBuffer(capacity: capacity)
+ }
+
+ mutating func enqueue(sbc_frames: UnsafeMutableBufferPointer, frame_size: Int)
+ {
+ self.sbc_frame_size = frame_size
+ if !self.sbc_frames.write(contentsOf: sbc_frames) {
+ log("Error: SBC frame buffer overflow")
+ }
+ self.updateResamplingFactor()
+ }
+
+ mutating func updateResamplingFactor() {
+ let nominal_factor: UInt32 = 0x10000
+ let compensation: UInt32 = 0x00100
+
+ let resampling_factor =
+ switch self.sbc_frames_in_buffer {
+ case ..) {
+ // called from lower-layer but guaranteed to be on main thread
+ guard self.sbc_frame_size != 0 else {
+ log("Frame size is 0")
+ buffer.update(repeating: 0)
+ return
+ }
+
+ // first fill from resampled audio
+ let samplesReadCount = self.decoded_audio.read(into: buffer)
+ var buffer = buffer.extracting(samplesReadCount...)
+
+ // then start decoding sbc frames into the buffer
+ while buffer.count > 0, self.sbc_frames.count > self.sbc_frame_size {
+ // decode frame
+ let elementsRead = self.sbc_frames.read(
+ into: self.sbc_frame_buffer, count: self.sbc_frame_size)
+ precondition(
+ elementsRead == self.sbc_frame_size, "sbc frame size mismatch")
+
+ SBCDecoder.decode_signed_16(
+ mode: SBC_MODE_STANDARD,
+ packet_status_flag: 0,
+ buffer: UnsafeRawBufferPointer(self.sbc_frame_buffer)
+ ) { samples, num_channels, sample_rate in
+ precondition(num_channels == 2, "must be stereo")
+
+ // Resample audio to compensate for the amount of buffered SBC frames
+ let samples = self.resampler.resample(
+ samples: .init(samples),
+ usingTemporaryBuffer: self.decoded_audio_buffer)
+
+ // Store samples in buffer first and excess in the ring buffer.
+ let (samples_to_copy, samples_to_store) = samples.split(
+ at: min(samples.count, buffer.count))
+ let samplesCopiedCount = buffer.moveUpdate(
+ fromContentsOf: samples_to_copy)
+ buffer = buffer.extracting(samplesCopiedCount...)
+ if !self.decoded_audio.write(contentsOf: samples_to_store) {
+ log("ERROR: PCM ring buffer full!")
+ }
+ }
+ }
+ }
+
+ mutating func fill_timer(
+ _ timer: UnsafeMutablePointer?
+ ) {
+ // refill
+ self.fill_buffers()
+
+ // re-set timer
+ btstack_run_loop_set_timer(timer, UInt32(DRIVER_POLL_INTERVAL_MS))
+ btstack_run_loop_add_timer(timer)
+ }
+
+ mutating func start_stream() {
+ // pre-fill buffers
+ self.fill_buffers()
+
+ // start timer
+ // FIXME: Use ctx
+ // NOTE: hardcoded to `Self` because the timer callback has no context
+ // argument which can be used to pass `self`
+ btstack_run_loop_set_timer_handler(
+ &self.fill_timer, { Application.shared.audioEngine.audio_pico.fill_timer($0) })
+ btstack_run_loop_set_timer_context(&self.fill_timer, nil)
+ btstack_run_loop_set_timer(
+ &self.fill_timer, UInt32(DRIVER_POLL_INTERVAL_MS))
+ btstack_run_loop_add_timer(&self.fill_timer)
+ }
+
+ mutating func stop_stream() {
+ // stop timer
+ btstack_run_loop_remove_timer(&self.fill_timer)
+ }
+}
diff --git a/harmony/Sources/Audio/MAX9744.swift b/harmony/Sources/Audio/MAX9744.swift
new file mode 100644
index 00000000..6c969508
--- /dev/null
+++ b/harmony/Sources/Audio/MAX9744.swift
@@ -0,0 +1,105 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+struct MAX9744: ~Copyable {
+ static let i2cAddress: UInt8 = 0x4B // 7 bit address
+ static let absoluteVolumeControlRegisterAddress: UInt8 = 0x0
+
+ static let modulationControlRegisterAddress: UInt8 = 0x1
+ static let filterlessModulationBitPattern: UInt8 = 0x0
+ static let pwmModulationBitPattern: UInt8 = 0x1
+
+ static let incrementalVolumeControlRegisterAddress: UInt8 = 0x3
+ static let increaseVolumeBitPattern: UInt8 = 0x4
+ static let decreaseVolumeBitPattern: UInt8 = 0x5
+
+ var i2c: i2c_inst_t
+
+ init(i2c: i2c_inst_t) {
+ self.i2c = i2c
+ }
+}
+
+extension MAX9744 {
+ static func validAddress(_ address: UInt8) -> Bool {
+ switch address {
+ case Self.absoluteVolumeControlRegisterAddress: true
+ case Self.filterlessModulationBitPattern: true
+ case Self.incrementalVolumeControlRegisterAddress: true
+ default: false
+ }
+ }
+
+ mutating func write(address: UInt8, value: UInt8) {
+ precondition(Self.validAddress(address))
+ var data = (address << 6) | value
+ log("attempting to write \(hex: data)")
+ let size = MemoryLayout.size(ofValue: data)
+ let result = i2c_write_blocking(
+ &self.i2c,
+ Self.i2cAddress,
+ &data,
+ size,
+ false)
+ precondition(result == size, "I2C write failed")
+ }
+
+ mutating func read(address: UInt8) -> UInt8 {
+ precondition(Self.validAddress(address))
+ var data = address << 6
+ let size = MemoryLayout.size(ofValue: data)
+ let readResult = i2c_read_blocking(
+ &self.i2c,
+ Self.i2cAddress,
+ &data,
+ size,
+ false)
+ precondition(readResult == size, "I2C read failed")
+ return data
+ }
+}
+
+extension MAX9744 {
+ /// 6 bit value ranging from 0 (mute) to 63 (+ 9.5 dB)
+ mutating func set(rawVolume: UInt8) {
+ precondition(0 <= rawVolume && rawVolume <= 63)
+ self.write(
+ address: Self.absoluteVolumeControlRegisterAddress,
+ value: rawVolume)
+ }
+
+ enum ModulationMode {
+ case filterless
+ case pwm
+ }
+
+ mutating func set(moduluationMode: ModulationMode) {
+ let modulationBitPattern = switch moduluationMode {
+ case .filterless: Self.filterlessModulationBitPattern
+ case .pwm: Self.pwmModulationBitPattern
+ }
+ self.write(
+ address: Self.modulationControlRegisterAddress,
+ value: modulationBitPattern)
+ }
+
+ mutating func increaseVolume() {
+ self.write(
+ address: Self.incrementalVolumeControlRegisterAddress,
+ value: Self.increaseVolumeBitPattern)
+ }
+
+ mutating func decreaseVolume() {
+ self.write(
+ address: Self.incrementalVolumeControlRegisterAddress,
+ value: Self.decreaseVolumeBitPattern)
+ }
+}
diff --git a/harmony/Sources/Audio/Resampler.swift b/harmony/Sources/Audio/Resampler.swift
new file mode 100644
index 00000000..ef4cd8bb
--- /dev/null
+++ b/harmony/Sources/Audio/Resampler.swift
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+struct Resampler: ~Copyable {
+ var channels: Int
+ var context: btstack_resample_t
+
+ init(channels: Int) {
+ self.channels = channels
+ self.context = btstack_resample_t()
+ btstack_resample_init(&self.context, Int32(channels))
+ }
+
+ mutating func set(channels: Int) {
+ self.channels = channels
+ btstack_resample_init(&self.context, Int32(channels))
+ }
+
+ mutating func set(factor: UInt32) {
+ btstack_resample_set_factor(&self.context, factor)
+ }
+
+ /// Resamples the given samples using the previously set resampling factor.
+ ///
+ /// Returns a slice of the temporary buffer that contains the resampled audio.
+ mutating func resample(
+ samples: UnsafeBufferPointer,
+ usingTemporaryBuffer buffer: UnsafeMutableBufferPointer
+ ) -> UnsafeMutableBufferPointer {
+ precondition(samples.count.isMultiple(of: self.channels))
+
+ // FIXME: understand why this is not `samples.count / self.channels`
+ // The documentation just calls this parameter `numFrames` which implies
+ // the sample count should be divided by the channel count.
+ let inputFrameCount = samples.count
+ let resampledFrameCount = btstack_resample_block(
+ &self.context,
+ samples.baseAddress,
+ UInt32(inputFrameCount),
+ buffer.baseAddress)
+ let resampledSampleCount = Int(resampledFrameCount) * self.channels
+ return buffer.extracting(..: ~Copyable {
+ // FIMXE: Use an inline allocation like `Vector`
+ var storage: UnsafeMutableBufferPointer
+ var readerIndex: Int
+ var writerIndex: Int
+
+ init(capacity: Int) {
+ self.storage = .allocate(capacity: capacity)
+ self.readerIndex = 0
+ self.writerIndex = 0
+ }
+
+ deinit {
+ var readerIndex = self.readerIndex
+ while self.readerIndex != self.writerIndex {
+ self.storage.deinitializeElement(at: readerIndex)
+ readerIndex = (readerIndex + 1) % self.storage.count
+ }
+ // FIXME: why can't we use a mutating method here?
+ // while _ = self.pop() { }
+ self.storage.deallocate()
+ }
+}
+
+extension Ring where Element: ~Copyable {
+ mutating func push(_ element: consuming Element) {
+ let nextWriterIndex = (self.writerIndex + 1) % self.storage.count
+ guard nextWriterIndex != self.readerIndex else { fatalError("Overflow") }
+ self.storage.initializeElement(at: self.writerIndex, to: element)
+ __dsb() // Make sure the element is written before updating the index
+ self.writerIndex = nextWriterIndex
+ }
+
+ mutating func pop() -> Element? {
+ guard self.readerIndex != self.writerIndex else { return nil }
+ let element = self.storage.moveElement(from: self.readerIndex)
+ __dsb() // Make sure the element is read before updating the index
+ self.readerIndex = (self.readerIndex + 1) % self.storage.count
+ return element
+ }
+}
diff --git a/harmony/Sources/Audio/RingBuffer.swift b/harmony/Sources/Audio/RingBuffer.swift
new file mode 100644
index 00000000..11a30d0e
--- /dev/null
+++ b/harmony/Sources/Audio/RingBuffer.swift
@@ -0,0 +1,126 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// FIXME: RingBuffer
+struct RingBuffer: ~Copyable {
+ // FIMXE: Use an inline allocation like `Vector`
+ var storage: UnsafeMutableBufferPointer
+ var count: Int
+ var readerIndex: Int
+ var writerIndex: Int
+
+ init(capacity: Int) {
+ self.storage = .allocate(capacity: capacity)
+ self.readerIndex = 0
+ self.writerIndex = 0
+ self.count = 0
+ }
+
+ deinit {
+ self.storage.deallocate()
+ }
+}
+
+extension RingBuffer {
+ var capacity: Int { self.storage.count }
+ var availableCapacity: Int { self.capacity - self.count }
+ var isEmpty: Bool { self.count == 0 }
+ var isFull: Bool { self.count == self.capacity }
+}
+
+extension RingBuffer {
+ mutating func clear() {
+ // Forget about the contents of `storage`, this is safe because
+ // `Element` is `BitwiseCopyable`.
+ self.count = 0
+ self.readerIndex = 0
+ self.writerIndex = 0
+ }
+
+ mutating func read(
+ into buffer: UnsafeMutableBufferPointer,
+ count: Int? = nil
+ ) -> Int {
+ let elementsToRead = min(buffer.count, count ?? Int.max, self.count)
+
+ // Reading 0 elements is a no-op.
+ guard elementsToRead > 0 else { return elementsToRead }
+
+ // Read the initial elements from the end of the ring buffer.
+ let elementsUntilEnd = self.capacity - self.readerIndex
+ let elementsToReadFirstHalf = min(elementsUntilEnd, elementsToRead)
+ buffer.baseAddress!.update(
+ from: self.storage.baseAddress! + self.readerIndex,
+ count: elementsToReadFirstHalf)
+ self.readerIndex += elementsToReadFirstHalf
+
+ // Update the reader index to wrap if needed.
+ if self.readerIndex == self.capacity {
+ self.readerIndex = 0
+ }
+
+ // Read the remaining elements from the beginning of the ring buffer.
+ let elementsToReadSecondHalf = elementsToRead - elementsToReadFirstHalf
+ precondition(elementsToReadSecondHalf >= 0)
+ (buffer.baseAddress! + elementsToReadFirstHalf).update(
+ from: self.storage.baseAddress! + self.readerIndex,
+ count: elementsToReadSecondHalf)
+ self.readerIndex += elementsToReadSecondHalf
+
+ // Update bookkeeping with the new count.
+ self.count -= elementsToRead
+
+ return elementsToRead
+ }
+
+ mutating func write(
+ contentsOf buffer: UnsafeMutableBufferPointer
+ ) -> Bool {
+ self.write(contentsOf: UnsafeBufferPointer(buffer))
+ }
+
+ mutating func write(
+ contentsOf buffer: UnsafeBufferPointer
+ ) -> Bool {
+ let elementsToWrite = buffer.count
+
+ // Writing 0 elements is a no-op.
+ guard elementsToWrite > 0 else { return true }
+ // Writing more than the available capacity is an error.
+ guard elementsToWrite <= self.availableCapacity else { return false }
+
+ // Write the initial elements to the end of the ring buffer.
+ let elementsUntilEnd = self.capacity - self.writerIndex
+ let elementsToWriteFirstHalf = min(elementsUntilEnd, elementsToWrite)
+ (self.storage.baseAddress! + self.writerIndex).update(
+ from: buffer.baseAddress!,
+ count: elementsToWriteFirstHalf)
+ self.writerIndex += elementsToWriteFirstHalf
+
+ // Update the writer index to wrap if needed.
+ if self.writerIndex == self.capacity {
+ self.writerIndex = 0
+ }
+
+ // Write the remaining elements to the beginning of the ring buffer.
+ let elementsToWriteSecondHalf = elementsToWrite - elementsToWriteFirstHalf
+ precondition(elementsToWriteSecondHalf >= 0)
+ (self.storage.baseAddress! + self.writerIndex).update(
+ from: buffer.baseAddress! + elementsToWriteFirstHalf,
+ count: elementsToWriteSecondHalf)
+ self.writerIndex += elementsToWriteSecondHalf
+
+ // Update bookkeeping with the new count.
+ self.count += elementsToWrite
+
+ return true
+ }
+}
diff --git a/harmony/Sources/Audio/SpinLock.swift b/harmony/Sources/Audio/SpinLock.swift
new file mode 100644
index 00000000..8212f04f
--- /dev/null
+++ b/harmony/Sources/Audio/SpinLock.swift
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+struct SpinLock: ~Copyable {
+ var _lock: UnsafeMutablePointer
+ var value: Value
+
+ init(index: Int, initialValue: consuming Value) {
+ self._lock = spin_lock_init(UInt32(index))
+ self.value = initialValue
+ }
+}
+
+extension SpinLock where Value: ~Copyable {
+ func lock() -> UInt32 {
+ spin_lock_blocking(self._lock)
+ }
+
+ func unlock(irq_mask: UInt32) {
+ spin_unlock(self._lock, irq_mask)
+ }
+
+ mutating func withLock(
+ _ body: (inout Value) throws(Error) -> Result
+ ) throws(Error) -> Result where Result: ~Copyable {
+ let irq_mask = self.lock()
+ defer { self.unlock(irq_mask: irq_mask) }
+ return try body(&self.value)
+ }
+}
diff --git a/harmony/Sources/Audio/TPA2016D2.swift b/harmony/Sources/Audio/TPA2016D2.swift
new file mode 100644
index 00000000..59b56640
--- /dev/null
+++ b/harmony/Sources/Audio/TPA2016D2.swift
@@ -0,0 +1,118 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+func i2c_init() {
+ i2c_init(&i2c0_inst, 100 * 1000) // 400kHz "Fast Mode"
+ gpio_set_function(UInt32(PICO_DEFAULT_I2C_SDA_PIN), GPIO_FUNC_I2C)
+ gpio_set_function(UInt32(PICO_DEFAULT_I2C_SCL_PIN), GPIO_FUNC_I2C)
+ gpio_pull_up(UInt32(PICO_DEFAULT_I2C_SDA_PIN))
+ gpio_pull_up(UInt32(PICO_DEFAULT_I2C_SCL_PIN))
+
+ // I2C reserves some addresses for special purposes. We exclude these from the scan.
+ // These are any addresses of the form 000 0xxx or 111 1xxx
+ func reserved_addr(_ addr: UInt8) -> Bool{
+ return (addr & 0x78) == 0 || (addr & 0x78) == 0x78
+ }
+
+ log("\nI2C Bus Scan")
+ log(" 0 1 2 3 4 5 6 7 8 9 A B C D E F")
+ for addr in UInt8(0) ..< (1 << 7) {
+ if addr.isMultiple(of: 16) {
+ log("\(addr >> 4) ", terminator: "")
+ }
+
+ // Perform a 1-byte dummy read from the probe address. If a slave
+ // acknowledges this address, the function returns the number of bytes
+ // transferred. If the address byte is ignored, the function returns
+ // -1.
+
+ // Skip over any reserved addresses.
+ var rxdata: UInt8 = 0
+ let ret = if reserved_addr(addr) {
+ Int32(PICO_ERROR_GENERIC.rawValue)
+ } else {
+ i2c_read_blocking(&i2c0_inst, addr, &rxdata, 1, false)
+ }
+
+ log(ret < 0 ? "." : "@", terminator: addr % 16 == 15 ? "\n" : " ")
+ }
+ log("Done.\n")
+}
+
+struct TPA2016D2: ~Copyable {
+ static let address: UInt8 = 0x58 // 7 bit address
+ static let IC_FUNCTION_CONTROL: UInt8 = 0x1
+ static let AGC_ATTACK_CONTROL: UInt8 = 0x2
+ static let AGC_RELEASE_CONTROL: UInt8 = 0x3
+ static let AGC_HOLD_TIME_CONTROL: UInt8 = 0x4
+ static let AGC_FIXED_GAIN_CONTROL: UInt8 = 0x5
+ static let AGC_CONTROL_0: UInt8 = 0x6
+ static let AGC_CONTROL_1: UInt8 = 0x7
+
+ var i2c: i2c_inst_t
+
+ init(i2c: i2c_inst_t) {
+ self.i2c = i2c
+
+ for r in UInt8(0x1) ... 0x7 {
+ log("Register \(hex: r); read \(hex: self.read(address: r))")
+ }
+
+ // Immediately configure the amp to our desired defaults.
+ // Disable AGC (Automatic Gain Control).
+ self.write(address: Self.AGC_CONTROL_1, value: 0x0)
+ // Disable Output Limiter
+ self.write(address: Self.AGC_CONTROL_0, value: 1 << 7)
+ // Set the attack time to the fastest setting (0.1067 ms per step)
+ self.write(address: Self.AGC_ATTACK_CONTROL, value: 1)
+ // Set the release time to the fastest setting (0.0137 s per step)
+ self.write(address: Self.AGC_RELEASE_CONTROL, value: 1)
+ // Disable the hold time entirely
+ self.write(address: Self.AGC_HOLD_TIME_CONTROL, value: 0)
+ }
+}
+
+extension TPA2016D2 {
+ mutating func write(address: UInt8, value: UInt8) {
+ var combined: UInt16 = (UInt16(value) << 8) | UInt16(address)
+ let result = i2c_write_blocking(
+ &self.i2c,
+ Self.address,
+ &combined,
+ MemoryLayout.size(ofValue: combined),
+ false)
+ precondition(result == 2, "I2C write failed")
+ // log("Register \(hex: address); wrote \(hex: value) - read \(hex: self.read(address: address))")
+ }
+
+ mutating func read(address: UInt8) -> UInt8 {
+ var data = address
+ let writeResult = i2c_write_blocking(&self.i2c, Self.address, &data, 1, false)
+ precondition(writeResult == 1, "I2C write failed")
+ let readResult = i2c_read_blocking(&self.i2c, Self.address, &data, 1, false)
+ precondition(readResult == 1, "I2C read failed")
+ return data
+ }
+}
+
+extension TPA2016D2 {
+ // scale from 0 to 255
+ mutating func set(gain: UInt8) {
+ precondition(0 <= gain && gain <= 30)
+ self.write(address: Self.AGC_FIXED_GAIN_CONTROL, value: gain)
+ }
+
+ mutating func mute(_ mute: Bool) {
+ var value = self.read(address: Self.IC_FUNCTION_CONTROL)
+ value = mute ? value | (1 << 5) : value & ~(1 << 5)
+ self.write(address: Self.IC_FUNCTION_CONTROL, value: value)
+ }
+}
diff --git a/harmony/Sources/Audio/Timer.swift b/harmony/Sources/Audio/Timer.swift
new file mode 100644
index 00000000..acad420a
--- /dev/null
+++ b/harmony/Sources/Audio/Timer.swift
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// struct Timer: ~Copyable, ~Escapable {
+// var context: UnsafePointer
+
+// init(context: borrowing Context) dependsOn(context) {
+// withUnsafePointerToInstance(context) { context in
+// self.context = context
+// }
+// }
+// }
\ No newline at end of file
diff --git a/harmony/Sources/Bluetooth/A2DP.swift b/harmony/Sources/Bluetooth/A2DP.swift
new file mode 100644
index 00000000..ebb257f6
--- /dev/null
+++ b/harmony/Sources/Bluetooth/A2DP.swift
@@ -0,0 +1,300 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// Advanced Audio Distribution Profile
+
+struct MediaCodecConfigurationSBC {
+ var reconfigure: UInt8
+ var num_channels: UInt8
+ var sampling_frequency: UInt16
+ var block_length: UInt8
+ var subbands: UInt8
+ var min_bitpool_value: UInt8
+ var max_bitpool_value: UInt8
+ var channel_mode: btstack_sbc_channel_mode_t
+ var allocation_method: btstack_sbc_allocation_method_t
+
+ init() {
+ self.reconfigure = 0
+ self.num_channels = 0
+ self.sampling_frequency = 0
+ self.block_length = 0
+ self.subbands = 0
+ self.min_bitpool_value = 0
+ self.max_bitpool_value = 0
+ self.channel_mode = SBC_CHANNEL_MODE_MONO
+ self.allocation_method = SBC_ALLOCATION_METHOD_LOUDNESS
+ }
+
+ func dump() {
+ log(
+ """
+ - num_channels: \(self.num_channels)
+ - sampling_frequency: \(self.sampling_frequency)
+ - channel_mode: \(self.channel_mode.rawValue)
+ - block_length: \(self.block_length)
+ - subbands: \(self.subbands)
+ - allocation_method: \(self.allocation_method.rawValue)
+ - bitpool_value [\(self.min_bitpool_value), \(self.max_bitpool_value)]
+ """)
+ }
+}
+
+enum StreamState {
+ case closed
+ case open
+ case playing
+ case paused
+}
+
+struct A2DPConnection {
+ static var shared = Self()
+
+ var addr: bd_addr_t = (0, 0, 0, 0, 0, 0)
+ var a2dp_cid: UInt16 = 0
+ var a2dp_local_seid: UInt8 = 0
+ var stream_state: StreamState = .closed
+ var sbc_configuration: MediaCodecConfigurationSBC = .init()
+}
+
+@_cdecl("a2dp_sink_packet_handler")
+func a2dp_sink_packet_handler(
+ packet_type: UInt8,
+ channel: UInt16,
+ packet: UnsafeMutablePointer?,
+ size: UInt16
+) {
+ guard packet_type == HCI_EVENT_PACKET else { return }
+ guard hci_event_packet_get_type(packet) == HCI_EVENT_A2DP_META else { return }
+
+ let subevent = packet?[2]
+ switch subevent {
+ case UInt8(A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION):
+ log("A2DP Sink : Received non SBC codec - not implemented")
+
+ case UInt8(A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION):
+ log("A2DP Sink : Received SBC codec configuration")
+ A2DPConnection.shared.sbc_configuration.reconfigure =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(
+ packet)
+ A2DPConnection.shared.sbc_configuration.num_channels =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(
+ packet)
+ A2DPConnection.shared.sbc_configuration.sampling_frequency =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(
+ packet)
+ A2DPConnection.shared.sbc_configuration.block_length =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(
+ packet)
+ A2DPConnection.shared.sbc_configuration.subbands =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(packet)
+ A2DPConnection.shared.sbc_configuration.min_bitpool_value =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(
+ packet)
+ A2DPConnection.shared.sbc_configuration.max_bitpool_value =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(
+ packet)
+
+ let allocation_method =
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(
+ packet)
+
+ // Adapt Bluetooth spec definition to SBC Encoder expected input
+ A2DPConnection.shared.sbc_configuration.allocation_method =
+ (btstack_sbc_allocation_method_t)(allocation_method - 1)
+
+ switch avdtp_channel_mode_t(
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(
+ packet))
+ {
+ case AVDTP_CHANNEL_MODE_JOINT_STEREO:
+ A2DPConnection.shared.sbc_configuration.channel_mode =
+ SBC_CHANNEL_MODE_JOINT_STEREO
+ case AVDTP_CHANNEL_MODE_STEREO:
+ A2DPConnection.shared.sbc_configuration.channel_mode =
+ SBC_CHANNEL_MODE_STEREO
+ case AVDTP_CHANNEL_MODE_DUAL_CHANNEL:
+ A2DPConnection.shared.sbc_configuration.channel_mode =
+ SBC_CHANNEL_MODE_DUAL_CHANNEL
+ case AVDTP_CHANNEL_MODE_MONO:
+ A2DPConnection.shared.sbc_configuration.channel_mode =
+ SBC_CHANNEL_MODE_MONO
+ default:
+ fatalError()
+ }
+ A2DPConnection.shared.sbc_configuration.dump()
+
+ case UInt8(A2DP_SUBEVENT_STREAM_ESTABLISHED):
+ let status = a2dp_subevent_stream_established_get_status(packet)
+ guard status == ERROR_CODE_SUCCESS else {
+ log(
+ "A2DP Sink : Streaming connection failed, status \(hex: status)"
+ )
+ return
+ }
+
+ a2dp_subevent_stream_established_get_bd_addr(
+ packet, &A2DPConnection.shared.addr)
+ A2DPConnection.shared.a2dp_cid =
+ a2dp_subevent_stream_established_get_a2dp_cid(packet)
+ A2DPConnection.shared.a2dp_local_seid =
+ a2dp_subevent_stream_established_get_local_seid(packet)
+ A2DPConnection.shared.stream_state = .open
+
+ log(
+ "A2DP Sink : Streaming connection is established, address \(cString: bd_addr_to_str(&A2DPConnection.shared.addr)), cid \(hex: A2DPConnection.shared.a2dp_cid), local seid \(A2DPConnection.shared.a2dp_local_seid)"
+ )
+
+ #if ENABLE_AVDTP_ACCEPTOR_EXPLICIT_START_STREAM_CONFIRMATION
+ case UInt8(A2DP_SUBEVENT_START_STREAM_REQUESTED):
+ log(
+ "A2DP Sink : Explicit Accept to start stream, local_seid %d\n",
+ a2dp_subevent_start_stream_requested_get_local_seid(packet))
+ a2dp_sink_start_stream_accept(a2dp_cid, a2dp_local_seid)
+ #endif
+
+ case UInt8(A2DP_SUBEVENT_STREAM_STARTED):
+ log("A2DP Sink : Stream started")
+ A2DPConnection.shared.stream_state = .playing
+ if A2DPConnection.shared.sbc_configuration.reconfigure != 0 {
+ Application.shared.audioEngine.close()
+ }
+ // prepare media processing
+ // audio playback starts when buffer reaches minimal level
+ Application.shared.audioEngine.`init`(A2DPConnection.shared.sbc_configuration)
+
+ case UInt8(A2DP_SUBEVENT_STREAM_SUSPENDED):
+ log("A2DP Sink : Stream paused")
+ A2DPConnection.shared.stream_state = .paused
+ Application.shared.audioEngine.pause()
+
+ case UInt8(A2DP_SUBEVENT_STREAM_RELEASED):
+ log("A2DP Sink : Stream released")
+ A2DPConnection.shared.stream_state = .closed
+ Application.shared.audioEngine.close()
+
+ case UInt8(A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED):
+ log("A2DP Sink : Signaling connection released")
+ A2DPConnection.shared.a2dp_cid = 0
+ Application.shared.audioEngine.close()
+
+ default:
+ log("AVRCP Sink : Event \(hex: subevent ?? 0xff) is not parsed")
+ }
+}
+
+/* @section Handle Media Data Packet
+ *
+ * @text Here the audio data, are received through the a2dp_sink_media_handler callback.
+ * Currently, only the SBC media codec is supported. Hence, the media data consists of the media packet header and the SBC packet.
+ * The SBC frame will be stored in a ring buffer for later processing (instead of decoding it to PCM right away which would require a much larger buffer).
+ * If the audio stream wasn't started already and there are enough SBC frames in the ring buffer, start playback.
+ */
+
+func read_media_data_header(
+ _ packet: UnsafeMutablePointer?,
+ _ size: Int32,
+ _ offset: UnsafeMutablePointer,
+ _ media_header: UnsafeMutablePointer
+) -> Bool {
+ guard let packet else { return false }
+ let media_header_len: Int32 = 12 // without crc
+ var pos = Int(offset.pointee)
+
+ if size - Int32(pos) < media_header_len {
+ log(
+ "Not enough data to read media packet header, expected \(media_header_len), received \(size-Int32(pos))"
+ )
+ return false
+ }
+
+ media_header.pointee.version = packet[pos] & 0x03
+ media_header.pointee.padding = UInt8(get_bit16(UInt16(packet[pos]), 2))
+ media_header.pointee.extension = UInt8(get_bit16(UInt16(packet[pos]), 3))
+ media_header.pointee.csrc_count = (packet[pos] >> 4) & 0x0F
+ pos += 1
+
+ media_header.pointee.marker = UInt8(get_bit16(UInt16(packet[pos]), 0))
+ media_header.pointee.payload_type = (packet[pos] >> 1) & 0x7F
+ pos += 1
+
+ media_header.pointee.sequence_number = UInt16(
+ big_endian_read_16(packet, Int32(pos)))
+ pos += 2
+
+ media_header.pointee.timestamp = big_endian_read_32(packet, Int32(pos))
+ pos += 4
+
+ media_header.pointee.synchronization_source = big_endian_read_32(
+ packet, Int32(pos))
+ pos += 4
+ offset.pointee = Int32(pos)
+ return true
+}
+
+func read_sbc_header(
+ _ packet: UnsafeMutablePointer?,
+ _ size: Int32,
+ _ offset: UnsafeMutablePointer,
+ _ sbc_header: UnsafeMutablePointer
+) -> Bool {
+ guard let packet else { return false }
+ let sbc_header_len: Int32 = 12 // without crc
+ var pos: Int32 = offset.pointee
+
+ if size - pos < sbc_header_len {
+ log(
+ "Not enough data to read SBC header, expected \(sbc_header_len), received \(size-pos)"
+ )
+ return false
+ }
+
+ sbc_header.pointee.fragmentation = UInt8(
+ get_bit16(UInt16(packet[Int(pos)]), 7))
+ sbc_header.pointee.starting_packet = UInt8(
+ get_bit16(UInt16(packet[Int(pos)]), 6))
+ sbc_header.pointee.last_packet = UInt8(get_bit16(UInt16(packet[Int(pos)]), 5))
+ sbc_header.pointee.num_frames = UInt8(packet[Int(pos)] & 0x0f)
+ pos += 1
+ offset.pointee = pos
+ return true
+}
+
+@_cdecl("a2dp_sink_media_handler")
+func a2dp_sink_media_handler(
+ seid: UInt8,
+ packet: UnsafeMutablePointer?,
+ size: UInt16
+) {
+ var pos: Int32 = 0
+
+ var media_header = avdtp_media_packet_header_t()
+ guard read_media_data_header(packet, Int32(size), &pos, &media_header) else {
+ log("Failed to read media data header")
+ return
+ }
+
+ var sbc_header = avdtp_sbc_codec_header_t()
+ guard read_sbc_header(packet, Int32(size), &pos, &sbc_header) else {
+ log("Failed to read SBC header")
+ return
+ }
+
+ let packet_length = UInt32(size) - UInt32(pos)
+ let packet_begin = packet?.advanced(by: Int(pos))
+ let sbc_frame_size = Int(packet_length / UInt32(sbc_header.num_frames))
+
+ let packetBuffer = UnsafeMutableBufferPointer(
+ start: packet_begin, count: Int(packet_length))
+ Application.shared.audioEngine.audio_pico.enqueue(
+ sbc_frames: packetBuffer, frame_size: sbc_frame_size)
+ Application.shared.audioEngine.start()
+}
diff --git a/harmony/Sources/Bluetooth/AVRCP.swift b/harmony/Sources/Bluetooth/AVRCP.swift
new file mode 100644
index 00000000..6f5bc44a
--- /dev/null
+++ b/harmony/Sources/Bluetooth/AVRCP.swift
@@ -0,0 +1,286 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// Audio/Video Remote Control Profile
+
+struct AVRCPConnection {
+ var addr: bd_addr_t
+ var avrcp_cid: UInt16
+ var playing: Bool
+ var notifications_supported_by_target: UInt16
+}
+
+var avrcp_connection = AVRCPConnection(
+ addr: (0, 0, 0, 0, 0, 0),
+ avrcp_cid: 0,
+ playing: false,
+ notifications_supported_by_target: 0)
+
+@_cdecl("avrcp_packet_handler")
+func avrcp_packet_handler(
+ packet_type: UInt8,
+ channel: UInt16,
+ packet: UnsafeMutablePointer?,
+ size: UInt16
+) {
+ guard packet_type == HCI_EVENT_PACKET else { return }
+ guard hci_event_packet_get_type(packet) == HCI_EVENT_AVRCP_META else {
+ return
+ }
+
+ let subevent = packet?[2]
+ switch subevent {
+ case UInt8(AVRCP_SUBEVENT_CONNECTION_ESTABLISHED):
+ log("AVRCP_SUBEVENT_CONNECTION_ESTABLISHED")
+ let local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet)
+ let status = avrcp_subevent_connection_established_get_status(packet)
+
+ if status != ERROR_CODE_SUCCESS {
+ log("AVRCP: Connection failed, status \(hex: status)")
+ avrcp_connection.avrcp_cid = 0
+ return
+ }
+
+ avrcp_connection.avrcp_cid = local_cid
+ var address: bd_addr_t = (0, 0, 0, 0, 0, 0)
+ avrcp_subevent_connection_established_get_bd_addr(packet, &address)
+ log(
+ "AVRCP: Connected to \(cString: bd_addr_to_str(&address)), cid \(hex: avrcp_connection.avrcp_cid)"
+ )
+
+ avrcp_target_support_event(
+ avrcp_connection.avrcp_cid, AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED)
+ avrcp_target_support_event(
+ avrcp_connection.avrcp_cid, AVRCP_NOTIFICATION_EVENT_BATT_STATUS_CHANGED)
+ let battery_status = AVRCP_BATTERY_STATUS_WARNING
+ avrcp_target_battery_status_changed(
+ avrcp_connection.avrcp_cid, battery_status)
+
+ // query supported events:
+ avrcp_controller_get_supported_events(avrcp_connection.avrcp_cid)
+
+ case UInt8(AVRCP_SUBEVENT_CONNECTION_RELEASED):
+ log("AVRCP_SUBEVENT_CONNECTION_RELEASED")
+ log(
+ "AVRCP: Channel released: cid \(hex: avrcp_subevent_connection_released_get_avrcp_cid(packet))"
+ )
+ avrcp_connection.avrcp_cid = 0
+ avrcp_connection.notifications_supported_by_target = 0
+
+ default:
+ log("AVRCP: Event \(hex: subevent ?? 0xff) is not parsed")
+ }
+}
+
+@_cdecl("avrcp_controller_packet_handler")
+func avrcp_controller_packet_handler(
+ packet_type: UInt8,
+ channel: UInt16,
+ packet: UnsafeMutablePointer?,
+ size: UInt16
+) {
+ guard packet_type == HCI_EVENT_PACKET else { return }
+ guard hci_event_packet_get_type(packet) == HCI_EVENT_AVRCP_META else {
+ return
+ }
+ guard avrcp_connection.avrcp_cid != 0 else { return }
+
+ let subevent = packet?[2]
+ switch subevent {
+ case UInt8(AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID):
+ avrcp_connection.notifications_supported_by_target |=
+ (1 << avrcp_subevent_get_capability_event_id_get_event_id(packet))
+
+ case UInt8(AVRCP_SUBEVENT_GET_CAPABILITY_EVENT_ID_DONE):
+ log("AVRCP Controller: supported notifications by target:")
+ for event_id in UInt8(
+ AVRCP_NOTIFICATION_EVENT_FIRST_INDEX.rawValue).. 0 else { break }
+ let avrcp_subevent_value = UnsafeBufferPointer(
+ start: avrcp_subevent_now_playing_title_info_get_value(packet),
+ count: Int(count))
+ log("AVRCP Controller: Title \(cString: avrcp_subevent_value)")
+
+ case UInt8(AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO):
+ let count = avrcp_subevent_now_playing_artist_info_get_value_len(packet)
+ guard count > 0 else { break }
+ let avrcp_subevent_value = UnsafeBufferPointer(
+ start: avrcp_subevent_now_playing_artist_info_get_value(packet),
+ count: Int(count))
+ log("AVRCP Controller: Artist \(cString: avrcp_subevent_value)")
+
+ case UInt8(AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO):
+ let count = avrcp_subevent_now_playing_album_info_get_value_len(packet)
+ guard count > 0 else { break }
+ let avrcp_subevent_value = UnsafeBufferPointer(
+ start: avrcp_subevent_now_playing_album_info_get_value(packet),
+ count: Int(count))
+ log("AVRCP Controller: Album \(cString: avrcp_subevent_value)")
+
+ case UInt8(AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO):
+ let count = avrcp_subevent_now_playing_genre_info_get_value_len(packet)
+ guard count > 0 else { break }
+ let avrcp_subevent_value = UnsafeBufferPointer(
+ start: avrcp_subevent_now_playing_genre_info_get_value(packet),
+ count: Int(count))
+ log("AVRCP Controller: Genre \(cString: avrcp_subevent_value)")
+
+ case UInt8(AVRCP_SUBEVENT_PLAY_STATUS):
+ let songLength = avrcp_subevent_play_status_get_song_length(packet)
+ let songPosition = avrcp_subevent_play_status_get_song_position(packet)
+ let playStatus = avrcp_play_status2str(
+ avrcp_subevent_play_status_get_play_status(packet))
+ log(
+ "AVRCP Controller: Song length \(songLength) ms, Song position \(songPosition) ms, Play status \(cString: playStatus)"
+ )
+
+ case UInt8(AVRCP_SUBEVENT_OPERATION_COMPLETE):
+ let operationId = avrcp_operation2str(
+ avrcp_subevent_operation_complete_get_operation_id(packet))
+ log("AVRCP Controller: \(cString: operationId) complete")
+
+ case UInt8(AVRCP_SUBEVENT_OPERATION_START):
+ let operationId = avrcp_operation2str(
+ avrcp_subevent_operation_start_get_operation_id(packet))
+ log("AVRCP Controller: \(cString: operationId) start")
+
+ case UInt8(AVRCP_SUBEVENT_NOTIFICATION_EVENT_TRACK_REACHED_END):
+ log("AVRCP Controller: Track reached end")
+
+ case UInt8(AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE):
+ let commandType = avrcp_ctype2str(
+ avrcp_subevent_player_application_value_response_get_command_type(packet))
+ log("AVRCP Controller: Set Player App Value \(cString: commandType)")
+
+ default:
+ break
+ }
+}
+
+@_cdecl("avrcp_target_packet_handler")
+func avrcp_target_packet_handler(
+ packet_type: UInt8,
+ channel: UInt16,
+ packet: UnsafeMutablePointer?,
+ size: UInt16
+) {
+ guard packet_type == HCI_EVENT_PACKET else { return }
+ guard hci_event_packet_get_type(packet) == HCI_EVENT_AVRCP_META else {
+ return
+ }
+
+ let subevent = packet?[2]
+ switch subevent {
+ case UInt8(AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED):
+ let volume = avrcp_subevent_notification_volume_changed_get_absolute_volume(
+ packet)
+ log("AVRCP Target : Volume set to [\(volume) / 127]")
+ Application.shared.audioEngine.set(volume: volume << 1)
+
+ case UInt8(AVRCP_SUBEVENT_OPERATION):
+ let operation_id = avrcp_operation_id_t(
+ avrcp_subevent_operation_get_operation_id(packet))
+ let button_state: StaticString =
+ avrcp_subevent_operation_get_button_pressed(packet) > 0
+ ? "PRESS" : "RELEASE"
+ switch operation_id {
+ case AVRCP_OPERATION_ID_VOLUME_UP:
+ log("AVRCP Target : VOLUME UP (\(button_state))")
+ case AVRCP_OPERATION_ID_VOLUME_DOWN:
+ log("AVRCP Target : VOLUME DOWN (\(button_state))")
+ default:
+ return
+ }
+
+ default:
+ log("AVRCP Target : Event \(hex: subevent ?? 0xff) is not parsed")
+ }
+}
diff --git a/harmony/Sources/Bluetooth/HCI.swift b/harmony/Sources/Bluetooth/HCI.swift
new file mode 100644
index 00000000..e025e281
--- /dev/null
+++ b/harmony/Sources/Bluetooth/HCI.swift
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// Host Controller Interface
+
+@_cdecl("hci_packet_handler")
+func hci_packet_handler(
+ packet_type: UInt8,
+ channel: UInt16,
+ packet: UnsafeMutablePointer?,
+ size: UInt16
+) {
+ guard packet_type == HCI_EVENT_PACKET else { return }
+ guard hci_event_packet_get_type(packet) == HCI_EVENT_PIN_CODE_REQUEST else {
+ return
+ }
+
+ var address: bd_addr_t = (0, 0, 0, 0, 0, 0)
+ log("Pin code request - using '0000'")
+ hci_event_pin_code_request_get_bd_addr(packet, &address)
+ gap_pin_code_response(&address, "0000")
+}
diff --git a/harmony/Sources/Bluetooth/SBC.swift b/harmony/Sources/Bluetooth/SBC.swift
new file mode 100644
index 00000000..2b9a3093
--- /dev/null
+++ b/harmony/Sources/Bluetooth/SBC.swift
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+enum SBCDecoder {
+ typealias Callback = (
+ _ data: UnsafeMutableBufferPointer,
+ _ num_channels: Int32,
+ _ sample_rate: Int32
+ ) -> Void
+
+ static var context = btstack_sbc_decoder_bluedroid_t()
+ static var instance: UnsafePointer? = nil
+ static var callback: Callback? = nil
+
+ static func configure(mode: btstack_sbc_mode_t) {
+ self.instance = btstack_sbc_decoder_bluedroid_init_instance(&context)
+
+ func decode_callback(
+ _ data: UnsafeMutablePointer?,
+ _ num_samples: Int32,
+ _ num_channels: Int32,
+ _ sample_rate: Int32,
+ _ context: UnsafeMutableRawPointer?
+ ) {
+ let data = UnsafeMutableBufferPointer(
+ start: data, count: Int(num_samples))
+ Self.callback?(data, num_channels, sample_rate)
+ }
+
+ instance?.pointee.configure(&context, mode, decode_callback, nil)
+ }
+
+ static func decode_signed_16(
+ mode: btstack_sbc_mode_t,
+ packet_status_flag: UInt8,
+ buffer: UnsafeRawBufferPointer,
+ callback: Callback
+ ) {
+ guard let instance = Self.instance else {
+ preconditionFailure("Must call configure prior to decode_signed_16")
+ }
+
+ return withoutActuallyEscaping(callback) {
+ Self.callback = $0
+ instance.pointee.decode_signed_16(
+ &Self.context,
+ packet_status_flag,
+ buffer.baseAddress,
+ UInt16(buffer.count))
+ Self.callback = nil
+ }
+ }
+}
diff --git a/harmony/Sources/Bluetooth/SDP.swift b/harmony/Sources/Bluetooth/SDP.swift
new file mode 100644
index 00000000..d7d37fac
--- /dev/null
+++ b/harmony/Sources/Bluetooth/SDP.swift
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+// Service Discovery Protocol
+
+struct ServiceDiscoveryProtocol: ~Copyable {
+ typealias ServiceRecord = UnsafePointer
+ typealias ServiceRecordHandle = UInt32
+
+ init() {
+ sdp_init()
+ }
+
+ deinit {
+ sdp_deinit()
+ }
+
+ mutating func registerService(record: ServiceRecord) {
+ precondition(sdp_register_service(record) == 0)
+ }
+
+ mutating func registerService(record: UnsafeMutableRawBufferPointer) {
+ precondition(de_get_len(record.baseAddress) <= record.count)
+ precondition(sdp_register_service(record.baseAddress) == 0)
+ }
+
+ mutating func unregisterService(handle: ServiceRecordHandle) {
+ sdp_unregister_service(handle)
+ }
+
+ mutating func getServiceRecordHandle(for record: ServiceRecord) -> ServiceRecordHandle {
+ sdp_get_service_record_handle(record)
+ }
+
+ mutating func makeServiceRecordHandle() -> ServiceRecordHandle {
+ sdp_create_service_record_handle()
+ }
+
+ mutating func getServiceRecord(for handle: ServiceRecordHandle) -> ServiceRecord? {
+ ServiceRecord(sdp_get_record_for_handle(handle))
+ }
+}
diff --git a/harmony/Sources/PIOPrograms/I2S.pio b/harmony/Sources/PIOPrograms/I2S.pio
new file mode 100644
index 00000000..7b9ab6ec
--- /dev/null
+++ b/harmony/Sources/PIOPrograms/I2S.pio
@@ -0,0 +1,64 @@
+;
+; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+;
+; SPDX-License-Identifier: BSD-3-Clause
+;
+
+; Transmit a mono or stereo I2S audio stream as stereo
+; This is 16 bits per sample; can be altered by modifying the "set" params,
+; or made programmable by replacing "set x" with "mov x, y" and using Y as a config register.
+;
+; Autopull must be enabled, with threshold set to 32.
+; Since I2S is MSB-first, shift direction should be to left.
+; Hence the format of the FIFO word is:
+;
+; | 31 : 16 | 15 : 0 |
+; | sample ws=0 | sample ws=1 |
+;
+; Data is output at 1 bit per clock. Use clock divider to adjust frequency.
+; Fractional divider will probably be needed to get correct bit clock period,
+; but for common syslck freqs this should still give a constant word select period.
+;
+; One output pin is used for the data output.
+; Two side-set pins are used. Bit 0 is clock, bit 1 is word select.
+
+; Send 16 bit words to the PIO for mono, 32 bit words for stereo
+
+.program audio_i2s
+.side_set 2
+
+ ; /--- LRCLK
+ ; |/-- BCLK
+bitloop1: ; ||
+ out pins, 1 side 0b10
+ jmp x-- bitloop1 side 0b11
+ out pins, 1 side 0b00
+ set x, 14 side 0b01
+
+bitloop0:
+ out pins, 1 side 0b00
+ jmp x-- bitloop0 side 0b01
+ out pins, 1 side 0b10
+public entry_point:
+ set x, 14 side 0b11
+
+% c-sdk {
+
+static inline void audio_i2s_program_init(PIO pio, uint sm, uint offset, uint data_pin, uint clock_pin_base) {
+ pio_sm_config sm_config = audio_i2s_program_get_default_config(offset);
+
+ sm_config_set_out_pins(&sm_config, data_pin, 1);
+ sm_config_set_sideset_pins(&sm_config, clock_pin_base);
+ sm_config_set_out_shift(&sm_config, false, true, 32);
+ sm_config_set_fifo_join(&sm_config, PIO_FIFO_JOIN_TX);
+
+ pio_sm_init(pio, sm, offset, &sm_config);
+
+ uint pin_mask = (1u << data_pin) | (3u << clock_pin_base);
+ pio_sm_set_pindirs_with_mask(pio, sm, pin_mask, pin_mask);
+ pio_sm_set_pins(pio, sm, 0); // clear pins
+
+ pio_sm_exec(pio, sm, pio_encode_jmp(offset + audio_i2s_offset_entry_point));
+}
+
+%}
diff --git a/harmony/Sources/PIOPrograms/QuadratureEncoder.pio b/harmony/Sources/PIOPrograms/QuadratureEncoder.pio
new file mode 100644
index 00000000..37ed3948
--- /dev/null
+++ b/harmony/Sources/PIOPrograms/QuadratureEncoder.pio
@@ -0,0 +1,148 @@
+
+// FROM: https://github.com/raspberrypi/pico-examples/blob/master/pio/quadrature_encoder/quadrature_encoder.pio
+
+;
+; Copyright (c) 2023 Raspberry Pi (Trading) Ltd.
+;
+; SPDX-License-Identifier: BSD-3-Clause
+;
+.pio_version 0 // only requires PIO version 0
+
+.program quadrature_encoder
+
+; the code must be loaded at address 0, because it uses computed jumps
+.origin 0
+
+
+; the code works by running a loop that continuously shifts the 2 phase pins into
+; ISR and looks at the lower 4 bits to do a computed jump to an instruction that
+; does the proper "do nothing" | "increment" | "decrement" action for that pin
+; state change (or no change)
+
+; ISR holds the last state of the 2 pins during most of the code. The Y register
+; keeps the current encoder count and is incremented / decremented according to
+; the steps sampled
+
+; the program keeps trying to write the current count to the RX FIFO without
+; blocking. To read the current count, the user code must drain the FIFO first
+; and wait for a fresh sample (takes ~4 SM cycles on average). The worst case
+; sampling loop takes 10 cycles, so this program is able to read step rates up
+; to sysclk / 10 (e.g., sysclk 125MHz, max step rate = 12.5 Msteps/sec)
+
+; 00 state
+ JMP update ; read 00
+ JMP decrement ; read 01
+ JMP increment ; read 10
+ JMP update ; read 11
+
+; 01 state
+ JMP increment ; read 00
+ JMP update ; read 01
+ JMP update ; read 10
+ JMP decrement ; read 11
+
+; 10 state
+ JMP decrement ; read 00
+ JMP update ; read 01
+ JMP update ; read 10
+ JMP increment ; read 11
+
+; to reduce code size, the last 2 states are implemented in place and become the
+; target for the other jumps
+
+; 11 state
+ JMP update ; read 00
+ JMP increment ; read 01
+decrement:
+ ; note: the target of this instruction must be the next address, so that
+ ; the effect of the instruction does not depend on the value of Y. The
+ ; same is true for the "JMP X--" below. Basically "JMP Y--, "
+ ; is just a pure "decrement Y" instruction, with no other side effects
+ JMP Y--, update ; read 10
+
+ ; this is where the main loop starts
+.wrap_target
+update:
+ MOV ISR, Y ; read 11
+ PUSH noblock
+
+sample_pins:
+ ; we shift into ISR the last state of the 2 input pins (now in OSR) and
+ ; the new state of the 2 pins, thus producing the 4 bit target for the
+ ; computed jump into the correct action for this state. Both the PUSH
+ ; above and the OUT below zero out the other bits in ISR
+ OUT ISR, 2
+ IN PINS, 2
+
+ ; save the state in the OSR, so that we can use ISR for other purposes
+ MOV OSR, ISR
+ ; jump to the correct state machine action
+ MOV PC, ISR
+
+ ; the PIO does not have a increment instruction, so to do that we do a
+ ; negate, decrement, negate sequence
+increment:
+ MOV Y, ~Y
+ JMP Y--, increment_cont
+increment_cont:
+ MOV Y, ~Y
+.wrap ; the .wrap here avoids one jump instruction and saves a cycle too
+
+
+
+% c-sdk {
+
+#include "hardware/clocks.h"
+#include "hardware/gpio.h"
+
+// max_step_rate is used to lower the clock of the state machine to save power
+// if the application doesn't require a very high sampling rate. Passing zero
+// will set the clock to the maximum
+
+static inline void quadrature_encoder_program_init(PIO pio, uint sm, uint pin, int max_step_rate)
+{
+ pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false);
+ pio_gpio_init(pio, pin);
+ pio_gpio_init(pio, pin + 1);
+
+ gpio_pull_up(pin);
+ gpio_pull_up(pin + 1);
+
+ pio_sm_config c = quadrature_encoder_program_get_default_config(0);
+
+ sm_config_set_in_pins(&c, pin); // for WAIT, IN
+ sm_config_set_jmp_pin(&c, pin); // for JMP
+ // shift to left, autopull disabled
+ sm_config_set_in_shift(&c, false, false, 32);
+ // don't join FIFO's
+ sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_NONE);
+
+ // passing "0" as the sample frequency,
+ if (max_step_rate == 0) {
+ sm_config_set_clkdiv(&c, 1.0);
+ } else {
+ // one state machine loop takes at most 10 cycles
+ float div = (float)clock_get_hz(clk_sys) / (10 * max_step_rate);
+ sm_config_set_clkdiv(&c, div);
+ }
+
+ pio_sm_init(pio, sm, 0, &c);
+ pio_sm_set_enabled(pio, sm, true);
+}
+
+static inline int32_t quadrature_encoder_get_count(PIO pio, uint sm)
+{
+ uint ret;
+ int n;
+
+ // if the FIFO has N entries, we fetch them to drain the FIFO,
+ // plus one entry which will be guaranteed to not be stale
+ n = pio_sm_get_rx_fifo_level(pio, sm) + 1;
+ while (n > 0) {
+ ret = pio_sm_get_blocking(pio, sm);
+ n--;
+ }
+ return ret;
+}
+
+%}
\ No newline at end of file
diff --git a/harmony/Sources/PIOPrograms/WS2812.pio b/harmony/Sources/PIOPrograms/WS2812.pio
new file mode 100644
index 00000000..839ce5f2
--- /dev/null
+++ b/harmony/Sources/PIOPrograms/WS2812.pio
@@ -0,0 +1,49 @@
+;
+; Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
+;
+; SPDX-License-Identifier: BSD-3-Clause
+;
+.pio_version 0 // only requires PIO version 0
+
+.program ws2812
+.side_set 1
+
+; The following constants are selected for broad compatibility with WS2812,
+; WS2812B, and SK6812 LEDs. Other constants may support higher bandwidths for
+; specific LEDs, such as (7,10,8) for WS2812B LEDs.
+
+.define public T1 3
+.define public T2 3
+.define public T3 4
+
+.wrap_target
+bitloop:
+ out x, 1 side 0 [T3 - 1] ; Side-set still takes place when instruction stalls
+ jmp !x do_zero side 1 [T1 - 1] ; Branch on the bit we shifted out. Positive pulse
+do_one:
+ jmp bitloop side 1 [T2 - 1] ; Continue driving high, for a long pulse
+do_zero:
+ nop side 0 [T2 - 1] ; Or drive low, for a short pulse
+.wrap
+
+% c-sdk {
+#include "hardware/clocks.h"
+
+static inline void ws2812_program_init(PIO pio, uint sm, uint offset, uint pin, float freq, bool rgbw) {
+
+ pio_gpio_init(pio, pin);
+ pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
+
+ pio_sm_config c = ws2812_program_get_default_config(offset);
+ sm_config_set_sideset_pins(&c, pin);
+ sm_config_set_out_shift(&c, false, true, rgbw ? 32 : 24);
+ sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX);
+
+ int cycles_per_bit = ws2812_T1 + ws2812_T2 + ws2812_T3;
+ float div = clock_get_hz(clk_sys) / (freq * cycles_per_bit);
+ sm_config_set_clkdiv(&c, div);
+
+ pio_sm_init(pio, sm, offset, &c);
+ pio_sm_set_enabled(pio, sm, true);
+}
+%}
diff --git a/harmony/Tests/AudioTests/RingBufferTests.swift b/harmony/Tests/AudioTests/RingBufferTests.swift
new file mode 100644
index 00000000..70e119e9
--- /dev/null
+++ b/harmony/Tests/AudioTests/RingBufferTests.swift
@@ -0,0 +1,177 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+import XCTest
+
+@testable import Core
+
+extension RingBuffer {
+ mutating func write(contentsOf array: [Element]) -> Bool {
+ array.withUnsafeBufferPointer {
+ self.write(contentsOf: $0)
+ }
+ }
+
+ mutating func read(into array: inout [Element], count: Int? = nil) -> Int {
+ array.withUnsafeMutableBufferPointer { buffer in
+ self.read(into: buffer, count: count)
+ }
+ }
+
+ func assertState(
+ count: Int,
+ readerIndex: Int,
+ writerIndex: Int,
+ file: StaticString = #filePath,
+ line: UInt = #line
+ ) {
+ XCTAssertEqual(
+ self.availableCapacity, self.capacity - count,
+ "incorrect availableCapacity", file: file, line: line)
+ XCTAssertEqual(
+ self.isEmpty, (count == 0), "incorrect isEmpty", file: file, line: line)
+ XCTAssertEqual(
+ self.isFull, (count == self.capacity), "incorrect isFull", file: file,
+ line: line)
+ XCTAssertEqual(self.count, count, "incorrect count", file: file, line: line)
+ XCTAssertEqual(
+ self.readerIndex, readerIndex, "incorrect readerIndex", file: file,
+ line: line)
+ XCTAssertEqual(
+ self.writerIndex, writerIndex, "incorrect writerIndex", file: file,
+ line: line)
+ if self.isEmpty || self.isFull {
+ XCTAssertEqual(self.readerIndex, self.writerIndex, file: file, line: line)
+ }
+ }
+}
+
+final class RingBufferTests: XCTestCase {
+ func testInitialization() {
+ let ringBuffer = RingBuffer(capacity: 10)
+ XCTAssertEqual(ringBuffer.capacity, 10)
+ ringBuffer.assertState(count: 0, readerIndex: 0, writerIndex: 0)
+ }
+
+ func testCapacityAndAvailableCapacity() {
+ var ringBuffer = RingBuffer(capacity: 5)
+ ringBuffer.assertState(count: 0, readerIndex: 0, writerIndex: 0)
+
+ XCTAssertTrue(ringBuffer.write(contentsOf: [1, 2, 3]))
+ ringBuffer.assertState(count: 3, readerIndex: 0, writerIndex: 3)
+
+ XCTAssertTrue(ringBuffer.write(contentsOf: [4, 5]))
+ ringBuffer.assertState(count: 5, readerIndex: 0, writerIndex: 0)
+ }
+
+ func testWriteAndRead() {
+ var ringBuffer = RingBuffer(capacity: 5)
+
+ // Write data to the buffer
+ XCTAssertTrue(ringBuffer.write(contentsOf: [1, 2, 3]))
+ ringBuffer.assertState(count: 3, readerIndex: 0, writerIndex: 3)
+
+ // Attempt to read from the buffer
+ var readBuffer = Array(repeating: 0, count: 3)
+ let readCount = ringBuffer.read(into: &readBuffer)
+ XCTAssertEqual(readCount, 3)
+ XCTAssertEqual(readBuffer, [1, 2, 3])
+ ringBuffer.assertState(count: 0, readerIndex: 3, writerIndex: 3)
+ }
+
+ func testOverwriteBehavior() {
+ var ringBuffer = RingBuffer(capacity: 3)
+
+ // Fill buffer to capacity
+ XCTAssertTrue(ringBuffer.write(contentsOf: [1, 2, 3]))
+ ringBuffer.assertState(count: 3, readerIndex: 0, writerIndex: 0)
+
+ // Attempt to overwrite when full
+ XCTAssertFalse(ringBuffer.write(contentsOf: [4]))
+ ringBuffer.assertState(count: 3, readerIndex: 0, writerIndex: 0)
+
+ // Read and check if the buffer remains unaltered
+ var readBuffer = Array(repeating: 0, count: 3)
+ let readCount = ringBuffer.read(into: &readBuffer)
+ XCTAssertEqual(readCount, 3)
+ XCTAssertEqual(readBuffer, [1, 2, 3])
+ ringBuffer.assertState(count: 0, readerIndex: 0, writerIndex: 0)
+ }
+
+ func testClearBuffer() {
+ var ringBuffer = RingBuffer(capacity: 5)
+ XCTAssertTrue(ringBuffer.write(contentsOf: [1, 2, 3]))
+ ringBuffer.assertState(count: 3, readerIndex: 0, writerIndex: 3)
+
+ ringBuffer.clear()
+ ringBuffer.assertState(count: 0, readerIndex: 0, writerIndex: 0)
+ }
+
+ func testWrappingBehavior() {
+ var ringBuffer = RingBuffer(capacity: 5)
+
+ // Step 1: Write some data to fill part of the buffer
+ XCTAssertTrue(ringBuffer.write(contentsOf: [1, 2, 3]))
+ ringBuffer.assertState(count: 3, readerIndex: 0, writerIndex: 3)
+
+ // Step 2: Read some data, advancing the reader index
+ var readBuffer = Array(repeating: 0, count: 2)
+ let readCount = ringBuffer.read(into: &readBuffer)
+ XCTAssertEqual(readCount, 2)
+ XCTAssertEqual(readBuffer, [1, 2])
+ ringBuffer.assertState(count: 1, readerIndex: 2, writerIndex: 3)
+
+ // Step 3: Write more data, causing the writer index to wrap around
+ XCTAssertTrue(ringBuffer.write(contentsOf: [4, 5, 6]))
+ ringBuffer.assertState(count: 4, readerIndex: 2, writerIndex: 1)
+
+ // Step 4: Read remaining data to verify the wrap-around behavior
+ readBuffer = Array(repeating: 0, count: 4)
+ let totalReadCount = ringBuffer.read(into: &readBuffer)
+ XCTAssertEqual(totalReadCount, 4)
+ XCTAssertEqual(readBuffer, [3, 4, 5, 6])
+ ringBuffer.assertState(count: 0, readerIndex: 1, writerIndex: 1)
+ }
+
+ func testWrappingWriteOverflowAndWrappingReadUnderflow() {
+ var ringBuffer = RingBuffer(capacity: 5)
+
+ // Step 1: Fill the buffer almost to capacity
+ XCTAssertTrue(ringBuffer.write(contentsOf: [1, 2, 3]))
+ ringBuffer.assertState(count: 3, readerIndex: 0, writerIndex: 3)
+
+ // Step 2: Read some data to advance the reader index
+ var readBuffer = Array(repeating: 0, count: 2)
+ let readCount = ringBuffer.read(into: &readBuffer)
+ XCTAssertEqual(readCount, 2)
+ XCTAssertEqual(readBuffer, [1, 2])
+ ringBuffer.assertState(count: 1, readerIndex: 2, writerIndex: 3)
+
+ // Step 3: Write more data to cause the writer index to wrap around
+ XCTAssertTrue(ringBuffer.write(contentsOf: [4, 5, 6]))
+ // Writer wraps around
+ ringBuffer.assertState(count: 4, readerIndex: 2, writerIndex: 1)
+
+ // Step 4: Attempt a write that overflows (fails due to lack of capacity)
+ XCTAssertFalse(ringBuffer.write(contentsOf: [7, 8, 9]))
+ // State remains unchanged
+ ringBuffer.assertState(count: 4, readerIndex: 2, writerIndex: 1)
+
+ // Step 5: Read more data than available to test wrapping underflow
+ readBuffer = Array(repeating: 0, count: 5)
+ let underflowReadCount = ringBuffer.read(into: &readBuffer)
+ XCTAssertEqual(underflowReadCount, 4) // Should only read 4 elements
+ // Validate read data
+ XCTAssertEqual(readBuffer.prefix(underflowReadCount), [3, 4, 5, 6])
+ // Reader wraps around
+ ringBuffer.assertState(count: 0, readerIndex: 1, writerIndex: 1)
+ }
+}
diff --git a/harmony/assets/harmony.jpeg b/harmony/assets/harmony.jpeg
new file mode 100644
index 00000000..c8ff0dab
Binary files /dev/null and b/harmony/assets/harmony.jpeg differ
diff --git a/harmony/include/btstack_config.h b/harmony/include/btstack_config.h
new file mode 100644
index 00000000..1b969e1b
--- /dev/null
+++ b/harmony/include/btstack_config.h
@@ -0,0 +1,89 @@
+#ifndef _PICO_BTSTACK_BTSTACK_CONFIG_H
+#define _PICO_BTSTACK_BTSTACK_CONFIG_H
+
+// BTstack features that can be enabled
+#define ENABLE_LOG_INFO
+#define ENABLE_LOG_ERROR
+#define ENABLE_PRINTF_HEXDUMP
+#define ENABLE_SCO_OVER_HCI
+
+#ifdef ENABLE_BLE
+#define ENABLE_GATT_CLIENT_PAIRING
+#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE
+#define ENABLE_LE_CENTRAL
+#define ENABLE_LE_DATA_LENGTH_EXTENSION
+#define ENABLE_LE_PERIPHERAL
+#define ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION
+#define ENABLE_LE_SECURE_CONNECTIONS
+#endif
+
+#ifdef ENABLE_CLASSIC
+#define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
+#define ENABLE_GOEP_L2CAP
+#endif
+
+#if defined (ENABLE_CLASSIC) && defined(ENABLE_BLE)
+#define ENABLE_CROSS_TRANSPORT_KEY_DERIVATION
+#endif
+
+// BTstack configuration. buffers, sizes, ...
+#define HCI_OUTGOING_PRE_BUFFER_SIZE 4
+#define HCI_ACL_PAYLOAD_SIZE (1691 + 4)
+#define HCI_ACL_CHUNK_SIZE_ALIGNMENT 4
+#define MAX_NR_AVDTP_CONNECTIONS 1
+#define MAX_NR_AVDTP_STREAM_ENDPOINTS 1
+#define MAX_NR_AVRCP_CONNECTIONS 2
+#define MAX_NR_BNEP_CHANNELS 1
+#define MAX_NR_BNEP_SERVICES 1
+#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2
+#define MAX_NR_GATT_CLIENTS 1
+#define MAX_NR_HCI_CONNECTIONS 2
+#define MAX_NR_HID_HOST_CONNECTIONS 1
+#define MAX_NR_HIDS_CLIENTS 1
+#define MAX_NR_HFP_CONNECTIONS 1
+#define MAX_NR_L2CAP_CHANNELS 4
+#define MAX_NR_L2CAP_SERVICES 3
+#define MAX_NR_RFCOMM_CHANNELS 1
+#define MAX_NR_RFCOMM_MULTIPLEXERS 1
+#define MAX_NR_RFCOMM_SERVICES 1
+#define MAX_NR_SERVICE_RECORD_ITEMS 4
+#define MAX_NR_SM_LOOKUP_ENTRIES 3
+#define MAX_NR_WHITELIST_ENTRIES 16
+#define MAX_NR_LE_DEVICE_DB_ENTRIES 16
+
+// Limit number of ACL/SCO Buffer to use by stack to avoid cyw43 shared bus overrun
+#define MAX_NR_CONTROLLER_ACL_BUFFERS 3
+#define MAX_NR_CONTROLLER_SCO_PACKETS 3
+
+// Enable and configure HCI Controller to Host Flow Control to avoid cyw43 shared bus overrun
+#define ENABLE_HCI_CONTROLLER_TO_HOST_FLOW_CONTROL
+#define HCI_HOST_ACL_PACKET_LEN 1024
+#define HCI_HOST_ACL_PACKET_NUM 3
+#define HCI_HOST_SCO_PACKET_LEN 120
+#define HCI_HOST_SCO_PACKET_NUM 3
+
+// Link Key DB and LE Device DB using TLV on top of Flash Sector interface
+#define NVM_NUM_DEVICE_DB_ENTRIES 16
+#define NVM_NUM_LINK_KEYS 16
+
+// We don't give btstack a malloc, so use a fixed-size ATT DB.
+#define MAX_ATT_DB_SIZE 512
+
+// BTstack HAL configuration
+#define HAVE_EMBEDDED_TIME_MS
+
+// map btstack_assert onto Pico SDK assert()
+#define HAVE_ASSERT
+
+// Some USB dongles take longer to respond to HCI reset (e.g. BCM20702A).
+#define HCI_RESET_RESEND_TIMEOUT_MS 1000
+
+#define ENABLE_SOFTWARE_AES128
+#define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS
+
+#define HAVE_BTSTACK_STDIN
+
+// To get the audio demos working even with HCI dump at 115200, this truncates long ACL packets
+//#define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100
+
+#endif // _PICO_BTSTACK_BTSTACK_CONFIG_H
diff --git a/harmony/include/lwipopts.h b/harmony/include/lwipopts.h
new file mode 100644
index 00000000..fefe1e4b
--- /dev/null
+++ b/harmony/include/lwipopts.h
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift.org open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LWIPOPTS_H
+#define _LWIPOPTS_H
+
+#define NO_SYS 1
+#define LWIP_SOCKET 0
+#define LWIP_NETCONN 0
+
+// Watch out: Without this, lwip fails to initialize and crashes inside
+// memp_init_pool due to misaligned memory access (the fallback is "1").
+#define MEM_ALIGNMENT 4
+
+#endif
diff --git a/pico-blink-sdk/CMakeLists.txt b/pico-blink-sdk/CMakeLists.txt
index 0553c8e0..63a9a58d 100644
--- a/pico-blink-sdk/CMakeLists.txt
+++ b/pico-blink-sdk/CMakeLists.txt
@@ -1,38 +1,45 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.29)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
+set(CMAKE_Swift_COMPILATION_MODE wholemodule)
+set(CMAKE_Swift_COMPILER_WORKS YES)
+
project(swift-blinky)
pico_sdk_init()
-
-if(APPLE)
-execute_process(COMMAND xcrun -f swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
-else()
-execute_process(COMMAND which swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
-endif()
+enable_language(Swift)
set(SWIFT_TARGET "armv6m-none-none-eabi") # default for rp2040
if(PICO_PLATFORM STREQUAL "rp2350-arm-s")
message(STATUS "PICO_PLATFORM is set to rp2350-arm-s, using armv7em")
set(SWIFT_TARGET "armv7em-none-none-eabi")
- list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc" "-mfloat-abi=soft")
+ list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc -mfloat-abi=soft")
elseif(PICO_PLATFORM STREQUAL "rp2040")
message(STATUS "PICO_PLATFORM is set to RP2040, using armv6m")
- list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc" "-mfloat-abi=soft")
+ list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc -mfloat-abi=soft")
elseif(PICO_PLATFORM STREQUAL "rp2350-riscv")
message(STATUS "PICO_PLATFORM is set to rp2350-riscv, using riscv32.")
set(SWIFT_TARGET "riscv32-none-none-eabi")
- list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc" "-march=rv32imac_zicsr_zifencei_zba_zbb_zbs_zbkb" "-Xcc" "-mabi=ilp32")
+ list(APPEND CLANG_ARCH_ABI_FLAGS "-Xcc -march=rv32imac_zicsr_zifencei_zba_zbb_zbs_zbkb -Xcc -mabi=ilp32")
endif()
-add_executable(swift-blinky)
+add_executable(swift-blinky
+ # Source files:
+ Main.swift
+)
+
+set_target_properties(swift-blinky PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(swift-blinky
pico_stdlib hardware_uart hardware_gpio
)
-# Gather compile definitions from all dependencies
+# Clear the default COMPILE_OPTIONS which include C specific compiler flags that the Swift compiler will not accept
+# Instead, set those options to only apply when compiling C code.
+set_target_properties(pico_standard_link PROPERTIES INTERFACE_COMPILE_OPTIONS "")
+target_compile_options(pico_standard_link INTERFACE "$<$:SHELL: -ffunction-sections -fdata-sections>")
+# Gather C compile definitions from all dependencies
set_property(GLOBAL PROPERTY visited_targets "")
set_property(GLOBAL PROPERTY compilerdefs_list "")
@@ -42,7 +49,7 @@ function(gather_compile_definitions_recursive target)
# make sure we don't visit the same target twice
# and that we don't visit the special generator expressions
- if (${target} MATCHES "\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
+ if (${target} MATCHES "\\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
return()
endif()
@@ -50,12 +57,10 @@ function(gather_compile_definitions_recursive target)
list(APPEND visited_targets ${target})
set_property(GLOBAL PROPERTY visited_targets "${visited_targets}")
- # Get the current value of compilerdefs_list
- get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)
-
get_target_property(target_definitions ${target} INTERFACE_COMPILE_DEFINITIONS)
if (target_definitions)
# Append the target definitions to compilerdefs_list
+ get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)
list(APPEND compilerdefs_list ${target_definitions})
set_property(GLOBAL PROPERTY compilerdefs_list "${compilerdefs_list}")
endif()
@@ -71,35 +76,38 @@ endfunction()
gather_compile_definitions_recursive(swift-blinky)
get_property(COMPILE_DEFINITIONS GLOBAL PROPERTY compilerdefs_list)
+get_property(INCLUDES GLOBAL PROPERTY includes_list)
-# Parse compiler definitions into a format that swiftc can understand
+# Convert compiler definitions into a format that swiftc can understand
list(REMOVE_DUPLICATES COMPILE_DEFINITIONS)
-list(PREPEND COMPILE_DEFINITIONS "")
+list(PREPEND COMPILE_DEFINITIONS "") # adds a semicolon at the beginning
string(REPLACE "$" "$" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
-string(REPLACE ";" ";-Xcc;-D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
-
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
- COMMAND
- ${SWIFTC}
- -target ${SWIFT_TARGET} -Xcc -fshort-enums
- ${COMPILE_DEFINITIONS}
+string(REPLACE ";" " -Xcc -D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
+
+# Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header).
+set(IMPLICIT_INCLUDES)
+foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
+endforeach()
+foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
+endforeach()
+
+target_compile_options(swift-blinky PUBLIC
+ "$<$:SHELL:
+ -target ${SWIFT_TARGET}
+ -enable-experimental-feature Embedded
+ -parse-as-library
+ -module-name swift_blinky
+
${CLANG_ARCH_ABI_FLAGS}
- -Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library
- $$\( echo '$' | tr '\;' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
- $$\( echo '${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}' | tr ' ' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
+ -Xcc -fshort-enums
+ -Xfrontend -function-sections
-import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
- ${CMAKE_CURRENT_LIST_DIR}/Main.swift
- -c -o ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
- DEPENDS
- ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
- ${CMAKE_CURRENT_LIST_DIR}/Main.swift
-)
-add_custom_target(swift-blinky-swiftcode DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o)
-
+ ${COMPILE_DEFINITIONS}
+ ${IMPLICIT_INCLUDES}
+ >")
-target_link_libraries(swift-blinky
- ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
-)
-add_dependencies(swift-blinky swift-blinky-swiftcode)
pico_add_extra_outputs(swift-blinky)
diff --git a/pico-blink-sdk/Main.swift b/pico-blink-sdk/Main.swift
index 060bc5f7..74c0d7af 100644
--- a/pico-blink-sdk/Main.swift
+++ b/pico-blink-sdk/Main.swift
@@ -14,7 +14,7 @@ struct Main {
static func main() {
let led = UInt32(PICO_DEFAULT_LED_PIN)
gpio_init(led)
- gpio_set_dir(led, /*out*/ true)
+ gpio_set_dir(led, true)
while true {
gpio_put(led, true)
sleep_ms(250)
diff --git a/pico-blink-sdk/README.md b/pico-blink-sdk/README.md
index 463c0653..a0b45830 100644
--- a/pico-blink-sdk/README.md
+++ b/pico-blink-sdk/README.md
@@ -28,7 +28,7 @@ $ export PICO_BOARD='' # Examples: pico, pico2
$ export PICO_PLATFORM='' # Optional; useful if you'd like to compile for RISC-V. Examples: rp2040, rp2350-arm-s, rp2350-riscv
$ export PICO_SDK_PATH=''
$ export PICO_TOOLCHAIN_PATH='' # A default `brew` install will be located at `/Applications/ArmGNUToolchain/[version]/arm-none-eabi`. This can also be a RISC-V toolchain for the RP2350.
-$ cmake -B build -G Ninja .
+$ cmake -B build -G Ninja . -DCMAKE_EXPORT_COMPILE_COMMANDS=On
$ cmake --build build
```
diff --git a/pico-w-blink-sdk/CMakeLists.txt b/pico-w-blink-sdk/CMakeLists.txt
index a59fa29f..41cb7fcd 100644
--- a/pico-w-blink-sdk/CMakeLists.txt
+++ b/pico-w-blink-sdk/CMakeLists.txt
@@ -1,21 +1,30 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.29)
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
+set(CMAKE_Swift_COMPILATION_MODE wholemodule)
+set(CMAKE_Swift_COMPILER_WORKS YES)
+
project(swift-blinky)
pico_sdk_init()
+enable_language(Swift)
+
+add_executable(swift-blinky
+ # Source files:
+ Main.swift
+)
-if(APPLE)
-execute_process(COMMAND xcrun -f swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
-else()
-execute_process(COMMAND which swiftc OUTPUT_VARIABLE SWIFTC OUTPUT_STRIP_TRAILING_WHITESPACE)
-endif()
+set_target_properties(swift-blinky PROPERTIES LINKER_LANGUAGE CXX)
-add_executable(swift-blinky)
target_link_libraries(swift-blinky
pico_stdlib hardware_uart hardware_gpio pico_lwip_arch pico_cyw43_arch_none
)
-# Gather compile definitions from all dependencies
+# Clear the default COMPILE_OPTIONS which include C specific compiler flags that the Swift compiler will not accept
+# Instead, set those options to only apply when compiling C code.
+set_target_properties(pico_standard_link PROPERTIES INTERFACE_COMPILE_OPTIONS "")
+target_compile_options(pico_standard_link INTERFACE "$<$:SHELL: -ffunction-sections -fdata-sections>")
+
+# Gather C compile definitions from all dependencies
set_property(GLOBAL PROPERTY visited_targets "")
set_property(GLOBAL PROPERTY compilerdefs_list "")
@@ -25,7 +34,7 @@ function(gather_compile_definitions_recursive target)
# make sure we don't visit the same target twice
# and that we don't visit the special generator expressions
- if (${target} MATCHES "\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
+ if (${target} MATCHES "\\\$<" OR ${target} MATCHES "::@" OR ${target} IN_LIST visited_targets)
return()
endif()
@@ -33,12 +42,10 @@ function(gather_compile_definitions_recursive target)
list(APPEND visited_targets ${target})
set_property(GLOBAL PROPERTY visited_targets "${visited_targets}")
- # Get the current value of compilerdefs_list
- get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)
-
get_target_property(target_definitions ${target} INTERFACE_COMPILE_DEFINITIONS)
if (target_definitions)
# Append the target definitions to compilerdefs_list
+ get_property(compilerdefs_list GLOBAL PROPERTY compilerdefs_list)
list(APPEND compilerdefs_list ${target_definitions})
set_property(GLOBAL PROPERTY compilerdefs_list "${compilerdefs_list}")
endif()
@@ -54,37 +61,37 @@ endfunction()
gather_compile_definitions_recursive(swift-blinky)
get_property(COMPILE_DEFINITIONS GLOBAL PROPERTY compilerdefs_list)
+get_property(INCLUDES GLOBAL PROPERTY includes_list)
-# Parse compiler definitions into a format that swiftc can understand
+# Convert compiler definitions into a format that swiftc can understand
list(REMOVE_DUPLICATES COMPILE_DEFINITIONS)
list(PREPEND COMPILE_DEFINITIONS "") # adds a semicolon at the beginning
string(REPLACE "$" "$" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
-string(REPLACE ";" ";-Xcc;-D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
+string(REPLACE ";" " -Xcc -D" COMPILE_DEFINITIONS "${COMPILE_DEFINITIONS}")
-add_custom_command(
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
- COMMAND
- ${SWIFTC}
- -target armv6m-none-none-eabi -Xcc -mfloat-abi=soft -Xcc -fshort-enums
- ${COMPILE_DEFINITIONS}
- -Xcc -DCYW43_LWIP
- -Xcc -DPICO_CYW43_ARCH_THREADSAFE_BACKGROUND
- -Xcc -I$ENV{PICO_SDK_PATH}/lib/lwip/src/include
- -Xcc -I${CMAKE_CURRENT_LIST_DIR}/include
- -Xfrontend -function-sections -enable-experimental-feature Embedded -wmo -parse-as-library
- $$\( echo '$' | tr '\;' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
- $$\( echo '${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES}' | tr ' ' '\\n' | sed -e 's/\\\(.*\\\)/-Xcc -I\\1/g' \)
+# Compute -Xcc flags to set up the C and C++ header search paths for Swift (for bridging header).
+set(IMPLICIT_INCLUDES)
+foreach(dir ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
+endforeach()
+foreach(dir ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-Xcc ")
+ string(CONCAT IMPLICIT_INCLUDES ${IMPLICIT_INCLUDES} "-I${dir} ")
+endforeach()
+
+target_compile_options(swift-blinky PUBLIC
+ "$<$:SHELL:
+ -target armv6m-none-none-eabi
+ -enable-experimental-feature Embedded
+ -parse-as-library
+ -module-name swift_blinky
+
+ -Xcc -fshort-enums
+ -Xfrontend -function-sections
-import-bridging-header ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
- ${CMAKE_CURRENT_LIST_DIR}/Main.swift
- -c -o ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
- DEPENDS
- ${CMAKE_CURRENT_LIST_DIR}/BridgingHeader.h
- ${CMAKE_CURRENT_LIST_DIR}/Main.swift
-)
-add_custom_target(swift-blinky-swiftcode DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o)
+ ${COMPILE_DEFINITIONS}
+ ${IMPLICIT_INCLUDES}
+ >")
-target_link_libraries(swift-blinky
- ${CMAKE_CURRENT_BINARY_DIR}/_swiftcode.o
-)
-add_dependencies(swift-blinky swift-blinky-swiftcode)
pico_add_extra_outputs(swift-blinky)
diff --git a/pico-w-blink-sdk/README.md b/pico-w-blink-sdk/README.md
index d8a114af..72702188 100644
--- a/pico-w-blink-sdk/README.md
+++ b/pico-w-blink-sdk/README.md
@@ -26,7 +26,7 @@ $ export TOOLCHAINS=''
$ export PICO_BOARD=pico_w
$ export PICO_SDK_PATH=''
$ export PICO_TOOLCHAIN_PATH=''
-$ cmake -B build -G Ninja .
+$ cmake -B build -G Ninja . -DCMAKE_EXPORT_COMPILE_COMMANDS=On
$ cmake --build build
```
diff --git a/rpi4b-blink/Makefile b/rpi4b-blink/Makefile
new file mode 100644
index 00000000..da37442b
--- /dev/null
+++ b/rpi4b-blink/Makefile
@@ -0,0 +1,28 @@
+SWIFT_EXEC ?= $(shell if [ "$(shell uname)" = "Darwin" ]; then xcrun -f swift; else which swift; fi)
+CLANG ?= $(shell if [ "$(shell uname)" = "Darwin" ]; then xcrun -f clang; else which clang; fi)
+LLVM_OBJCOPY ?= $(shell if [ "$(shell uname)" = "Darwin" ]; then xcrun -f llvm-objcopy; else which llvm-objcopy; fi)
+
+BUILDROOT := $(shell $(SWIFT_EXEC) build --triple aarch64-none-none-elf -Xswiftc -Xfrontend -Xswiftc -disable-stack-protector --show-bin-path)
+
+.PHONY: all clean
+
+all: kernel8.img
+
+kernel8.img: kernel8.elf
+ @echo "💾 Converting to binary kernel image with llvm-objcopy..."
+ $(LLVM_OBJCOPY) -O binary kernel8.elf kernel8.img
+ @echo ""
+ @echo "🥳 Done! kernel8.img was saved to this directory."
+
+kernel8.elf: $(BUILDROOT)/libMainApp.a $(BUILDROOT)/Support.build/boot.S.o link.ld
+ @echo "🔗 Linking with clang..."
+ $(CLANG) --target=aarch64-elf -o kernel8.elf $< $^ -fuse-ld=lld -nostdlib -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-T ./link.ld
+ @echo ""
+
+$(BUILDROOT)/libMainApp.a $(BUILDROOT)/Support.build/boot.S.o:
+ @echo "🛠️ Building with Swift Package Manager..."
+ $(SWIFT_EXEC) build --triple aarch64-none-none-elf -Xswiftc -Xfrontend -Xswiftc -disable-stack-protector
+ @echo ""
+
+clean:
+ rm -rf kernel8.elf kernel8.img .build
\ No newline at end of file
diff --git a/rpi4b-blink/Package.swift b/rpi4b-blink/Package.swift
new file mode 100644
index 00000000..f004c0b8
--- /dev/null
+++ b/rpi4b-blink/Package.swift
@@ -0,0 +1,36 @@
+// swift-tools-version: 6.1
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "RPi4B-Blink",
+ platforms: [
+ .macOS(.v14)
+ ],
+ products: [
+ .library(
+ name: "MainApp",
+ type: .static,
+ targets: ["MainApp"])
+ ],
+ dependencies: [
+ .package(
+ url: "https://github.com/apple/swift-mmio.git",
+ branch: "swift-embedded-examples")
+ ],
+ targets: [
+ .target(
+ name: "MainApp",
+ dependencies: [
+ .product(name: "MMIO", package: "swift-mmio")
+ ],
+ swiftSettings: [
+ .enableExperimentalFeature("Embedded"),
+ .unsafeFlags(["-Xfrontend", "-function-sections"]),
+ ]
+ ),
+ .target(name: "Support"),
+
+ ]
+)
diff --git a/rpi4b-blink/README.md b/rpi4b-blink/README.md
new file mode 100644
index 00000000..b68de6a5
--- /dev/null
+++ b/rpi4b-blink/README.md
@@ -0,0 +1,24 @@
+# rpi4b-blink
+
+
+
+## Requirements
+
+- A Raspberry Pi 4B board
+- An SD Card, with a Raspberry Pi OS installed (this way, we don't need to create the configuration files from scratch). You may backup `kernel8.img` and `config.txt` if you need the Linux install later, since we will change these files.
+- LLVM installed (`brew install llvm`) and added to PATH. This is needed to convert the resulted ELF file to binary image format using `llvm-objcopy`.
+
+## How to build and run this example:
+
+- Make sure you have a recent nightly Swift toolchain that has Embedded Swift support.
+- Build the program, then copy the kernel image to the SD card.
+``` console
+$ cd rpi4b-blink
+$ export TOOLCHAINS='' # Your Swift nightly toolchain identifier
+$ make
+$ cp kernel8.img /Volumes/bootfs
+```
+- If your original OS is not 64-bit, make sure to set `arm_64bit=1` in `config.txt`.
+- Place the SD card in your Raspberry Pi 4B, and connect it to power.
+- After the boot sequence, the green (ACT) led will start blinking in a regular pattern.
+
diff --git a/rpi4b-blink/Sources/MainApp/MainApp.swift b/rpi4b-blink/Sources/MainApp/MainApp.swift
new file mode 100644
index 00000000..eaef412f
--- /dev/null
+++ b/rpi4b-blink/Sources/MainApp/MainApp.swift
@@ -0,0 +1,82 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+import MMIO
+
+@Register(bitWidth: 32)
+struct GPSET1 {
+ @ReadWrite(bits: 10..<11, as: Bool.self)
+ var set: SET
+}
+
+@Register(bitWidth: 32)
+struct GPCLR1 {
+ @ReadWrite(bits: 10..<11, as: Bool.self)
+ var clear: CLEAR
+}
+
+@Register(bitWidth: 32)
+struct GPFSEL4 {
+ @ReadWrite(bits: 6..<7, as: Bool.self)
+ var fsel42b1: FSEL42b1
+ @ReadWrite(bits: 7..<8, as: Bool.self)
+ var fsel42b2: FSEL42b2
+ @ReadWrite(bits: 8..<9, as: Bool.self)
+ var fsel42b3: FSEL42b3
+}
+
+@RegisterBlock
+struct GPIO {
+ @RegisterBlock(offset: 0x200020)
+ var gpset1: Register
+ @RegisterBlock(offset: 0x20002c)
+ var gpclr1: Register
+ @RegisterBlock(offset: 0x200010)
+ var gpfsel4: Register
+}
+
+let gpio = GPIO(unsafeAddress: 0xFE00_0000)
+
+func setLedOutput() {
+ gpio.gpfsel4.modify {
+ // setFunction Select 42 (fsel42) to 001
+ $0.fsel42b1 = true
+ $0.fsel42b2 = false
+ $0.fsel42b3 = false
+ }
+}
+
+func ledOn() {
+ gpio.gpset1.modify {
+ $0.set = true
+ }
+}
+
+func ledOff() {
+ gpio.gpclr1.modify {
+ $0.clear = true
+ }
+}
+
+@main
+struct Main {
+
+ static func main() {
+ setLedOutput()
+
+ while true {
+ ledOn()
+ for _ in 1..<100000 {} // just a delay
+ ledOff()
+ for _ in 1..<100000 {} // just a delay
+ }
+ }
+}
diff --git a/rpi4b-blink/Sources/Support/boot.S b/rpi4b-blink/Sources/Support/boot.S
new file mode 100644
index 00000000..0a8f8c39
--- /dev/null
+++ b/rpi4b-blink/Sources/Support/boot.S
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+.section ".text.boot"
+
+.global _start
+
+_start:
+ // Check processor ID is zero (executing on main core), else hang
+ mrs x1, mpidr_el1
+ and x1, x1, #3
+ cbz x1, 2f
+ // We're not on the main core, so hang in an infinite wait loop
+1: wfe
+ b 1b
+2: // We're on the main core!
+
+ // Set stack to start below our code
+ ldr x1, =_start
+ mov sp, x1
+
+ // Clean the BSS section
+ ldr x1, =__bss_start // Start address
+ ldr w2, =__bss_size // Size of the section
+3: cbz w2, 4f // Quit loop if zero
+ str xzr, [x1], #8
+ sub w2, w2, #1
+ cbnz w2, 3b // Loop if non-zero
+
+ // Jump to Swift!
+4: bl main
+ // Halt if Swift returns
+ b 1b
diff --git a/rpi4b-blink/Sources/Support/include/boot.h b/rpi4b-blink/Sources/Support/include/boot.h
new file mode 100644
index 00000000..e69de29b
diff --git a/rpi4b-blink/assets/rpi4.png b/rpi4b-blink/assets/rpi4.png
new file mode 100644
index 00000000..1df6f1c3
Binary files /dev/null and b/rpi4b-blink/assets/rpi4.png differ
diff --git a/rpi4b-blink/link.ld b/rpi4b-blink/link.ld
new file mode 100644
index 00000000..dfbf0227
--- /dev/null
+++ b/rpi4b-blink/link.ld
@@ -0,0 +1,19 @@
+SECTIONS
+{
+ . = 0x80000; /* Kernel load address for AArch64 */
+ .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
+ PROVIDE(_data = .);
+ .data : { *(.data .data.* .gnu.linkonce.d*) }
+ .bss (NOLOAD) : {
+ . = ALIGN(16);
+ __bss_start = .;
+ *(.bss .bss.*)
+ *(COMMON)
+ __bss_end = .;
+ }
+ _end = .;
+
+ /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
+}
+__bss_size = (__bss_end - __bss_start)>>3;
diff --git a/rpi5-blink/Makefile b/rpi5-blink/Makefile
new file mode 100644
index 00000000..da37442b
--- /dev/null
+++ b/rpi5-blink/Makefile
@@ -0,0 +1,28 @@
+SWIFT_EXEC ?= $(shell if [ "$(shell uname)" = "Darwin" ]; then xcrun -f swift; else which swift; fi)
+CLANG ?= $(shell if [ "$(shell uname)" = "Darwin" ]; then xcrun -f clang; else which clang; fi)
+LLVM_OBJCOPY ?= $(shell if [ "$(shell uname)" = "Darwin" ]; then xcrun -f llvm-objcopy; else which llvm-objcopy; fi)
+
+BUILDROOT := $(shell $(SWIFT_EXEC) build --triple aarch64-none-none-elf -Xswiftc -Xfrontend -Xswiftc -disable-stack-protector --show-bin-path)
+
+.PHONY: all clean
+
+all: kernel8.img
+
+kernel8.img: kernel8.elf
+ @echo "💾 Converting to binary kernel image with llvm-objcopy..."
+ $(LLVM_OBJCOPY) -O binary kernel8.elf kernel8.img
+ @echo ""
+ @echo "🥳 Done! kernel8.img was saved to this directory."
+
+kernel8.elf: $(BUILDROOT)/libMainApp.a $(BUILDROOT)/Support.build/boot.S.o link.ld
+ @echo "🔗 Linking with clang..."
+ $(CLANG) --target=aarch64-elf -o kernel8.elf $< $^ -fuse-ld=lld -nostdlib -Wl,--unresolved-symbols=ignore-in-object-files -Wl,-T ./link.ld
+ @echo ""
+
+$(BUILDROOT)/libMainApp.a $(BUILDROOT)/Support.build/boot.S.o:
+ @echo "🛠️ Building with Swift Package Manager..."
+ $(SWIFT_EXEC) build --triple aarch64-none-none-elf -Xswiftc -Xfrontend -Xswiftc -disable-stack-protector
+ @echo ""
+
+clean:
+ rm -rf kernel8.elf kernel8.img .build
\ No newline at end of file
diff --git a/rpi5-blink/Package.resolved b/rpi5-blink/Package.resolved
new file mode 100644
index 00000000..1a6f57c0
--- /dev/null
+++ b/rpi5-blink/Package.resolved
@@ -0,0 +1,33 @@
+{
+ "originHash" : "193ca3f107e2c8dd2da5d091f6259f64b2cbfd6776d1c26bbcfb195b3a0b5045",
+ "pins" : [
+ {
+ "identity" : "swift-argument-parser",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-argument-parser.git",
+ "state" : {
+ "revision" : "41982a3656a71c768319979febd796c6fd111d5c",
+ "version" : "1.5.0"
+ }
+ },
+ {
+ "identity" : "swift-mmio",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-mmio.git",
+ "state" : {
+ "branch" : "swift-embedded-examples",
+ "revision" : "06d96ed4916739f2edafde87f3951b2d2a04df65"
+ }
+ },
+ {
+ "identity" : "swift-syntax",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/swiftlang/swift-syntax.git",
+ "state" : {
+ "revision" : "0687f71944021d616d34d922343dcef086855920",
+ "version" : "600.0.1"
+ }
+ }
+ ],
+ "version" : 3
+}
diff --git a/rpi5-blink/Package.swift b/rpi5-blink/Package.swift
new file mode 100644
index 00000000..a01f42ef
--- /dev/null
+++ b/rpi5-blink/Package.swift
@@ -0,0 +1,36 @@
+// swift-tools-version: 6.1
+// The swift-tools-version declares the minimum version of Swift required to build this package.
+
+import PackageDescription
+
+let package = Package(
+ name: "RPi5-Blink",
+ platforms: [
+ .macOS(.v14)
+ ],
+ products: [
+ .library(
+ name: "MainApp",
+ type: .static,
+ targets: ["MainApp"])
+ ],
+ dependencies: [
+ .package(
+ url: "https://github.com/apple/swift-mmio.git",
+ branch: "swift-embedded-examples")
+ ],
+ targets: [
+ .target(
+ name: "MainApp",
+ dependencies: [
+ .product(name: "MMIO", package: "swift-mmio")
+ ],
+ swiftSettings: [
+ .enableExperimentalFeature("Embedded"),
+ .unsafeFlags(["-Xfrontend", "-function-sections"]),
+ ]
+ ),
+ .target(name: "Support"),
+
+ ]
+)
diff --git a/rpi5-blink/README.md b/rpi5-blink/README.md
new file mode 100644
index 00000000..49c200b2
--- /dev/null
+++ b/rpi5-blink/README.md
@@ -0,0 +1,25 @@
+# rpi5-blink
+
+
+
+## Requirements
+
+- A Raspberry Pi 5 board
+- An SD Card, with a Raspberry Pi OS installed (this way, we don't need to create the configuration files from scratch). You may backup `kernel8.img` and `kernel_2712.img` if you need the Linux install later, since we will change these files.
+- LLVM installed (`brew install llvm`) and added to PATH. This is needed to convert the resulted ELF file to binary image format using `llvm-objcopy`.
+
+## How to build and run this example:
+
+- Make sure you have a recent nightly Swift toolchain that has Embedded Swift support.
+- Build the program, then copy the kernel image to the SD card.
+``` console
+$ cd rpi5-blink
+$ export TOOLCHAINS='' # Your Swift nightly toolchain identifier
+$ make
+$ cp kernel8.img /Volumes/bootfs # Copy kernel image to SD card
+$ rm /Volumes/bootfs/kernel_2712.img # Delete this kernel image so our kernel8.img is used
+$ # You can also rename our kernel8.img to kernel_2712.img, or set it to anything you want and specify "kernel=[your-img-name]" in config.txt.
+```
+- Place the SD card in your Raspberry Pi 5, and connect it to power.
+- After the boot sequence, the green (ACT) led will start blinking in a regular pattern.
+
diff --git a/rpi5-blink/Sources/MainApp/MainApp.swift b/rpi5-blink/Sources/MainApp/MainApp.swift
new file mode 100644
index 00000000..7bbae377
--- /dev/null
+++ b/rpi5-blink/Sources/MainApp/MainApp.swift
@@ -0,0 +1,56 @@
+import MMIO
+
+@Register(bitWidth: 32)
+struct GIOIODIR {
+ @ReadWrite(bits: 9..<10, as: Bool.self)
+ var direction: DIRECTION
+}
+
+@Register(bitWidth: 32)
+struct GIODATA {
+ @ReadWrite(bits: 9..<10, as: Bool.self)
+ var value: VALUE
+}
+
+@RegisterBlock
+struct GPIO {
+ @RegisterBlock(offset: 0x00008)
+ var gioiodir: Register
+ @RegisterBlock(offset: 0x00004)
+ var giodata: Register
+}
+
+let gpio = GPIO(unsafeAddress: 0x10_7d51_7c00)
+
+func setLedOutput() {
+ gpio.gioiodir.modify {
+ $0.direction = false // 0 is output, 1 is input
+ }
+}
+
+func ledOn() {
+ gpio.giodata.modify {
+ $0.value = true // pin on
+ }
+}
+
+func ledOff() {
+ gpio.giodata.modify {
+ $0.value = false // pin off
+ }
+}
+
+@main
+struct Main {
+
+ static func main() {
+ setLedOutput()
+
+ while true {
+ ledOn()
+ for _ in 1..<100000 {} // just a delay
+ ledOff()
+ for _ in 1..<100000 {} // just a delay
+ }
+ }
+}
diff --git a/rpi5-blink/Sources/Support/boot.S b/rpi5-blink/Sources/Support/boot.S
new file mode 100644
index 00000000..0a8f8c39
--- /dev/null
+++ b/rpi5-blink/Sources/Support/boot.S
@@ -0,0 +1,41 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+.section ".text.boot"
+
+.global _start
+
+_start:
+ // Check processor ID is zero (executing on main core), else hang
+ mrs x1, mpidr_el1
+ and x1, x1, #3
+ cbz x1, 2f
+ // We're not on the main core, so hang in an infinite wait loop
+1: wfe
+ b 1b
+2: // We're on the main core!
+
+ // Set stack to start below our code
+ ldr x1, =_start
+ mov sp, x1
+
+ // Clean the BSS section
+ ldr x1, =__bss_start // Start address
+ ldr w2, =__bss_size // Size of the section
+3: cbz w2, 4f // Quit loop if zero
+ str xzr, [x1], #8
+ sub w2, w2, #1
+ cbnz w2, 3b // Loop if non-zero
+
+ // Jump to Swift!
+4: bl main
+ // Halt if Swift returns
+ b 1b
diff --git a/rpi5-blink/Sources/Support/include/boot.h b/rpi5-blink/Sources/Support/include/boot.h
new file mode 100644
index 00000000..e69de29b
diff --git a/rpi5-blink/assets/raspi5.png b/rpi5-blink/assets/raspi5.png
new file mode 100644
index 00000000..3fb4451f
Binary files /dev/null and b/rpi5-blink/assets/raspi5.png differ
diff --git a/rpi5-blink/link.ld b/rpi5-blink/link.ld
new file mode 100644
index 00000000..dfbf0227
--- /dev/null
+++ b/rpi5-blink/link.ld
@@ -0,0 +1,19 @@
+SECTIONS
+{
+ . = 0x80000; /* Kernel load address for AArch64 */
+ .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) }
+ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) }
+ PROVIDE(_data = .);
+ .data : { *(.data .data.* .gnu.linkonce.d*) }
+ .bss (NOLOAD) : {
+ . = ALIGN(16);
+ __bss_start = .;
+ *(.bss .bss.*)
+ *(COMMON)
+ __bss_end = .;
+ }
+ _end = .;
+
+ /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) }
+}
+__bss_size = (__bss_end - __bss_start)>>3;
diff --git a/stm32-blink/Board.swift b/stm32-blink/Board.swift
new file mode 100644
index 00000000..130932e2
--- /dev/null
+++ b/stm32-blink/Board.swift
@@ -0,0 +1,115 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2023 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+#if STM32F746G_DISCOVERY
+
+typealias Board = STM32F746Board
+enum STM32F746Board {
+ static func initialize() {
+ // (1) AHB1ENR[lecConfig.0] = 1 ... enable clock
+ setRegisterBit(
+ baseAddress: RCC.BaseAddress, offset: RCC.Offsets.AHB1ENR,
+ bit: RCC.AHB1ENRBit(for: ledConfig.0),
+ value: 1)
+ // (2) MODER[1] = 1 ... set mode to output
+ setRegisterTwoBitField(
+ baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.MODER,
+ bitsStartingAt: 2 * ledConfig.1, value: 1)
+ // (3) OTYPER[1] = 0 ... output type is push-pull
+ setRegisterBit(
+ baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.OTYPER,
+ bit: ledConfig.1,
+ value: 0)
+ // (4) OSPEEDR[1] = 2 ... speed is high
+ setRegisterTwoBitField(
+ baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.OSPEEDR,
+ bitsStartingAt: 2 * ledConfig.1, value: 2)
+ // (5) PUPDR[1] = 2 ... set pull to down
+ setRegisterTwoBitField(
+ baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.PUPDR,
+ bitsStartingAt: 2 * ledConfig.1, value: 2)
+
+ ledOff()
+ }
+
+ static func ledOn() {
+ // ODR[1] = 1
+ setRegisterBit(
+ baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.ODR, bit: 1,
+ value: 1)
+ }
+
+ static func ledOff() {
+ // ODR[1] = 0
+ setRegisterBit(
+ baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.ODR, bit: 1,
+ value: 0)
+ }
+
+ static func delay(milliseconds: Int) {
+ for _ in 0..<10_000 * milliseconds {
+ nop()
+ }
+ }
+}
+
+#elseif NUCLEO_F103RB
+
+typealias Board = STM32F1Board
+enum STM32F1Board {
+ static func initialize() {
+ // (1) APB2ENR[ledConfig.0] = 1 ... enable clock
+ setRegisterBit(
+ baseAddress: RCC.BaseAddress, offset: RCC.Offsets.APB2ENR,
+ bit: RCC.APB2ENRBit(for: ledConfig.0),
+ value: 1)
+ // (2) CRL.MODE[ledConfig.1] = 0b11 ... set mode to output, high speed
+ setRegisterTwoBitField(
+ baseAddress: GPIO.GPIOBaseAddress(for: ledConfig.0),
+ offset: GPIO.Offsets.CRL,
+ bitsStartingAt: 4 * ledConfig.1, value: 3)
+ // (3) CRL.CNF[ledConfig.1] = 0b00 ... general purpose, push-pull
+ setRegisterTwoBitField(
+ baseAddress: GPIO.GPIOBaseAddress(for: ledConfig.0),
+ offset: GPIO.Offsets.CRL,
+ bitsStartingAt: 4 * ledConfig.1 + 2, value: 0)
+
+ ledOff()
+ }
+
+ static func ledOn() {
+ // ODR[ledConfig.1] = 1
+ setRegisterBit(
+ baseAddress: GPIO.GPIOBaseAddress(for: ledConfig.0),
+ offset: GPIO.Offsets.ODR, bit: ledConfig.1,
+ value: 1)
+ }
+
+ static func ledOff() {
+ // ODR[ledConfig.1] = 0
+ setRegisterBit(
+ baseAddress: GPIO.GPIOBaseAddress(for: ledConfig.0),
+ offset: GPIO.Offsets.ODR, bit: ledConfig.1,
+ value: 0)
+ }
+
+ static func delay(milliseconds: Int) {
+ for _ in 0..<10_000 * milliseconds {
+ nop()
+ }
+ }
+}
+
+#else
+
+#error("Unknown board")
+
+#endif
diff --git a/stm32-blink/BridgingHeader.h b/stm32-blink/BridgingHeader.h
index 5a160e8b..6b807332 100644
--- a/stm32-blink/BridgingHeader.h
+++ b/stm32-blink/BridgingHeader.h
@@ -11,16 +11,6 @@
#pragma once
-#include
-
-static inline __attribute((always_inline)) uint32_t volatile_load_uint32_t(const volatile uint32_t * _Nonnull source) {
- return *((const volatile uint32_t * _Nonnull) source);
-}
-
-static inline __attribute((always_inline)) void volatile_store_uint32_t(volatile uint32_t * _Nonnull destination, uint32_t value) {
- *((volatile uint32_t * _Nonnull) destination) = value;
-}
-
static inline __attribute((always_inline)) void nop() {
asm volatile("nop");
}
diff --git a/stm32-blink/Main.swift b/stm32-blink/Main.swift
index c21650e3..43d23858 100644
--- a/stm32-blink/Main.swift
+++ b/stm32-blink/Main.swift
@@ -9,59 +9,26 @@
//
//===----------------------------------------------------------------------===//
-enum STM32F746Board {
- static func initialize() {
- // Configure pin I1 as an LED
+#if STM32F746G_DISCOVERY
- // (1) AHB1ENR[i] = 1 ... enable clock
- setRegisterBit(
- baseAddress: RCC.BaseAddress, offset: RCC.Offsets.AHB1ENR, bit: 8,
- value: 1)
- // (2) MODER[1] = 1 ... set mode to output
- setRegisterTwoBitField(
- baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.MODER,
- bitsStartingAt: 2, value: 1)
- // (3) OTYPER[1] = 0 ... output type is push-pull
- setRegisterBit(
- baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.OTYPER, bit: 1,
- value: 0)
- // (4) OSPEEDR[1] = 2 ... speed is high
- setRegisterTwoBitField(
- baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.OSPEEDR,
- bitsStartingAt: 2, value: 2)
- // (5) PUPDR[1] = 2 ... set pull to down
- setRegisterTwoBitField(
- baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.PUPDR,
- bitsStartingAt: 2, value: 2)
+// I1 pin aka "Arduino D13" pin on STM32F746 Discovery Board
+// https://www.st.com/resource/en/schematic_pack/mb1191-f746ngh6-c01_schematic.pdf
+let ledConfig: (GPIOBank, GPIOPin) = (.i, 1)
- ledOff()
- }
+#elseif NUCLEO_F103RB
- static func ledOn() {
- // ODR[1] = 1
- setRegisterBit(
- baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.ODR, bit: 1,
- value: 1)
- }
+// A5 pin aka "Arduino D13" pin on Nucleo-64 boards
+// https://www.st.com/resource/en/user_manual/um1724-stm32-nucleo64-boards-mb1136-stmicroelectronics.pdf
+let ledConfig: (GPIOBank, GPIOPin) = (.a, 5)
- static func ledOff() {
- // ODR[1] = 0
- setRegisterBit(
- baseAddress: GPIO.GPIOi_BaseAddress, offset: GPIO.Offsets.ODR, bit: 1,
- value: 0)
- }
+#else
- static func delay(milliseconds: Int) {
- for _ in 0..<10_000 * milliseconds {
- nop()
- }
- }
-}
+#error("Unknown board")
+
+#endif
@main
struct Main {
- typealias Board = STM32F746Board
-
static func main() {
Board.initialize()
diff --git a/stm32-blink/README.md b/stm32-blink/README.md
index 9289f7d5..5ae799f3 100644
--- a/stm32-blink/README.md
+++ b/stm32-blink/README.md
@@ -4,19 +4,41 @@ This example shows a simple baremetal firmware for an STM32 board that blinks an
-## How to build and run this example:
+## Requirements
- Connect the STM32F746G-DISCO board via the ST-LINK USB port to your Mac.
-- Make sure you have a recent nightly Swift toolchain that has Embedded Swift support.
+- Download and install a [recent nightly Swift toolchain](https://swift.org/download). Use the "Development Snapshot" from "main".
- Install the [`stlink`](https://github.com/stlink-org/stlink) command line tools, e.g. via `brew install stlink`.
+
+## Building and running the firmware as Mach-O on macOS
+
- Build and upload the program to flash memory of the microcontroller:
```console
$ cd stm32-blink
-$ TOOLCHAINS='' ./build.sh
+$ export TOOLCHAINS=$(plutil -extract CFBundleIdentifier raw /Library/Developer/Toolchains/swift-latest.xctoolchain/Info.plist)
+$ export STM_BOARD=STM32F746G_DISCOVERY # or NUCLEO_F103RB
+$ ./build-macho.sh
$ st-flash --reset write .build/blink.bin 0x08000000
```
- The green LED next to the RESET button should now be blinking in a pattern.
+## Building and running the firmware as ELF (on either macOS or Linux)
+
+- Build and upload the program to flash memory of the microcontroller:
+```console
+$ cd stm32-blink
+
+# If on macOS, select the right latest nightly toolchain (on Linux this is not needed):
+$ export TOOLCHAINS=$(plutil -extract CFBundleIdentifier raw /Library/Developer/Toolchains/swift-latest.xctoolchain/Info.plist)
+
+$ export STM_BOARD=STM32F746G_DISCOVERY # or NUCLEO_F103RB
+$ ./build-elf.sh
+$ st-flash --format ihex --reset write .build/blink.hex
+```
+- The green LED next to the RESET button should now be blinking in a pattern.
+
+## Binary size
+
The resulting size of the compiled and linked binary is very small (which shouldn't be surprising given that this toy example only blinks an LED), and demonstrates how the Embedded Swift compilation mode doesn't include unnecessary code or data in the resulting program:
```console
diff --git a/stm32-blink/Registers.swift b/stm32-blink/Registers.swift
index ef22eec9..ccbf13fb 100644
--- a/stm32-blink/Registers.swift
+++ b/stm32-blink/Registers.swift
@@ -11,45 +11,51 @@
// swift-format-ignore-file
-extension UnsafeMutablePointer where Pointee == UInt32 {
- func volatileLoad() -> Pointee {
- return volatile_load_uint32_t(self)
- }
+import _Volatile
- func volatileStore(_ value: Pointee) {
- volatile_store_uint32_t(self, value)
- }
+#if STM32F746G_DISCOVERY
+
+// Register definitions for STM32F746NG MCU
+// https://www.st.com/resource/en/reference_manual/rm0385-stm32f75xxx-and-stm32f74xxx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
+
+enum GPIOBank: Int {
+ case a, b, c, d, e, f, g, h, i, j, k
}
+typealias GPIOPin = Int
enum RCC {
static let BaseAddress = UnsafeMutablePointer(bitPattern: 0x40023800 as UInt)!
enum Offsets {
- static let CR = 0x0
- static let PLLCFGR = 0x4
- static let CFGR = 0x8
- static let CIR = 0xc
- static let AHB1RSTR = 0x10
- static let AHB2RSTR = 0x14
- static let AHB3RSTR = 0x18
- static let APB1RSTR = 0x20
- static let APB2RSTR = 0x24
static let AHB1ENR = 0x30
- static let AHB2ENR = 0x34
- static let AHB3ENR = 0x38
- static let APB1ENR = 0x40
- static let APB2ENR = 0x44
- static let AHB1LPENR = 0x50
- static let AHB2LPENR = 0x54
- static let AHB3LPENR = 0x58
- static let APB1LPENR = 0x60
- static let APB2LPENR = 0x64
- static let BDCR = 0x70
- static let CSR = 0x74
- static let SSCGR = 0x80
- static let PLLI2SCFGR = 0x84
- static let PLLSAICFGR = 0x88
- static let DKCFGR1 = 0x8c
- static let DKCFGR2 = 0x90
+ }
+ enum Bits {
+ static let AHB1ENR_GPIOAEN = 0
+ static let AHB1ENR_GPIOBEN = 1
+ static let AHB1ENR_GPIOCEN = 2
+ static let AHB1ENR_GPIODEN = 3
+ static let AHB1ENR_GPIOEEN = 4
+ static let AHB1ENR_GPIOFEN = 5
+ static let AHB1ENR_GPIOGEN = 6
+ static let AHB1ENR_GPIOHEN = 7
+ static let AHB1ENR_GPIOIEN = 8
+ static let AHB1ENR_GPIOJEN = 9
+ static let AHB1ENR_GPIOKEN = 10
+ }
+
+ static func AHB1ENRBit(for bank: GPIOBank) -> Int {
+ return switch bank {
+ case .a: Bits.AHB1ENR_GPIOAEN
+ case .b: Bits.AHB1ENR_GPIOBEN
+ case .c: Bits.AHB1ENR_GPIOCEN
+ case .d: Bits.AHB1ENR_GPIODEN
+ case .e: Bits.AHB1ENR_GPIOEEN
+ case .f: Bits.AHB1ENR_GPIOFEN
+ case .g: Bits.AHB1ENR_GPIOGEN
+ case .h: Bits.AHB1ENR_GPIOHEN
+ case .i: Bits.AHB1ENR_GPIOIEN
+ case .j: Bits.AHB1ENR_GPIOJEN
+ case .k: Bits.AHB1ENR_GPIOKEN
+ }
}
}
@@ -73,30 +79,100 @@ enum GPIO {
static let PUPDR = 0xc
static let IDR = 0x10
static let ODR = 0x14
- static let BSRR = 0x18
- static let LCKR = 0x1c
- static let AFRL = 0x20
- static let AFRH = 0x24
- static let BRR = 0x28
}
}
+#elseif NUCLEO_F103RB
+
+// Register definitions for STM32F103RB MCU
+// https://www.st.com/resource/en/reference_manual/rm0008-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
+
+enum GPIOBank: Int {
+ case a, b, c, d, e, f, g
+}
+typealias GPIOPin = Int
+
+enum RCC {
+ static let BaseAddress = UnsafeMutablePointer(bitPattern: 0x40021000 as UInt)!
+ enum Offsets {
+ static let APB2ENR = 0x18
+ }
+ enum Bits {
+ static let APB2ENR_IOPAEN = 2
+ static let APB2ENR_IOPBEN = 3
+ static let APB2ENR_IOPCEN = 4
+ static let APB2ENR_IOPDEN = 5
+ static let APB2ENR_IOPEEN = 6
+ static let APB2ENR_IOPFEN = 7
+ static let APB2ENR_IOPGEN = 8
+ }
+
+ static func APB2ENRBit(for bank: GPIOBank) -> Int {
+ return switch bank {
+ case .a: Bits.APB2ENR_IOPAEN
+ case .b: Bits.APB2ENR_IOPBEN
+ case .c: Bits.APB2ENR_IOPCEN
+ case .d: Bits.APB2ENR_IOPDEN
+ case .e: Bits.APB2ENR_IOPEEN
+ case .f: Bits.APB2ENR_IOPFEN
+ case .g: Bits.APB2ENR_IOPGEN
+ }
+ }
+}
+
+enum GPIO {
+ static let GPIOa_BaseAddress = UnsafeMutablePointer(bitPattern: 0x40010800 as UInt)!
+ static let GPIOb_BaseAddress = UnsafeMutablePointer(bitPattern: 0x40010c00 as UInt)!
+ static let GPIOc_BaseAddress = UnsafeMutablePointer(bitPattern: 0x40011000 as UInt)!
+ static let GPIOd_BaseAddress = UnsafeMutablePointer(bitPattern: 0x40011400 as UInt)!
+ static let GPIOe_BaseAddress = UnsafeMutablePointer(bitPattern: 0x40011800 as UInt)!
+ static let GPIOf_BaseAddress = UnsafeMutablePointer(bitPattern: 0x40011c00 as UInt)!
+ static let GPIOg_BaseAddress = UnsafeMutablePointer(bitPattern: 0x40012000 as UInt)!
+
+ static func GPIOBaseAddress(for bank: GPIOBank) -> UnsafeMutablePointer {
+ return switch bank {
+ case .a: GPIOa_BaseAddress
+ case .b: GPIOb_BaseAddress
+ case .c: GPIOc_BaseAddress
+ case .d: GPIOd_BaseAddress
+ case .e: GPIOe_BaseAddress
+ case .f: GPIOf_BaseAddress
+ case .g: GPIOg_BaseAddress
+ }
+ }
+
+ enum Offsets {
+ static let CRL = 0x0
+ static let CRH = 0x4
+ static let IDR = 0x8
+ static let ODR = 0xc
+ }
+}
+
+#else
+
+#error("Unknown board")
+
+#endif
+
func setRegisterBit(baseAddress: UnsafeMutablePointer, offset: Int, bit: Int, value: Int) {
precondition(offset % 4 == 0)
precondition(bit >= 0 && bit < 32)
precondition(value >= 0 && value < 2)
let p = baseAddress.advanced(by: offset / 4)
- let previousValue: UInt32 = p.volatileLoad()
+ let m = VolatileMappedRegister(unsafeBitPattern: UInt(bitPattern: p))
+ let previousValue: UInt32 = m.load()
let newValue: UInt32 = previousValue & ~(1 << UInt32(bit)) | (UInt32(value) << UInt32(bit))
- p.volatileStore(newValue)
+ m.store(newValue)
}
func setRegisterTwoBitField(baseAddress: UnsafeMutablePointer, offset: Int, bitsStartingAt: Int, value: Int) {
precondition(offset % 4 == 0)
- precondition(bitsStartingAt >= 0 && bitsStartingAt < 16)
+ precondition(bitsStartingAt >= 0 && bitsStartingAt < 31)
precondition(value >= 0 && value < 4)
let p = baseAddress.advanced(by: offset / 4)
- let previousValue: UInt32 = p.volatileLoad()
+ let m = VolatileMappedRegister(unsafeBitPattern: UInt(bitPattern: p))
+ let previousValue: UInt32 = m.load()
let newValue: UInt32 = previousValue & ~(0b11 << UInt32(bitsStartingAt)) | (UInt32(value) << UInt32(bitsStartingAt))
- p.volatileStore(newValue)
+ m.store(newValue)
}
diff --git a/stm32-blink/Startup.c b/stm32-blink/Startup.c
index 16ea6367..9237afb1 100644
--- a/stm32-blink/Startup.c
+++ b/stm32-blink/Startup.c
@@ -22,9 +22,16 @@ void interrupt(void) {
while (1) {}
}
-__attribute((used)) __attribute((section("__VECTORS,__text")))
+__attribute((used))
+#if defined(__ELF__)
+__attribute((section(".vectors")))
+#elif defined(__MACH__)
+__attribute((section("__VECTORS,__text")))
+#else
+#error Unknown file format
+#endif
void *vector_table[114] = {
- (void *)0x2000fffc, // initial SP
+ (void *)0x20001ffc, // initial SP, assume we have 8 KB of SRAM
reset, // Reset
interrupt, // NMI
diff --git a/stm32-blink/build-elf.sh b/stm32-blink/build-elf.sh
new file mode 100755
index 00000000..afd9413e
--- /dev/null
+++ b/stm32-blink/build-elf.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+set -vex
+
+# Determine file paths
+REPOROOT=$(realpath -- "$(dirname "${BASH_SOURCE[0]}")")/..
+TOOLSROOT="$REPOROOT/Tools"
+SRCROOT="$REPOROOT/stm32-blink"
+BUILDROOT="$SRCROOT/.build"
+
+# Clean the build directory
+rm -r "$BUILDROOT" || true
+
+# Setup tools and build flags
+TARGET=armv7em-none-none-eabi
+
+if [[ ! "$STM_BOARD" ]] ; then
+ echo "STM_BOARD must be set to STM32F746G_DISCOVERY or NUCLEO_F103RB"
+ exit 1
+fi
+
+SWIFT_EXEC=${SWIFT_EXEC:-$(which swiftc)}
+SWIFT_FLAGS="-target $TARGET -Osize"
+SWIFT_FLAGS+=" -import-bridging-header $SRCROOT/BridgingHeader.h -wmo -enable-experimental-feature Embedded"
+SWIFT_FLAGS+=" -Xfrontend -function-sections -D${STM_BOARD}"
+
+CLANG_EXEC=${CLANG_EXEC:-$(which clang)}
+CLANG_FLAGS="-target $TARGET -Oz"
+
+LD_EXEC=${LD_EXEC:-$CLANG_EXEC}
+LD_FLAGS="-target $TARGET -fuse-ld=lld -nostdlib -static -Wl,-e,vector_table -Wl,--gc-sections -Wl,-T,$SRCROOT/elf-linkerscript.ld"
+
+# Create build directory
+mkdir -p "$BUILDROOT"
+
+# Build Swift sources
+# shellcheck disable=SC2086 # intentional splitting
+"$SWIFT_EXEC" $SWIFT_FLAGS -c $SRCROOT/*.swift -o "$BUILDROOT/blink.o"
+
+# Build C sources
+# shellcheck disable=SC2086 # intentional splitting
+"$CLANG_EXEC" $CLANG_FLAGS -c "$SRCROOT/Startup.c" -o "$BUILDROOT/Startup.o"
+
+# Link objects into executable
+# shellcheck disable=SC2086 # intentional splitting
+"$LD_EXEC" $LD_FLAGS "$BUILDROOT/blink.o" "$BUILDROOT/Startup.o" -o "$BUILDROOT/blink.elf"
+
+# Convert to Intel HEX for flashing
+"$TOOLSROOT"/elf2hex.py "$BUILDROOT/blink.elf" "$BUILDROOT/blink.hex"
+
+# Echo final binary path
+ls -al "$BUILDROOT/blink.hex"
diff --git a/stm32-blink/build-macho.sh b/stm32-blink/build-macho.sh
new file mode 100755
index 00000000..b45c44cc
--- /dev/null
+++ b/stm32-blink/build-macho.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+set -vex
+
+# Determine file paths
+REPOROOT=$(git rev-parse --show-toplevel)
+TOOLSROOT="$REPOROOT/Tools"
+SRCROOT="$REPOROOT/stm32-blink"
+BUILDROOT="$SRCROOT/.build"
+
+# Clean the build directory
+rm -r "$BUILDROOT" || true
+
+# Setup tools and build flags
+TARGET=armv7em-apple-none-macho
+
+if [[ ! "$STM_BOARD" ]] ; then
+ echo "STM_BOARD must be set to STM32F746G_DISCOVERY or NUCLEO_F103RB"
+ exit 1
+fi
+
+SWIFT_EXEC=${SWIFT_EXEC:-$(xcrun -f swiftc)}
+SWIFT_FLAGS="-target $TARGET -Osize"
+SWIFT_FLAGS+=" -import-bridging-header $SRCROOT/BridgingHeader.h -wmo -enable-experimental-feature Embedded"
+SWIFT_FLAGS+=" -Xcc -D__APPLE__ -Xcc -D__MACH__ -Xcc -ffreestanding"
+SWIFT_FLAGS+=" -D${STM_BOARD}"
+
+CLANG_EXEC=${CLANG_EXEC:-$(xcrun -f clang)}
+CLANG_FLAGS="-target $TARGET -Oz"
+
+LD_EXEC=${LD_EXEC:-$CLANG_EXEC}
+LD_FLAGS="-target $TARGET -nostdlib -static -Wl,-e,_reset -dead_strip -Wl,-no_zero_fill_sections -Wl,-segalign,4 -Wl,-segaddr,__VECTORS,0x08000000 -Wl,-seg1addr,0x08000200 -Wl,-pagezero_size,0"
+
+PYTHON_EXEC=${PYTHON_EXEC:-$(xcrun -f python3)}
+MACHO2BIN="$TOOLSROOT/macho2bin.py"
+
+# Create build directory
+mkdir -p "$BUILDROOT"
+
+# Build Swift sources
+# shellcheck disable=SC2086 # intentional splitting
+"$SWIFT_EXEC" $SWIFT_FLAGS -c "$SRCROOT/"*.swift -o "$BUILDROOT/blink.o"
+
+# Build C sources
+# shellcheck disable=SC2086 # intentional splitting
+"$CLANG_EXEC" $CLANG_FLAGS -c "$SRCROOT/Startup.c" -o "$BUILDROOT/Startup.o"
+
+# Link objects into executable
+# shellcheck disable=SC2086 # intentional splitting
+"$LD_EXEC" $LD_FLAGS "$BUILDROOT/blink.o" "$BUILDROOT/Startup.o" -o "$BUILDROOT/blink"
+
+# Extract sections from executable into flashable binary
+"$PYTHON_EXEC" "$MACHO2BIN" "$BUILDROOT/blink" "$BUILDROOT/blink.bin" --base-address 0x08000000 --segments '__TEXT,__DATA,__VECTORS'
+
+# Echo final binary path
+ls -al "$BUILDROOT/blink.bin"
diff --git a/stm32-blink/build.sh b/stm32-blink/build.sh
deleted file mode 100755
index adc54c8c..00000000
--- a/stm32-blink/build.sh
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/sh
-
-set -vex
-
-# Determine file paths
-REPOROOT=$(git rev-parse --show-toplevel)
-TOOLSROOT="$REPOROOT/Tools"
-SRCROOT="$REPOROOT/stm32-blink"
-BUILDROOT="$SRCROOT/.build"
-
-# Setup tools and build flags
-TARGET=armv7-apple-none-macho
-
-SWIFT_EXEC=${SWIFT_EXEC:-$(xcrun -f swiftc)}
-SWIFT_FLAGS="-target $TARGET -Osize -import-bridging-header $SRCROOT/BridgingHeader.h -wmo -enable-experimental-feature Embedded -Xcc -D__APPLE__ -Xcc -D__MACH__ -Xcc -ffreestanding"
-
-CLANG_EXEC=${CLANG_EXEC:-$(xcrun -f clang)}
-CLANG_FLAGS="-target $TARGET -Oz"
-
-LD_EXEC=${LD_EXEC:-$CLANG_EXEC}
-LD_FLAGS="-target $TARGET -nostdlib -static -Wl,-e,_reset -dead_strip -Wl,-no_zero_fill_sections -Wl,-segalign,4 -Wl,-segaddr,__VECTORS,0x00200000 -Wl,-seg1addr,0x00200200 -Wl,-pagezero_size,0"
-
-PYTHON_EXEC=${PYTHON_EXEC:-$(xcrun -f python3)}
-MACHO2BIN="$TOOLSROOT/macho2bin.py"
-
-# Create build directory
-mkdir -p "$BUILDROOT"
-
-# Build Swift sources
-"$SWIFT_EXEC" "$SWIFT_FLAGS" -c "$SRCROOT/*.swift" -o "$BUILDROOT/blink.o"
-
-# Build C sources
-"$CLANG_EXEC" "$CLANG_FLAGS" -c "$SRCROOT/Startup.c" -o "$BUILDROOT/Startup.o"
-
-# Link objects into executable
-"$LD_EXEC" "$LD_FLAGS" "$BUILDROOT/blink.o" "$BUILDROOT/Startup.o" -o "$BUILDROOT/blink"
-
-# Extract sections from executable into flashable binary
-"$PYTHON_EXEC" "$MACHO2BIN" "$BUILDROOT/blink" "$BUILDROOT/blink.bin" --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS'
-
-# Echo final binary path
-ls -al "$BUILDROOT/blink.bin"
diff --git a/stm32-blink/elf-linkerscript.ld b/stm32-blink/elf-linkerscript.ld
new file mode 100644
index 00000000..98d5f00a
--- /dev/null
+++ b/stm32-blink/elf-linkerscript.ld
@@ -0,0 +1,13 @@
+MEMORY
+{
+ flash : ORIGIN = 0x08000000, LENGTH = 32K
+ sram : ORIGIN = 0x20000000, LENGTH = 8K
+}
+
+SECTIONS
+{
+ .text : { *(.vectors*) ; *(.text*) } > flash
+ .bss : { *(.bss*) } > sram
+ .data : { *(.data*) } > sram
+ /DISCARD/ : { *(.swift_modhash*) }
+}
diff --git a/stm32-lcd-logo/Main.swift b/stm32-lcd-logo/Main.swift
deleted file mode 100644
index fa8d1803..00000000
--- a/stm32-lcd-logo/Main.swift
+++ /dev/null
@@ -1,66 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift open source project
-//
-// Copyright (c) 2023 Apple Inc. and the Swift project authors.
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-//
-//===----------------------------------------------------------------------===//
-
-@main
-struct Main {
- static func main() {
- var board = STM32F746Board()
-
- let blink = {
- board.ledOn()
- board.delay(milliseconds: 10)
- board.ledOff()
- board.delay(milliseconds: 20)
- }
-
- board.delay(milliseconds: 10)
-
- let maxLogoPosition = Point(
- x: board.displaySize.width - board.logoLayerSize.width,
- y: board.displaySize.height - board.logoLayerSize.height)
-
- var logoPosition = Point(x: 100, y: 0)
- board.moveLogo(to: logoPosition)
-
- var logoDelta = Point(x: 1, y: 1)
-
- var iteration = 0
-
- while true {
- board.delay(milliseconds: 10)
-
- logoPosition = logoPosition.offset(by: logoDelta)
- board.moveLogo(to: logoPosition)
-
- if logoPosition.x <= 0 || logoPosition.x >= maxLogoPosition.x {
- logoDelta.x *= -1
- }
- if logoPosition.y <= 0 || logoPosition.y >= maxLogoPosition.y {
- logoDelta.y *= -1
- }
-
- if iteration % 16 == 0 { blink() }
-
- let backgroundGray: Int
- if iteration % 512 < 256 {
- backgroundGray = iteration % 256
- } else if iteration % 512 == 256 {
- backgroundGray = 255
- } else {
- backgroundGray = (512 - (iteration % 512)) % 256
- }
- board.setBackgroundColor(
- color: Color(r: backgroundGray, g: backgroundGray, b: backgroundGray))
-
- iteration += 1
- }
- }
-}
diff --git a/stm32-lcd-logo/Makefile b/stm32-lcd-logo/Makefile
index 4bda625a..b04fafbd 100644
--- a/stm32-lcd-logo/Makefile
+++ b/stm32-lcd-logo/Makefile
@@ -9,53 +9,47 @@
##
##===----------------------------------------------------------------------===##
-# Determine file paths
-REPOROOT := $(shell git rev-parse --show-toplevel)
-TOOLSROOT := $(REPOROOT)/Tools
-SRCROOT := $(REPOROOT)/stm32-lcd-logo
-BUILDROOT := $(SRCROOT)/.build
-
-# Setup tools and build flags
-TARGET := armv7-apple-none-macho
-BASEADDRESS := 0x00200000
-
-SWIFT_EXEC := $(shell xcrun -f swiftc)
-SWIFT_FLAGS := -target $(TARGET) -Osize -import-bridging-header $(SRCROOT)/Support/BridgingHeader.h -wmo -enable-experimental-feature Embedded -Xcc -D__APPLE__ -Xcc -D__MACH__ -Xcc -ffreestanding
-
-CLANG_EXEC := $(shell xcrun -f clang)
-CLANG_FLAGS := -target $(TARGET) -Oz
-
-LD_EXEC := $(CLANG_EXEC)
-LD_FLAGS := -target $(TARGET) -static -Wl,-e,_reset -dead_strip -Wl,-no_zero_fill_sections -Wl,-segalign,4 -Wl,-segaddr,__VECTORS,0x00200000 -Wl,-seg1addr,0x00200200 -Wl,-pagezero_size,0
-
-PYTHON_EXEC := $(shell xcrun -f python3)
-MACHO2BIN := $(TOOLSROOT)/macho2bin.py
-
-.PHONY: all
-all: $(BUILDROOT)/lcd-logo.bin
-
-$(BUILDROOT):
- # Create build directory
- mkdir -p $(BUILDROOT)
-
-$(BUILDROOT)/lcd-logo.o: $(SRCROOT)/Main.swift $(SRCROOT)/Support/*.swift | $(BUILDROOT)
- # Build Swift sources
- $(SWIFT_EXEC) $(SWIFT_FLAGS) -c $^ -o $@
-
-$(BUILDROOT)/Startup.o: $(SRCROOT)/Support/Startup.c | $(BUILDROOT)
- # Build C sources
- $(CLANG_EXEC) $(CLANG_FLAGS) -c $^ -o $@
-
-$(BUILDROOT)/PixelData.o: $(SRCROOT)/Support/PixelData.c | $(BUILDROOT)
- # Build C sources
- $(CLANG_EXEC) $(CLANG_FLAGS) -c $^ -o $@
-
-$(BUILDROOT)/lcd-logo: $(BUILDROOT)/lcd-logo.o $(BUILDROOT)/Startup.o $(BUILDROOT)/PixelData.o
- # Link objects into executable
- $(LD_EXEC) $(LD_FLAGS) $^ -o $@
-
-$(BUILDROOT)/lcd-logo.bin: $(BUILDROOT)/lcd-logo
- # Extract sections from executable into flashable binary
- $(PYTHON_EXEC) $(MACHO2BIN) $^ $@ --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS'
- # Echo final binary path
- ls -al $(BUILDROOT)/lcd-logo.bin
+# Paths
+REPOROOT := $(shell git rev-parse --show-toplevel)
+TOOLSROOT := $(REPOROOT)/Tools
+TOOLSET := $(TOOLSROOT)/Toolsets/stm32f74x-lcd.json
+MACHO2BIN := $(TOOLSROOT)/macho2bin.py
+SWIFT_BUILD := swift build
+
+# Flags
+ARCH := armv7em
+TARGET := $(ARCH)-apple-none-macho
+SWIFT_BUILD_ARGS := \
+ --configuration release \
+ --triple $(TARGET) \
+ --toolset $(TOOLSET) \
+ --disable-local-rpath
+BUILDROOT := $(shell $(SWIFT_BUILD) $(SWIFT_BUILD_ARGS) --show-bin-path)
+
+.PHONY: build
+build:
+ @echo "building..."
+ $(SWIFT_BUILD) \
+ $(SWIFT_BUILD_ARGS) \
+ -Xlinker -map -Xlinker $(BUILDROOT)/Application.mangled.map \
+ --verbose
+
+ @echo "demangling linker map..."
+ cat $(BUILDROOT)/Application.mangled.map \
+ | c++filt | swift demangle > $(BUILDROOT)/Application.map
+
+ @echo "disassembling..."
+ otool \
+ -arch $(ARCH) -v -V -d -t \
+ $(BUILDROOT)/Application \
+ | c++filt | swift demangle > $(BUILDROOT)/Application.disassembly
+
+ @echo "extracting binary..."
+ $(MACHO2BIN) \
+ $(BUILDROOT)/Application $(BUILDROOT)/Application.bin --base-address 0x00200000 --segments '__TEXT,__DATA,__VECTORS'
+
+.PHONY: clean
+clean:
+ @echo "cleaning..."
+ @swift package clean
+ @rm -rf .build
diff --git a/stm32-lcd-logo/Package.resolved b/stm32-lcd-logo/Package.resolved
new file mode 100644
index 00000000..a1112472
--- /dev/null
+++ b/stm32-lcd-logo/Package.resolved
@@ -0,0 +1,33 @@
+{
+ "originHash" : "5728b1ec253c3300a921ee6ddc3c43ff685abaa7f6ca8d86433af91b7883bf79",
+ "pins" : [
+ {
+ "identity" : "swift-argument-parser",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-argument-parser.git",
+ "state" : {
+ "revision" : "41982a3656a71c768319979febd796c6fd111d5c",
+ "version" : "1.5.0"
+ }
+ },
+ {
+ "identity" : "swift-mmio",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/apple/swift-mmio",
+ "state" : {
+ "branch" : "main",
+ "revision" : "daf25ecacc0d9b71036c6af32cb7786a01802799"
+ }
+ },
+ {
+ "identity" : "swift-syntax",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/swiftlang/swift-syntax.git",
+ "state" : {
+ "revision" : "0687f71944021d616d34d922343dcef086855920",
+ "version" : "600.0.1"
+ }
+ }
+ ],
+ "version" : 3
+}
diff --git a/stm32-lcd-logo/Package.swift b/stm32-lcd-logo/Package.swift
new file mode 100644
index 00000000..846e699b
--- /dev/null
+++ b/stm32-lcd-logo/Package.swift
@@ -0,0 +1,28 @@
+// swift-tools-version: 6.2
+
+import PackageDescription
+
+let package = Package(
+ name: "stm32-lcd-logo",
+ platforms: [
+ .macOS(.v10_15)
+ ],
+ products: [
+ .executable(name: "Application", targets: ["Application"])
+ ],
+ dependencies: [
+ .package(url: "https://github.com/apple/swift-mmio", branch: "main")
+ ],
+ targets: [
+ // SVD2Swift \
+ // --input Tools/SVDs/stm32f7x6.patched.svd \
+ // --output stm32-lcd-logo/Sources/STM32F7x6 \
+ // --peripherals FLASH GPIOA GPIOB GPIOC GPIOD GPIOE GPIOF GPIOG GPIOH GPIOI GPIOJ GPIOK LTDC RCC
+ .executableTarget(
+ name: "Application",
+ dependencies: [
+ .product(name: "MMIO", package: "swift-mmio"),
+ "Support",
+ ]),
+ .target(name: "Support"),
+ ])
diff --git a/stm32-lcd-logo/Sources/Application/Geometry/Color.swift b/stm32-lcd-logo/Sources/Application/Geometry/Color.swift
new file mode 100644
index 00000000..c553d8f2
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Geometry/Color.swift
@@ -0,0 +1,18 @@
+//
+// Color.swift
+// stm32-lcd-logo
+//
+// Created by Rauhul Varma on 3/12/25.
+//
+
+struct Color {
+ var red: UInt8
+ var green: UInt8
+ var blue: UInt8
+}
+
+extension Color {
+ static func gray(_ value: UInt8) -> Color {
+ Color(red: value, green: value, blue: value)
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/Geometry/Point.swift b/stm32-lcd-logo/Sources/Application/Geometry/Point.swift
new file mode 100644
index 00000000..7f3a9944
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Geometry/Point.swift
@@ -0,0 +1,15 @@
+//
+// Point.swift
+// stm32-lcd-logo
+//
+// Created by Rauhul Varma on 3/12/25.
+//
+
+struct Point {
+ var x: Int
+ var y: Int
+
+ func offset(by: Point) -> Point {
+ Point(x: x + by.x, y: y + by.y)
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/Geometry/Size.swift b/stm32-lcd-logo/Sources/Application/Geometry/Size.swift
new file mode 100644
index 00000000..30688054
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Geometry/Size.swift
@@ -0,0 +1,11 @@
+//
+// Size.swift
+// stm32-lcd-logo
+//
+// Created by Rauhul Varma on 3/12/25.
+//
+
+struct Size {
+ var width: Int
+ var height: Int
+}
diff --git a/stm32-lcd-logo/Sources/Application/HAL/GPIOA+Helpers.swift b/stm32-lcd-logo/Sources/Application/HAL/GPIOA+Helpers.swift
new file mode 100644
index 00000000..1348a90a
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/HAL/GPIOA+Helpers.swift
@@ -0,0 +1,122 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+extension GPIOA {
+ public enum Port: Int {
+ case a, b, c, d, e, f, g, h, i, j, k
+ }
+
+ enum Mode: UInt32 {
+ case input = 0x0
+ case output = 0x1
+ case alternateFunction = 0x2
+ case analog = 0x3
+ }
+
+ enum OutputType: UInt32 {
+ case pushPull = 0x0
+ case openDrain = 0x1
+ }
+
+ enum OutputSpeed: UInt32 {
+ case low = 0x0
+ case medium = 0x1
+ case high = 0x2
+ case max = 0x3
+ }
+
+ enum Pull: UInt32 {
+ case `none` = 0x0
+ case up = 0x1
+ case down = 0x2
+ }
+
+ struct Configuration {
+ var mode: Mode
+ var outputType: OutputType
+ var outputSpeed: OutputSpeed
+ var pull: Pull
+ var alternateFunction: UInt32
+ }
+
+ func configure(pin: Int, as configuration: Configuration) {
+ self.moder.modify { rw in
+ rw.raw.storage.set(
+ value: configuration.mode.rawValue,
+ mask: 0b11,
+ offset: pin * 2)
+ }
+
+ // Comprised of 16 x 1 bit fields.
+ self.otyper.modify { rw in
+ rw.raw.storage.set(
+ value: configuration.outputType.rawValue,
+ mask: 0b1,
+ offset: pin)
+ }
+
+ // Comprised of 16 x 2 bit fields.
+ self.ospeedr.modify { rw in
+ rw.raw.storage.set(
+ value: configuration.outputSpeed.rawValue,
+ mask: 0b11,
+ offset: pin * 2)
+ }
+
+ // Comprised of 16 x 2 bit fields.
+ self.pupdr.modify { rw in
+ rw.raw.storage.set(
+ value: configuration.pull.rawValue,
+ mask: 0b11,
+ offset: pin * 2)
+ }
+
+ // Comprised of 16 x 4 bit fields, split across 2 registers.
+ if pin < 8 {
+ self.afrl.modify { rw in
+ rw.raw.storage.set(
+ value: configuration.alternateFunction,
+ mask: 0b1111,
+ offset: pin * 4)
+ }
+ } else {
+ self.afrh.modify { rw in
+ rw.raw.storage.set(
+ value: configuration.alternateFunction,
+ mask: 0b1111,
+ offset: (pin - 8) * 4)
+ }
+ }
+ }
+
+ func set(pin: Int, to value: Bool) {
+ // Lower 16 bits are set, upper 16 bits are reset.
+ if value {
+ self.bsrr.write { $0.raw.storage = 1 << pin }
+ } else {
+ self.bsrr.write { $0.raw.storage = 1 << (pin + 16) }
+ }
+ }
+}
+
+extension UInt32 {
+ fileprivate func get(mask: Self, offset: UInt8) -> Self {
+ let mask = mask &<< offset
+ return (self & mask) &>> offset
+ }
+
+ fileprivate mutating func set(value: Self, mask: Self, offset: Int) {
+ let mask = mask &<< offset
+ let oldValue: UInt32 = self & ~mask
+ let newValue: UInt32 = (value &<< offset) & mask
+ self = oldValue | newValue
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/HAL/LTDC+Helpers.swift b/stm32-lcd-logo/Sources/Application/HAL/LTDC+Helpers.swift
new file mode 100644
index 00000000..b45019ca
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/HAL/LTDC+Helpers.swift
@@ -0,0 +1,227 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2024 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+import Support
+
+extension LTDC {
+ enum Constants {
+ static let hsync = 30
+ static let vsync = 10
+ static let hbp = 13
+ static let hfp = 32
+ static let vbp = 2
+ static let vfp = 2
+
+ static let pixelSize = 4
+
+ static let displayWidth = 480
+ static let displayHeight = 272
+
+ static let layerWidth = 50
+ static let layerHeight = 50
+ }
+
+ func configure() {
+ rcc.pllcfgr.write {
+ $0.raw.pllm = 25
+ $0.raw.plln = 432
+ $0.pllsrc = .HSE
+ }
+
+ rcc.cr.modify { $1.raw.pllon = 1 }
+ while rcc.cr.read().raw.pllrdy != 1 {}
+
+ // FIXME: use named fields
+ rcc.cfgr.modify {
+ $0.raw.storage &= 0b11
+ $0.raw.storage |= 0b10
+ }
+ while rcc.cfgr.read().raw.storage & 0b1100 != 0b1000 {}
+
+ rcc.pllsaicfgr.modify {
+ $0.raw.pllsain = 192
+ $0.raw.pllsair = 5
+ }
+ rcc.dckcfgr1.modify { $0.pllsaidivr = .Div4 }
+
+ rcc.cr.modify { $1.raw.pllsaion = 1 }
+ while rcc.cr.read().raw.pllsairdy != 1 {}
+
+ rcc.enableGPIOPortClock(.a)
+ rcc.enableGPIOPortClock(.b)
+ rcc.enableGPIOPortClock(.c)
+ rcc.enableGPIOPortClock(.d)
+ rcc.enableGPIOPortClock(.e)
+ rcc.enableGPIOPortClock(.f)
+ rcc.enableGPIOPortClock(.g)
+ rcc.enableGPIOPortClock(.h)
+ rcc.enableGPIOPortClock(.i)
+ rcc.enableGPIOPortClock(.j)
+ rcc.enableGPIOPortClock(.k)
+
+ let pinConfiguration = GPIOA.Configuration(
+ mode: .alternateFunction,
+ outputType: .pushPull,
+ outputSpeed: .high,
+ pull: .none,
+ alternateFunction: 14)
+
+ let clkPin = 14
+ let dePin = 7
+ let hsyncPin = 10
+ let vsyncPin = 9
+
+ gpioi.configure(pin: clkPin, as: pinConfiguration)
+ gpiok.configure(pin: dePin, as: pinConfiguration)
+ gpioi.configure(pin: hsyncPin, as: pinConfiguration)
+ gpioi.configure(pin: vsyncPin, as: pinConfiguration)
+
+ let r0Pin = 15
+ let r1Pin = 0
+ let r2Pin = 1
+ let r3Pin = 2
+ let r4Pin = 3
+ let r5Pin = 4
+ let r6Pin = 5
+ let r7Pin = 6
+
+ gpioi.configure(pin: r0Pin, as: pinConfiguration)
+ gpioj.configure(pin: r1Pin, as: pinConfiguration)
+ gpioj.configure(pin: r2Pin, as: pinConfiguration)
+ gpioj.configure(pin: r3Pin, as: pinConfiguration)
+ gpioj.configure(pin: r4Pin, as: pinConfiguration)
+ gpioj.configure(pin: r5Pin, as: pinConfiguration)
+ gpioj.configure(pin: r6Pin, as: pinConfiguration)
+ gpioj.configure(pin: r7Pin, as: pinConfiguration)
+
+ let g0Pin = 7
+ let g1Pin = 8
+ let g2Pin = 9
+ let g3Pin = 10
+ let g4Pin = 11
+ let g5Pin = 0
+ let g6Pin = 1
+ let g7Pin = 2
+
+ gpioj.configure(pin: g0Pin, as: pinConfiguration)
+ gpioj.configure(pin: g1Pin, as: pinConfiguration)
+ gpioj.configure(pin: g2Pin, as: pinConfiguration)
+ gpioj.configure(pin: g3Pin, as: pinConfiguration)
+ gpioj.configure(pin: g4Pin, as: pinConfiguration)
+ gpiok.configure(pin: g5Pin, as: pinConfiguration)
+ gpiok.configure(pin: g6Pin, as: pinConfiguration)
+ gpiok.configure(pin: g7Pin, as: pinConfiguration)
+
+ let b0Pin = 4
+ let b1Pin = 13
+ let b2Pin = 14
+ let b3Pin = 15
+ let b4Pin = 12
+ let b5Pin = 4
+ let b6Pin = 5
+ let b7Pin = 6
+
+ gpioe.configure(pin: b0Pin, as: pinConfiguration)
+ gpioj.configure(pin: b1Pin, as: pinConfiguration)
+ gpioj.configure(pin: b2Pin, as: pinConfiguration)
+ gpioj.configure(pin: b3Pin, as: pinConfiguration)
+ gpiog.configure(pin: b4Pin, as: pinConfiguration)
+ gpiok.configure(pin: b5Pin, as: pinConfiguration)
+ gpiok.configure(pin: b6Pin, as: pinConfiguration)
+ gpiok.configure(pin: b7Pin, as: pinConfiguration)
+
+ let lcdPinConfiguration = GPIOA.Configuration(
+ mode: .output,
+ outputType: .pushPull,
+ outputSpeed: .low,
+ pull: .down,
+ alternateFunction: 0)
+
+ let backlightPin = 3
+ let lcdDispPin = 12
+
+ gpiok.configure(pin: backlightPin, as: lcdPinConfiguration)
+ gpioi.configure(pin: lcdDispPin, as: lcdPinConfiguration)
+
+ gpioi.set(pin: lcdDispPin, to: true)
+ gpiok.set(pin: backlightPin, to: true)
+
+ rcc.apb2enr.modify { $0.raw.ltdcen = 1 }
+
+ self.sscr.modify { $0.raw.vsh = UInt32(Constants.vsync - 1) }
+ self.sscr.modify { $0.raw.hsw = UInt32(Constants.hsync - 1) }
+ self.bpcr.modify {
+ $0.raw.ahbp = UInt32(Constants.hsync + Constants.hbp - 1)
+ }
+ self.bpcr.modify {
+ $0.raw.avbp = UInt32(Constants.vsync + Constants.vbp - 1)
+ }
+ self.awcr.modify {
+ $0.raw.aah = UInt32(
+ Constants.displayHeight + Constants.vsync + Constants.vbp - 1)
+ }
+ self.awcr.modify {
+ $0.raw.aaw = UInt32(
+ Constants.displayWidth + Constants.hsync + Constants.hbp - 1)
+ }
+ self.twcr.modify {
+ $0.raw.totalw = UInt32(
+ Constants.displayWidth + Constants.hsync + Constants.hbp + Constants.hfp
+ - 1)
+ }
+ self.twcr.modify {
+ $0.raw.totalh = UInt32(
+ Constants.displayHeight + Constants.vsync + Constants.vbp
+ + Constants.vfp - 1)
+ }
+
+ self.layer[1].pfcr.modify { $0.raw.storage = 0 } // Format ARGB8888
+ self.layer[1].cfbar.modify {
+ $0.raw.storage = UInt32(UInt(bitPattern: logoPixelDataStartPointer))
+ }
+ self.layer[1].cacr.modify { $0.raw.consta = 255 }
+ self.layer[1].bfcr.modify { $0.raw.bf1 = 5 }
+ self.layer[1].bfcr.modify { $0.raw.bf2 = 4 }
+ self.layer[1].cfblr.modify {
+ $0.raw.storage =
+ UInt32(UInt32(Constants.pixelSize * Constants.layerWidth) << 16)
+ | UInt32(Constants.pixelSize * Constants.layerWidth + 3)
+ }
+ self.layer[1].cfblnr.modify {
+ $0.raw.cfblnbr = UInt32(Constants.layerHeight)
+ }
+ self.layer[1].cr.modify { $0.raw.len = 1 }
+
+ self.srcr.modify { $0.raw.vbr = 1 } // reload
+
+ self.gcr.modify { $1.raw.ltdcen = 1 }
+ }
+
+ func set(layer: Int, position point: Point) {
+ let i: Int =
+ ((Constants.layerWidth + Constants.hbp + Constants.hsync - 1
+ + point.x) << 16) | (Constants.hbp + Constants.hsync + point.x)
+ self.layer[layer].whpcr.modify { $0.raw.storage = UInt32(i) }
+ let j: Int =
+ ((Constants.layerHeight + Constants.vsync + Constants.vbp - 1
+ + point.y) << 16) | (Constants.vsync + Constants.vbp + point.y)
+ self.layer[layer].wvpcr.modify { $0.raw.storage = UInt32(j) }
+ self.srcr.modify { $0.raw.vbr = 1 }
+ }
+
+ func set(backgroundColor: Color) {
+ self.bccr.modify {
+ $0.raw.bcred = UInt32(backgroundColor.red)
+ $0.raw.bcgreen = UInt32(backgroundColor.green)
+ $0.raw.bcblue = UInt32(backgroundColor.blue)
+ }
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/HAL/RCC+Helpers.swift b/stm32-lcd-logo/Sources/Application/HAL/RCC+Helpers.swift
new file mode 100644
index 00000000..84488921
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/HAL/RCC+Helpers.swift
@@ -0,0 +1,53 @@
+extension RCC {
+ func enableGPIOPortClock(_ port: GPIOA.Port) {
+ switch port {
+ case .a: self.ahb1enr.modify { $0.raw.gpioaen = 1 }
+ case .b: self.ahb1enr.modify { $0.raw.gpioben = 1 }
+ case .c: self.ahb1enr.modify { $0.raw.gpiocen = 1 }
+ case .d: self.ahb1enr.modify { $0.raw.gpioden = 1 }
+ case .e: self.ahb1enr.modify { $0.raw.gpioeen = 1 }
+ case .f: self.ahb1enr.modify { $0.raw.gpiofen = 1 }
+ case .g: self.ahb1enr.modify { $0.raw.gpiogen = 1 }
+ case .h: self.ahb1enr.modify { $0.raw.gpiohen = 1 }
+ case .i: self.ahb1enr.modify { $0.raw.gpioien = 1 }
+ case .j: self.ahb1enr.modify { $0.raw.gpiojen = 1 }
+ case .k: self.ahb1enr.modify { $0.raw.gpioken = 1 }
+ }
+ }
+
+ func enableUARTClock(_ uartNum: UInt8) {
+ switch uartNum {
+ case 1: self.apb2enr.modify { $0.raw.usart1en = 1 }
+ case 2: self.apb1enr.modify { $0.raw.usart2en = 1 }
+ case 3: self.apb1enr.modify { $0.raw.usart3en = 1 }
+ case 4: self.apb1enr.modify { $0.raw.uart4en = 1 }
+ case 5: self.apb1enr.modify { $0.raw.uart5en = 1 }
+ case 6: self.apb2enr.modify { $0.raw.usart6en = 1 }
+ case 7: self.apb1enr.modify { $0.raw.uart7en = 1 }
+ case 8: self.apb1enr.modify { $0.raw.uart8en = 1 }
+ default: fatalError("Invalid UART number")
+ }
+ }
+
+ func enableI2CClock(_ i2cNum: UInt8) {
+ switch i2cNum {
+ case 1: self.apb1enr.modify { $0.raw.i2c1en = 1 }
+ case 2: self.apb1enr.modify { $0.raw.i2c2en = 1 }
+ case 3: self.apb1enr.modify { $0.raw.i2c3en = 1 }
+ case 4: self.apb1enr.modify { $0.raw.i2c4en = 1 }
+ default: fatalError("Invalid I2C number")
+ }
+ }
+
+ func enableSPIClock(_ spiNum: UInt8) {
+ switch spiNum {
+ case 1: self.apb2enr.modify { $0.raw.spi1en = 1 }
+ case 2: self.apb1enr.modify { $0.raw.spi2en = 1 }
+ case 3: self.apb1enr.modify { $0.raw.spi3en = 1 }
+ case 4: self.apb2enr.modify { $0.raw.spi4en = 1 }
+ case 5: self.apb2enr.modify { $0.raw.spi5en = 1 }
+ case 6: self.apb2enr.modify { $0.raw.spi6en = 1 }
+ default: fatalError("Invalid SPI number")
+ }
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/Main.swift b/stm32-lcd-logo/Sources/Application/Main.swift
new file mode 100644
index 00000000..6cb83c21
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Main.swift
@@ -0,0 +1,79 @@
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2023 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+import Support
+
+@main
+struct Main {
+ static let logoSize = Size(
+ width: LTDC.Constants.layerWidth,
+ height: LTDC.Constants.layerHeight)
+ static let displaySize = Size(
+ width: LTDC.Constants.displayWidth,
+ height: LTDC.Constants.displayHeight)
+ static let maxLogoPosition = Point(
+ x: Self.displaySize.width - Self.logoSize.width,
+ y: Self.displaySize.height - Self.logoSize.height)
+
+ static func main() {
+ // FIXME: remove sleep hack for some bug in clock configuration
+ Self.delay(milliseconds: 1)
+ configureFlash()
+ initializeLTCD()
+ ltdc.configure()
+
+ var logoPosition = Point(x: 100, y: 100)
+ var logoDelta = Point(x: 1, y: 1)
+ var backgroundGray: UInt8 = .min
+ var backgroundDelta: Int8 = -1
+
+ while true {
+ Self.delay(milliseconds: 10)
+
+ if logoPosition.x <= 0 || logoPosition.x >= maxLogoPosition.x {
+ logoDelta.x *= -1
+ }
+ if logoPosition.y <= 0 || logoPosition.y >= maxLogoPosition.y {
+ logoDelta.y *= -1
+ }
+ logoPosition = logoPosition.offset(by: logoDelta)
+ ltdc.set(layer: 1, position: logoPosition)
+
+ if backgroundGray == .min || backgroundGray == .max {
+ backgroundDelta *= -1
+ }
+ backgroundGray = UInt8(Int16(backgroundGray) + Int16(backgroundDelta))
+ ltdc.set(backgroundColor: .gray(backgroundGray))
+ }
+ }
+
+ static func delay(milliseconds: Int) {
+ for _ in 0..<100_000 * milliseconds {
+ nop()
+ }
+ }
+
+ static func configureFlash() {
+ flash.acr.modify { $0.latency = .WS5 }
+ }
+
+ static func initializeLTCD() {
+ rcc.cfgr.write { $0.raw.storage = 0 }
+ rcc.cr.modify { r, w in
+ w.hsion = .On
+ w.csson = .Off
+ w.raw.hseon = 1
+ w.raw.pllon = 0
+ w.raw.hsebyp = 0
+ }
+ while rcc.cr.read().raw.hserdy == 0 {}
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/Registers/Device.swift b/stm32-lcd-logo/Sources/Application/Registers/Device.swift
new file mode 100644
index 00000000..992bf558
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/Device.swift
@@ -0,0 +1,45 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// FLASH
+let flash = FLASH(unsafeAddress: 0x40023c00)
+
+/// General-purpose I/Os
+let gpioa = GPIOA(unsafeAddress: 0x40020000)
+
+/// General-purpose I/Os
+let gpiob = GPIOB(unsafeAddress: 0x40020400)
+
+/// General-purpose I/Os
+let gpioc = GPIOC(unsafeAddress: 0x40020800)
+
+/// General-purpose I/Os
+let gpiod = GPIOD(unsafeAddress: 0x40020c00)
+
+/// General-purpose I/Os
+let gpioe = GPIOE(unsafeAddress: 0x40021000)
+
+/// General-purpose I/Os
+let gpiof = GPIOF(unsafeAddress: 0x40021400)
+
+/// General-purpose I/Os
+let gpiog = GPIOG(unsafeAddress: 0x40021800)
+
+/// General-purpose I/Os
+let gpioh = GPIOH(unsafeAddress: 0x40021c00)
+
+/// General-purpose I/Os
+let gpioi = GPIOI(unsafeAddress: 0x40022000)
+
+/// General-purpose I/Os
+let gpioj = GPIOJ(unsafeAddress: 0x40022400)
+
+/// General-purpose I/Os
+let gpiok = GPIOK(unsafeAddress: 0x40022800)
+
+/// LCD-TFT Controller
+let ltdc = LTDC(unsafeAddress: 0x40016800)
+
+/// Reset and clock control
+let rcc = RCC(unsafeAddress: 0x40023800)
diff --git a/stm32-lcd-logo/Sources/Application/Registers/FLASH.swift b/stm32-lcd-logo/Sources/Application/Registers/FLASH.swift
new file mode 100644
index 00000000..ddca3de8
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/FLASH.swift
@@ -0,0 +1,469 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// FLASH
+@RegisterBlock
+struct FLASH {
+ /// Flash access control register
+ @RegisterBlock(offset: 0x0)
+ var acr: Register
+
+ /// Flash key register
+ @RegisterBlock(offset: 0x4)
+ var keyr: Register
+
+ /// Flash option key register
+ @RegisterBlock(offset: 0x8)
+ var optkeyr: Register
+
+ /// Status register
+ @RegisterBlock(offset: 0xc)
+ var sr: Register
+
+ /// Control register
+ @RegisterBlock(offset: 0x10)
+ var cr: Register
+
+ /// Flash option control register
+ @RegisterBlock(offset: 0x14)
+ var optcr: Register
+
+ /// Flash option control register 1
+ @RegisterBlock(offset: 0x18)
+ var optcr1: Register
+}
+
+extension FLASH {
+ /// Flash access control register
+ @Register(bitWidth: 32)
+ struct ACR {
+ /// Latency
+ @ReadWrite(bits: 0..<4, as: LATENCYValues.self)
+ var latency: LATENCY
+
+ /// Prefetch enable
+ @ReadWrite(bits: 8..<9, as: PRFTENValues.self)
+ var prften: PRFTEN
+
+ /// ART Accelerator Enable
+ @ReadWrite(bits: 9..<10, as: ARTENValues.self)
+ var arten: ARTEN
+
+ /// ART Accelerator reset
+ @ReadWrite(bits: 11..<12, as: ARTRSTValues.self)
+ var artrst: ARTRST
+ }
+
+ /// Flash key register
+ @Register(bitWidth: 32)
+ struct KEYR {
+ /// FPEC key
+ @WriteOnly(bits: 0..<32)
+ var key: KEY
+ }
+
+ /// Flash option key register
+ @Register(bitWidth: 32)
+ struct OPTKEYR {
+ /// Option byte key
+ @WriteOnly(bits: 0..<32)
+ var optkeyr_field: OPTKEYR_FIELD
+ }
+
+ /// Status register
+ @Register(bitWidth: 32)
+ struct SR {
+ /// End of operation
+ @ReadWrite(bits: 0..<1)
+ var eop: EOP
+
+ /// Operation error
+ @ReadWrite(bits: 1..<2)
+ var operr: OPERR
+
+ /// Write protection error
+ @ReadWrite(bits: 4..<5)
+ var wrperr: WRPERR
+
+ /// Programming alignment error
+ @ReadWrite(bits: 5..<6)
+ var pgaerr: PGAERR
+
+ /// Programming parallelism error
+ @ReadWrite(bits: 6..<7)
+ var pgperr: PGPERR
+
+ /// Programming sequence error
+ @ReadWrite(bits: 7..<8)
+ var erserr: ERSERR
+
+ /// Busy
+ @ReadOnly(bits: 16..<17)
+ var bsy: BSY
+ }
+
+ /// Control register
+ @Register(bitWidth: 32)
+ struct CR {
+ /// Programming
+ @ReadWrite(bits: 0..<1, as: PGValues.self)
+ var pg: PG
+
+ /// Sector Erase
+ @ReadWrite(bits: 1..<2, as: SERValues.self)
+ var ser: SER
+
+ /// Mass Erase of sectors 0 to 11
+ @ReadWrite(bits: 2..<3, as: MERValues.self)
+ var mer: MER
+
+ /// Sector number
+ @ReadWrite(bits: 3..<7)
+ var snb: SNB
+
+ /// Program size
+ @ReadWrite(bits: 8..<10, as: PSIZEValues.self)
+ var psize: PSIZE
+
+ /// Start
+ @ReadWrite(bits: 16..<17, as: STRTValues.self)
+ var strt: STRT
+
+ /// End of operation interrupt enable
+ @ReadWrite(bits: 24..<25, as: EOPIEValues.self)
+ var eopie: EOPIE
+
+ /// Error interrupt enable
+ @ReadWrite(bits: 25..<26, as: ERRIEValues.self)
+ var errie: ERRIE
+
+ /// Lock
+ @ReadWrite(bits: 31..<32, as: LOCKValues.self)
+ var lock: LOCK
+ }
+
+ /// Flash option control register
+ @Register(bitWidth: 32)
+ struct OPTCR {
+ /// Option lock
+ @ReadWrite(bits: 0..<1)
+ var optlock: OPTLOCK
+
+ /// Option start
+ @ReadWrite(bits: 1..<2)
+ var optstrt: OPTSTRT
+
+ /// BOR reset Level
+ @ReadWrite(bits: 2..<4)
+ var bor_lev: BOR_LEV
+
+ /// User option bytes
+ @ReadWrite(bits: 4..<5)
+ var wwdg_sw: WWDG_SW
+
+ /// User option bytes
+ @ReadWrite(bits: 5..<6)
+ var iwdg_sw: IWDG_SW
+
+ /// User option bytes
+ @ReadWrite(bits: 6..<7)
+ var nrst_stop: nRST_STOP
+
+ /// User option bytes
+ @ReadWrite(bits: 7..<8)
+ var nrst_stdby: nRST_STDBY
+
+ /// Read protect
+ @ReadWrite(bits: 8..<16)
+ var rdp: RDP
+
+ /// Not write protect
+ @ReadWrite(bits: 16..<24)
+ var nwrp: nWRP
+
+ /// Independent watchdog counter freeze in standby mode
+ @ReadWrite(bits: 30..<31)
+ var iwdg_stdby: IWDG_STDBY
+
+ /// Independent watchdog counter freeze in Stop mode
+ @ReadWrite(bits: 31..<32)
+ var iwdg_stop: IWDG_STOP
+ }
+
+ /// Flash option control register 1
+ @Register(bitWidth: 32)
+ struct OPTCR1 {
+ /// Boot base address when Boot pin =0
+ @ReadWrite(bits: 0..<16)
+ var boot_add0: BOOT_ADD0
+
+ /// Boot base address when Boot pin =1
+ @ReadWrite(bits: 16..<32)
+ var boot_add1: BOOT_ADD1
+ }
+}
+
+extension FLASH.ACR {
+ struct LATENCYValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 4
+
+ /// 0 wait states
+ static let WS0 = Self(rawValue: 0x0)
+
+ /// 1 wait states
+ static let WS1 = Self(rawValue: 0x1)
+
+ /// 2 wait states
+ static let WS2 = Self(rawValue: 0x2)
+
+ /// 3 wait states
+ static let WS3 = Self(rawValue: 0x3)
+
+ /// 4 wait states
+ static let WS4 = Self(rawValue: 0x4)
+
+ /// 5 wait states
+ static let WS5 = Self(rawValue: 0x5)
+
+ /// 6 wait states
+ static let WS6 = Self(rawValue: 0x6)
+
+ /// 7 wait states
+ static let WS7 = Self(rawValue: 0x7)
+
+ /// 8 wait states
+ static let WS8 = Self(rawValue: 0x8)
+
+ /// 9 wait states
+ static let WS9 = Self(rawValue: 0x9)
+
+ /// 10 wait states
+ static let WS10 = Self(rawValue: 0xa)
+
+ /// 11 wait states
+ static let WS11 = Self(rawValue: 0xb)
+
+ /// 12 wait states
+ static let WS12 = Self(rawValue: 0xc)
+
+ /// 13 wait states
+ static let WS13 = Self(rawValue: 0xd)
+
+ /// 14 wait states
+ static let WS14 = Self(rawValue: 0xe)
+
+ /// 15 wait states
+ static let WS15 = Self(rawValue: 0xf)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.ACR {
+ struct PRFTENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Prefetch is disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Prefetch is enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.ACR {
+ struct ARTENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// ART Accelerator is disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// ART Accelerator is enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.ACR {
+ struct ARTRSTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Accelerator is not reset
+ static let NotReset = Self(rawValue: 0x0)
+
+ /// Accelerator is reset
+ static let Reset = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct PGValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Flash programming activated
+ static let Program = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct SERValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Erase activated for selected sector
+ static let SectorErase = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct MERValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Erase activated for all user sectors
+ static let MassErase = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct PSIZEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// Program x8
+ static let PSIZE8 = Self(rawValue: 0x0)
+
+ /// Program x16
+ static let PSIZE16 = Self(rawValue: 0x1)
+
+ /// Program x32
+ static let PSIZE32 = Self(rawValue: 0x2)
+
+ /// Program x64
+ static let PSIZE64 = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct STRTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Trigger an erase operation
+ static let Start = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct EOPIEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// End of operation interrupt disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// End of operation interrupt enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct ERRIEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Error interrupt generation disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Error interrupt generation enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension FLASH.CR {
+ struct LOCKValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// FLASH_CR register is unlocked
+ static let Unlocked = Self(rawValue: 0x0)
+
+ /// FLASH_CR register is locked
+ static let Locked = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOA.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOA.swift
new file mode 100644
index 00000000..3bc4d2ff
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOA.swift
@@ -0,0 +1,1075 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+@RegisterBlock
+struct GPIOA {
+ /// GPIO port mode register
+ @RegisterBlock(offset: 0x0)
+ var moder: Register
+
+ /// GPIO port output type register
+ @RegisterBlock(offset: 0x4)
+ var otyper: Register
+
+ /// GPIO port output speed register
+ @RegisterBlock(offset: 0x8)
+ var ospeedr: Register
+
+ /// GPIO port pull-up/pull-down register
+ @RegisterBlock(offset: 0xc)
+ var pupdr: Register
+
+ /// GPIO port input data register
+ @RegisterBlock(offset: 0x10)
+ var idr: Register
+
+ /// GPIO port output data register
+ @RegisterBlock(offset: 0x14)
+ var odr: Register
+
+ /// GPIO port bit set/reset register
+ @RegisterBlock(offset: 0x18)
+ var bsrr: Register
+
+ /// GPIO port configuration lock register
+ @RegisterBlock(offset: 0x1c)
+ var lckr: Register
+
+ /// GPIO alternate function low register
+ @RegisterBlock(offset: 0x20)
+ var afrl: Register
+
+ /// GPIO alternate function high register
+ @RegisterBlock(offset: 0x24)
+ var afrh: Register
+
+ /// GPIO port bit reset register
+ @RegisterBlock(offset: 0x28)
+ var brr: Register
+}
+
+extension GPIOA {
+ /// GPIO port mode register
+ @Register(bitWidth: 32)
+ struct MODER {
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 30..<32)
+ var moder15: MODER15
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 28..<30)
+ var moder14: MODER14
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 26..<28)
+ var moder13: MODER13
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 24..<26)
+ var moder12: MODER12
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 22..<24)
+ var moder11: MODER11
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 20..<22)
+ var moder10: MODER10
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 18..<20)
+ var moder9: MODER9
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 16..<18)
+ var moder8: MODER8
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 14..<16)
+ var moder7: MODER7
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 12..<14)
+ var moder6: MODER6
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 10..<12)
+ var moder5: MODER5
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 8..<10)
+ var moder4: MODER4
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 6..<8)
+ var moder3: MODER3
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 4..<6)
+ var moder2: MODER2
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 2..<4)
+ var moder1: MODER1
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 0..<2, as: MODER0Values.self)
+ var moder0: MODER0
+ }
+
+ /// GPIO port output type register
+ @Register(bitWidth: 32)
+ struct OTYPER {
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 15..<16)
+ var ot15: OT15
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 14..<15)
+ var ot14: OT14
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 13..<14)
+ var ot13: OT13
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 12..<13)
+ var ot12: OT12
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 11..<12)
+ var ot11: OT11
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 10..<11)
+ var ot10: OT10
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 9..<10)
+ var ot9: OT9
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 8..<9)
+ var ot8: OT8
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 7..<8)
+ var ot7: OT7
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 6..<7)
+ var ot6: OT6
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 5..<6)
+ var ot5: OT5
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 4..<5)
+ var ot4: OT4
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 3..<4)
+ var ot3: OT3
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 2..<3)
+ var ot2: OT2
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 1..<2)
+ var ot1: OT1
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 0..<1, as: OT0Values.self)
+ var ot0: OT0
+ }
+
+ /// GPIO port output speed register
+ @Register(bitWidth: 32)
+ struct OSPEEDR {
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 30..<32)
+ var ospeedr15: OSPEEDR15
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 28..<30)
+ var ospeedr14: OSPEEDR14
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 26..<28)
+ var ospeedr13: OSPEEDR13
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 24..<26)
+ var ospeedr12: OSPEEDR12
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 22..<24)
+ var ospeedr11: OSPEEDR11
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 20..<22)
+ var ospeedr10: OSPEEDR10
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 18..<20)
+ var ospeedr9: OSPEEDR9
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 16..<18)
+ var ospeedr8: OSPEEDR8
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 14..<16)
+ var ospeedr7: OSPEEDR7
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 12..<14)
+ var ospeedr6: OSPEEDR6
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 10..<12)
+ var ospeedr5: OSPEEDR5
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 8..<10)
+ var ospeedr4: OSPEEDR4
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 6..<8)
+ var ospeedr3: OSPEEDR3
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 4..<6)
+ var ospeedr2: OSPEEDR2
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 2..<4)
+ var ospeedr1: OSPEEDR1
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 0..<2, as: OSPEEDR0Values.self)
+ var ospeedr0: OSPEEDR0
+ }
+
+ /// GPIO port pull-up/pull-down register
+ @Register(bitWidth: 32)
+ struct PUPDR {
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 30..<32)
+ var pupdr15: PUPDR15
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 28..<30)
+ var pupdr14: PUPDR14
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 26..<28)
+ var pupdr13: PUPDR13
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 24..<26)
+ var pupdr12: PUPDR12
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 22..<24)
+ var pupdr11: PUPDR11
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 20..<22)
+ var pupdr10: PUPDR10
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 18..<20)
+ var pupdr9: PUPDR9
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 16..<18)
+ var pupdr8: PUPDR8
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 14..<16)
+ var pupdr7: PUPDR7
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 12..<14)
+ var pupdr6: PUPDR6
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 10..<12)
+ var pupdr5: PUPDR5
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 8..<10)
+ var pupdr4: PUPDR4
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 6..<8)
+ var pupdr3: PUPDR3
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 4..<6)
+ var pupdr2: PUPDR2
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 2..<4)
+ var pupdr1: PUPDR1
+
+ /// Port x configuration bits (y = 0..15)
+ @ReadWrite(bits: 0..<2, as: PUPDR0Values.self)
+ var pupdr0: PUPDR0
+ }
+
+ /// GPIO port input data register
+ @Register(bitWidth: 32)
+ struct IDR {
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 15..<16)
+ var idr15: IDR15
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 14..<15)
+ var idr14: IDR14
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 13..<14)
+ var idr13: IDR13
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 12..<13)
+ var idr12: IDR12
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 11..<12)
+ var idr11: IDR11
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 10..<11)
+ var idr10: IDR10
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 9..<10)
+ var idr9: IDR9
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 8..<9)
+ var idr8: IDR8
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 7..<8)
+ var idr7: IDR7
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 6..<7)
+ var idr6: IDR6
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 5..<6)
+ var idr5: IDR5
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 4..<5)
+ var idr4: IDR4
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 3..<4)
+ var idr3: IDR3
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 2..<3)
+ var idr2: IDR2
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 1..<2)
+ var idr1: IDR1
+
+ /// Port input data (y = 0..15)
+ @ReadOnly(bits: 0..<1)
+ var idr0: IDR0
+ }
+
+ /// GPIO port output data register
+ @Register(bitWidth: 32)
+ struct ODR {
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 15..<16)
+ var odr15: ODR15
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 14..<15)
+ var odr14: ODR14
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 13..<14)
+ var odr13: ODR13
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 12..<13)
+ var odr12: ODR12
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 11..<12)
+ var odr11: ODR11
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 10..<11)
+ var odr10: ODR10
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 9..<10)
+ var odr9: ODR9
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 8..<9)
+ var odr8: ODR8
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 7..<8)
+ var odr7: ODR7
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 6..<7)
+ var odr6: ODR6
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 5..<6)
+ var odr5: ODR5
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 4..<5)
+ var odr4: ODR4
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 3..<4)
+ var odr3: ODR3
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 2..<3)
+ var odr2: ODR2
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 1..<2)
+ var odr1: ODR1
+
+ /// Port output data (y = 0..15)
+ @ReadWrite(bits: 0..<1, as: ODR0Values.self)
+ var odr0: ODR0
+ }
+
+ /// GPIO port bit set/reset register
+ @Register(bitWidth: 32)
+ struct BSRR {
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 31..<32)
+ var br15: BR15
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 30..<31)
+ var br14: BR14
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 29..<30)
+ var br13: BR13
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 28..<29)
+ var br12: BR12
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 27..<28)
+ var br11: BR11
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 26..<27)
+ var br10: BR10
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 25..<26)
+ var br9: BR9
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 24..<25)
+ var br8: BR8
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 23..<24)
+ var br7: BR7
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 22..<23)
+ var br6: BR6
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 21..<22)
+ var br5: BR5
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 20..<21)
+ var br4: BR4
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 19..<20)
+ var br3: BR3
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 18..<19)
+ var br2: BR2
+
+ /// Port x reset bit y (y = 0..15)
+ @WriteOnly(bits: 17..<18)
+ var br1: BR1
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 16..<17)
+ var br0: BR0
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 15..<16)
+ var bs15: BS15
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 14..<15)
+ var bs14: BS14
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 13..<14)
+ var bs13: BS13
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 12..<13)
+ var bs12: BS12
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 11..<12)
+ var bs11: BS11
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 10..<11)
+ var bs10: BS10
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 9..<10)
+ var bs9: BS9
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 8..<9)
+ var bs8: BS8
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 7..<8)
+ var bs7: BS7
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 6..<7)
+ var bs6: BS6
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 5..<6)
+ var bs5: BS5
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 4..<5)
+ var bs4: BS4
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 3..<4)
+ var bs3: BS3
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 2..<3)
+ var bs2: BS2
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 1..<2)
+ var bs1: BS1
+
+ /// Port x set bit y (y= 0..15)
+ @WriteOnly(bits: 0..<1)
+ var bs0: BS0
+ }
+
+ /// GPIO port configuration lock register
+ @Register(bitWidth: 32)
+ struct LCKR {
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 16..<17, as: LCKKValues.self)
+ var lckk: LCKK
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 15..<16)
+ var lck15: LCK15
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 14..<15)
+ var lck14: LCK14
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 13..<14)
+ var lck13: LCK13
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 12..<13)
+ var lck12: LCK12
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 11..<12)
+ var lck11: LCK11
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 10..<11)
+ var lck10: LCK10
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 9..<10)
+ var lck9: LCK9
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 8..<9)
+ var lck8: LCK8
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 7..<8)
+ var lck7: LCK7
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 6..<7)
+ var lck6: LCK6
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 5..<6)
+ var lck5: LCK5
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 4..<5)
+ var lck4: LCK4
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 3..<4)
+ var lck3: LCK3
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 2..<3)
+ var lck2: LCK2
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 1..<2)
+ var lck1: LCK1
+
+ /// Port x lock bit y (y= 0..15)
+ @ReadWrite(bits: 0..<1, as: LCK0Values.self)
+ var lck0: LCK0
+ }
+
+ /// GPIO alternate function low register
+ @Register(bitWidth: 32)
+ struct AFRL {
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 28..<32)
+ var afrl7: AFRL7
+
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 24..<28)
+ var afrl6: AFRL6
+
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 20..<24)
+ var afrl5: AFRL5
+
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 16..<20)
+ var afrl4: AFRL4
+
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 12..<16)
+ var afrl3: AFRL3
+
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 8..<12)
+ var afrl2: AFRL2
+
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 4..<8)
+ var afrl1: AFRL1
+
+ /// Alternate function selection for port x bit y (y = 0..7)
+ @ReadWrite(bits: 0..<4, as: AFRL0Values.self)
+ var afrl0: AFRL0
+ }
+
+ /// GPIO alternate function high register
+ @Register(bitWidth: 32)
+ struct AFRH {
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 28..<32)
+ var afrh15: AFRH15
+
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 24..<28)
+ var afrh14: AFRH14
+
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 20..<24)
+ var afrh13: AFRH13
+
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 16..<20)
+ var afrh12: AFRH12
+
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 12..<16)
+ var afrh11: AFRH11
+
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 8..<12)
+ var afrh10: AFRH10
+
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 4..<8)
+ var afrh9: AFRH9
+
+ /// Alternate function selection for port x bit y (y = 8..15)
+ @ReadWrite(bits: 0..<4, as: AFRH8Values.self)
+ var afrh8: AFRH8
+ }
+
+ /// GPIO port bit reset register
+ @Register(bitWidth: 32)
+ struct BRR {
+ /// Port A Reset bit 0
+ @ReadWrite(bits: 0..<1)
+ var br0: BR0
+
+ /// Port A Reset bit 1
+ @ReadWrite(bits: 1..<2)
+ var br1: BR1
+
+ /// Port A Reset bit 2
+ @ReadWrite(bits: 2..<3)
+ var br2: BR2
+
+ /// Port A Reset bit 3
+ @ReadWrite(bits: 3..<4)
+ var br3: BR3
+
+ /// Port A Reset bit 4
+ @ReadWrite(bits: 4..<5)
+ var br4: BR4
+
+ /// Port A Reset bit 5
+ @ReadWrite(bits: 5..<6)
+ var br5: BR5
+
+ /// Port A Reset bit 6
+ @ReadWrite(bits: 6..<7)
+ var br6: BR6
+
+ /// Port A Reset bit 7
+ @ReadWrite(bits: 7..<8)
+ var br7: BR7
+
+ /// Port A Reset bit 8
+ @ReadWrite(bits: 8..<9)
+ var br8: BR8
+
+ /// Port A Reset bit 9
+ @ReadWrite(bits: 9..<10)
+ var br9: BR9
+
+ /// Port A Reset bit 10
+ @ReadWrite(bits: 10..<11)
+ var br10: BR10
+
+ /// Port A Reset bit 11
+ @ReadWrite(bits: 11..<12)
+ var br11: BR11
+
+ /// Port A Reset bit 12
+ @ReadWrite(bits: 12..<13)
+ var br12: BR12
+
+ /// Port A Reset bit 13
+ @ReadWrite(bits: 13..<14)
+ var br13: BR13
+
+ /// Port A Reset bit 14
+ @ReadWrite(bits: 14..<15)
+ var br14: BR14
+
+ /// Port A Reset bit 15
+ @ReadWrite(bits: 15..<16)
+ var br15: BR15
+ }
+}
+
+extension GPIOA.MODER {
+ struct MODER0Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// Input mode (reset state)
+ static let Input = Self(rawValue: 0x0)
+
+ /// General purpose output mode
+ static let Output = Self(rawValue: 0x1)
+
+ /// Alternate function mode
+ static let Alternate = Self(rawValue: 0x2)
+
+ /// Analog mode
+ static let Analog = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.OTYPER {
+ struct OT0Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Output push-pull (reset state)
+ static let PushPull = Self(rawValue: 0x0)
+
+ /// Output open-drain
+ static let OpenDrain = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.OSPEEDR {
+ struct OSPEEDR0Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// Low speed
+ static let LowSpeed = Self(rawValue: 0x0)
+
+ /// Medium speed
+ static let MediumSpeed = Self(rawValue: 0x1)
+
+ /// High speed
+ static let HighSpeed = Self(rawValue: 0x2)
+
+ /// Very high speed
+ static let VeryHighSpeed = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.PUPDR {
+ struct PUPDR0Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// No pull-up, pull-down
+ static let Floating = Self(rawValue: 0x0)
+
+ /// Pull-up
+ static let PullUp = Self(rawValue: 0x1)
+
+ /// Pull-down
+ static let PullDown = Self(rawValue: 0x2)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.ODR {
+ struct ODR0Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Set output to logic low
+ static let Low = Self(rawValue: 0x0)
+
+ /// Set output to logic high
+ static let High = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.LCKR {
+ struct LCKKValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Port configuration lock key not active
+ static let NotActive = Self(rawValue: 0x0)
+
+ /// Port configuration lock key active
+ static let Active = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.LCKR {
+ struct LCK0Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Port configuration not locked
+ static let Unlocked = Self(rawValue: 0x0)
+
+ /// Port configuration locked
+ static let Locked = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.AFRL {
+ struct AFRL0Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 4
+
+ /// AF0
+ static let AF0 = Self(rawValue: 0x0)
+
+ /// AF1
+ static let AF1 = Self(rawValue: 0x1)
+
+ /// AF2
+ static let AF2 = Self(rawValue: 0x2)
+
+ /// AF3
+ static let AF3 = Self(rawValue: 0x3)
+
+ /// AF4
+ static let AF4 = Self(rawValue: 0x4)
+
+ /// AF5
+ static let AF5 = Self(rawValue: 0x5)
+
+ /// AF6
+ static let AF6 = Self(rawValue: 0x6)
+
+ /// AF7
+ static let AF7 = Self(rawValue: 0x7)
+
+ /// AF8
+ static let AF8 = Self(rawValue: 0x8)
+
+ /// AF9
+ static let AF9 = Self(rawValue: 0x9)
+
+ /// AF10
+ static let AF10 = Self(rawValue: 0xa)
+
+ /// AF11
+ static let AF11 = Self(rawValue: 0xb)
+
+ /// AF12
+ static let AF12 = Self(rawValue: 0xc)
+
+ /// AF13
+ static let AF13 = Self(rawValue: 0xd)
+
+ /// AF14
+ static let AF14 = Self(rawValue: 0xe)
+
+ /// AF15
+ static let AF15 = Self(rawValue: 0xf)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension GPIOA.AFRH {
+ struct AFRH8Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 4
+
+ /// AF0
+ static let AF0 = Self(rawValue: 0x0)
+
+ /// AF1
+ static let AF1 = Self(rawValue: 0x1)
+
+ /// AF2
+ static let AF2 = Self(rawValue: 0x2)
+
+ /// AF3
+ static let AF3 = Self(rawValue: 0x3)
+
+ /// AF4
+ static let AF4 = Self(rawValue: 0x4)
+
+ /// AF5
+ static let AF5 = Self(rawValue: 0x5)
+
+ /// AF6
+ static let AF6 = Self(rawValue: 0x6)
+
+ /// AF7
+ static let AF7 = Self(rawValue: 0x7)
+
+ /// AF8
+ static let AF8 = Self(rawValue: 0x8)
+
+ /// AF9
+ static let AF9 = Self(rawValue: 0x9)
+
+ /// AF10
+ static let AF10 = Self(rawValue: 0xa)
+
+ /// AF11
+ static let AF11 = Self(rawValue: 0xb)
+
+ /// AF12
+ static let AF12 = Self(rawValue: 0xc)
+
+ /// AF13
+ static let AF13 = Self(rawValue: 0xd)
+
+ /// AF14
+ static let AF14 = Self(rawValue: 0xe)
+
+ /// AF15
+ static let AF15 = Self(rawValue: 0xf)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOB.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOB.swift
new file mode 100644
index 00000000..c820355f
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOB.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOB = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOC.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOC.swift
new file mode 100644
index 00000000..76543eca
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOC.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOC = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOD.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOD.swift
new file mode 100644
index 00000000..d54a0d5b
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOD.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOD = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOE.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOE.swift
new file mode 100644
index 00000000..08b7facf
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOE.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOE = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOF.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOF.swift
new file mode 100644
index 00000000..a0502a12
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOF.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOF = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOG.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOG.swift
new file mode 100644
index 00000000..1bfc7fd8
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOG.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOG = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOH.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOH.swift
new file mode 100644
index 00000000..3384a586
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOH.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOH = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOI.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOI.swift
new file mode 100644
index 00000000..f7e28cc8
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOI.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOI = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOJ.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOJ.swift
new file mode 100644
index 00000000..6e349edb
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOJ.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOJ = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/GPIOK.swift b/stm32-lcd-logo/Sources/Application/Registers/GPIOK.swift
new file mode 100644
index 00000000..ca28ed7e
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/GPIOK.swift
@@ -0,0 +1,7 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// General-purpose I/Os
+typealias GPIOK = GPIOA
+
diff --git a/stm32-lcd-logo/Sources/Application/Registers/LTDC.swift b/stm32-lcd-logo/Sources/Application/Registers/LTDC.swift
new file mode 100644
index 00000000..bbbe2dbe
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/LTDC.swift
@@ -0,0 +1,847 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// LCD-TFT Controller
+@RegisterBlock
+struct LTDC {
+ /// Synchronization Size Configuration Register
+ @RegisterBlock(offset: 0x8)
+ var sscr: Register
+
+ /// Back Porch Configuration Register
+ @RegisterBlock(offset: 0xc)
+ var bpcr: Register
+
+ /// Active Width Configuration Register
+ @RegisterBlock(offset: 0x10)
+ var awcr: Register
+
+ /// Total Width Configuration Register
+ @RegisterBlock(offset: 0x14)
+ var twcr: Register
+
+ /// Global Control Register
+ @RegisterBlock(offset: 0x18)
+ var gcr: Register
+
+ /// Shadow Reload Configuration Register
+ @RegisterBlock(offset: 0x24)
+ var srcr: Register
+
+ /// Background Color Configuration Register
+ @RegisterBlock(offset: 0x2c)
+ var bccr: Register
+
+ /// Interrupt Enable Register
+ @RegisterBlock(offset: 0x34)
+ var ier: Register
+
+ /// Interrupt Status Register
+ @RegisterBlock(offset: 0x38)
+ var isr: Register
+
+ /// Interrupt Clear Register
+ @RegisterBlock(offset: 0x3c)
+ var icr: Register
+
+ /// Line Interrupt Position Configuration Register
+ @RegisterBlock(offset: 0x40)
+ var lipcr: Register
+
+ /// Current Position Status Register
+ @RegisterBlock(offset: 0x44)
+ var cpsr: Register
+
+ /// Current Display Status Register
+ @RegisterBlock(offset: 0x48)
+ var cdsr: Register
+
+ /// Cluster LAYER%s, containing L?CR, L?WHPCR, L?WVPCR, L?CKCR, L?PFCR, L?CACR, L?DCCR, L?BFCR, L?CFBAR, L?CFBLR, L?CFBLNR, L?CLUTWR
+ @RegisterBlock(offset: 0x84, stride: 0x80, count: 2)
+ var layer: RegisterArray
+}
+
+extension LTDC {
+ /// Synchronization Size Configuration Register
+ @Register(bitWidth: 32)
+ struct SSCR {
+ /// Horizontal Synchronization Width (in units of pixel clock period)
+ @ReadWrite(bits: 16..<28)
+ var hsw: HSW
+
+ /// Vertical Synchronization Height (in units of horizontal scan line)
+ @ReadWrite(bits: 0..<11)
+ var vsh: VSH
+ }
+
+ /// Back Porch Configuration Register
+ @Register(bitWidth: 32)
+ struct BPCR {
+ /// Accumulated Horizontal back porch (in units of pixel clock period)
+ @ReadWrite(bits: 16..<28)
+ var ahbp: AHBP
+
+ /// Accumulated Vertical back porch (in units of horizontal scan line)
+ @ReadWrite(bits: 0..<11)
+ var avbp: AVBP
+ }
+
+ /// Active Width Configuration Register
+ @Register(bitWidth: 32)
+ struct AWCR {
+ /// Accumulated Active Width (in units of pixel clock period)
+ @ReadWrite(bits: 16..<28)
+ var aaw: AAW
+
+ /// Accumulated Active Height (in units of horizontal scan line)
+ @ReadWrite(bits: 0..<11)
+ var aah: AAH
+ }
+
+ /// Total Width Configuration Register
+ @Register(bitWidth: 32)
+ struct TWCR {
+ /// Total Width (in units of pixel clock period)
+ @ReadWrite(bits: 16..<28)
+ var totalw: TOTALW
+
+ /// Total Height (in units of horizontal scan line)
+ @ReadWrite(bits: 0..<11)
+ var totalh: TOTALH
+ }
+
+ /// Global Control Register
+ @Register(bitWidth: 32)
+ struct GCR {
+ /// Horizontal Synchronization Polarity
+ @ReadWrite(bits: 31..<32, as: HSPOLValues.self)
+ var hspol: HSPOL
+
+ /// Vertical Synchronization Polarity
+ @ReadWrite(bits: 30..<31, as: VSPOLValues.self)
+ var vspol: VSPOL
+
+ /// Data Enable Polarity
+ @ReadWrite(bits: 29..<30, as: DEPOLValues.self)
+ var depol: DEPOL
+
+ /// Pixel Clock Polarity
+ @ReadWrite(bits: 28..<29, as: PCPOLValues.self)
+ var pcpol: PCPOL
+
+ /// Dither Enable
+ @ReadWrite(bits: 16..<17, as: DENValues.self)
+ var den: DEN
+
+ /// Dither Red Width
+ @ReadOnly(bits: 12..<15)
+ var drw: DRW
+
+ /// Dither Green Width
+ @ReadOnly(bits: 8..<11)
+ var dgw: DGW
+
+ /// Dither Blue Width
+ @ReadOnly(bits: 4..<7)
+ var dbw: DBW
+
+ /// LCD-TFT controller enable bit
+ @ReadWrite(bits: 0..<1, as: LTDCENValues.self)
+ var ltdcen: LTDCEN
+ }
+
+ /// Shadow Reload Configuration Register
+ @Register(bitWidth: 32)
+ struct SRCR {
+ /// Vertical Blanking Reload
+ @ReadWrite(bits: 1..<2, as: VBRValues.self)
+ var vbr: VBR
+
+ /// Immediate Reload
+ @ReadWrite(bits: 0..<1, as: IMRValues.self)
+ var imr: IMR
+ }
+
+ /// Background Color Configuration Register
+ @Register(bitWidth: 32)
+ struct BCCR {
+ /// Background color blue value
+ @ReadWrite(bits: 0..<8)
+ var bcblue: BCBLUE
+
+ /// Background color green value
+ @ReadWrite(bits: 8..<16)
+ var bcgreen: BCGREEN
+
+ /// Background color red value
+ @ReadWrite(bits: 16..<24)
+ var bcred: BCRED
+ }
+
+ /// Interrupt Enable Register
+ @Register(bitWidth: 32)
+ struct IER {
+ /// Register Reload interrupt enable
+ @ReadWrite(bits: 3..<4, as: RRIEValues.self)
+ var rrie: RRIE
+
+ /// Transfer Error Interrupt Enable
+ @ReadWrite(bits: 2..<3, as: TERRIEValues.self)
+ var terrie: TERRIE
+
+ /// FIFO Underrun Interrupt Enable
+ @ReadWrite(bits: 1..<2, as: FUIEValues.self)
+ var fuie: FUIE
+
+ /// Line Interrupt Enable
+ @ReadWrite(bits: 0..<1, as: LIEValues.self)
+ var lie: LIE
+ }
+
+ /// Interrupt Status Register
+ @Register(bitWidth: 32)
+ struct ISR {
+ /// Register Reload Interrupt Flag
+ @ReadOnly(bits: 3..<4)
+ var rrif: RRIF
+
+ /// Transfer Error interrupt flag
+ @ReadOnly(bits: 2..<3)
+ var terrif: TERRIF
+
+ /// FIFO Underrun Interrupt flag
+ @ReadOnly(bits: 1..<2)
+ var fuif: FUIF
+
+ /// Line Interrupt flag
+ @ReadOnly(bits: 0..<1)
+ var lif: LIF
+ }
+
+ /// Interrupt Clear Register
+ @Register(bitWidth: 32)
+ struct ICR {
+ /// Clears Register Reload Interrupt Flag
+ @WriteOnly(bits: 3..<4)
+ var crrif: CRRIF
+
+ /// Clears the Transfer Error Interrupt Flag
+ @WriteOnly(bits: 2..<3)
+ var cterrif: CTERRIF
+
+ /// Clears the FIFO Underrun Interrupt flag
+ @WriteOnly(bits: 1..<2)
+ var cfuif: CFUIF
+
+ /// Clears the Line Interrupt Flag
+ @WriteOnly(bits: 0..<1)
+ var clif: CLIF
+ }
+
+ /// Line Interrupt Position Configuration Register
+ @Register(bitWidth: 32)
+ struct LIPCR {
+ /// Line Interrupt Position
+ @ReadWrite(bits: 0..<11)
+ var lipos: LIPOS
+ }
+
+ /// Current Position Status Register
+ @Register(bitWidth: 32)
+ struct CPSR {
+ /// Current X Position
+ @ReadOnly(bits: 16..<32)
+ var cxpos: CXPOS
+
+ /// Current Y Position
+ @ReadOnly(bits: 0..<16)
+ var cypos: CYPOS
+ }
+
+ /// Current Display Status Register
+ @Register(bitWidth: 32)
+ struct CDSR {
+ /// Horizontal Synchronization display Status
+ @ReadOnly(bits: 3..<4)
+ var hsyncs: HSYNCS
+
+ /// Vertical Synchronization display Status
+ @ReadOnly(bits: 2..<3)
+ var vsyncs: VSYNCS
+
+ /// Horizontal Data Enable display Status
+ @ReadOnly(bits: 1..<2)
+ var hdes: HDES
+
+ /// Vertical Data Enable display Status
+ @ReadOnly(bits: 0..<1)
+ var vdes: VDES
+ }
+
+ /// Cluster LAYER%s, containing L?CR, L?WHPCR, L?WVPCR, L?CKCR, L?PFCR, L?CACR, L?DCCR, L?BFCR, L?CFBAR, L?CFBLR, L?CFBLNR, L?CLUTWR
+ @RegisterBlock
+ struct LAYER {
+ /// Layerx Control Register
+ @RegisterBlock(offset: 0x0)
+ var cr: Register
+
+ /// Layerx Window Horizontal Position Configuration Register
+ @RegisterBlock(offset: 0x4)
+ var whpcr: Register
+
+ /// Layerx Window Vertical Position Configuration Register
+ @RegisterBlock(offset: 0x8)
+ var wvpcr: Register
+
+ /// Layerx Color Keying Configuration Register
+ @RegisterBlock(offset: 0xc)
+ var ckcr: Register
+
+ /// Layerx Pixel Format Configuration Register
+ @RegisterBlock(offset: 0x10)
+ var pfcr: Register
+
+ /// Layerx Constant Alpha Configuration Register
+ @RegisterBlock(offset: 0x14)
+ var cacr: Register
+
+ /// Layerx Default Color Configuration Register
+ @RegisterBlock(offset: 0x18)
+ var dccr: Register
+
+ /// Layerx Blending Factors Configuration Register
+ @RegisterBlock(offset: 0x1c)
+ var bfcr: Register
+
+ /// Layerx Color Frame Buffer Address Register
+ @RegisterBlock(offset: 0x28)
+ var cfbar: Register
+
+ /// Layerx Color Frame Buffer Length Register
+ @RegisterBlock(offset: 0x2c)
+ var cfblr: Register
+
+ /// Layerx ColorFrame Buffer Line Number Register
+ @RegisterBlock(offset: 0x30)
+ var cfblnr: Register
+
+ /// Layerx CLUT Write Register
+ @RegisterBlock(offset: 0x40)
+ var clutwr: Register
+ }
+}
+
+extension LTDC.LAYER {
+ /// Layerx Control Register
+ @Register(bitWidth: 32)
+ struct CR {
+ /// Color Look-Up Table Enable
+ @ReadWrite(bits: 4..<5, as: CLUTENValues.self)
+ var cluten: CLUTEN
+
+ /// Color Keying Enable
+ @ReadWrite(bits: 1..<2, as: COLKENValues.self)
+ var colken: COLKEN
+
+ /// Layer Enable
+ @ReadWrite(bits: 0..<1, as: LENValues.self)
+ var len: LEN
+ }
+
+ /// Layerx Window Horizontal Position Configuration Register
+ @Register(bitWidth: 32)
+ struct WHPCR {
+ /// Window Horizontal Stop Position
+ @ReadWrite(bits: 16..<28)
+ var whsppos: WHSPPOS
+
+ /// Window Horizontal Start Position
+ @ReadWrite(bits: 0..<12)
+ var whstpos: WHSTPOS
+ }
+
+ /// Layerx Window Vertical Position Configuration Register
+ @Register(bitWidth: 32)
+ struct WVPCR {
+ /// Window Vertical Stop Position
+ @ReadWrite(bits: 16..<27)
+ var wvsppos: WVSPPOS
+
+ /// Window Vertical Start Position
+ @ReadWrite(bits: 0..<11)
+ var wvstpos: WVSTPOS
+ }
+
+ /// Layerx Color Keying Configuration Register
+ @Register(bitWidth: 32)
+ struct CKCR {
+ /// Color Key Red value
+ @ReadWrite(bits: 16..<24)
+ var ckred: CKRED
+
+ /// Color Key Green value
+ @ReadWrite(bits: 8..<16)
+ var ckgreen: CKGREEN
+
+ /// Color Key Blue value
+ @ReadWrite(bits: 0..<8)
+ var ckblue: CKBLUE
+ }
+
+ /// Layerx Pixel Format Configuration Register
+ @Register(bitWidth: 32)
+ struct PFCR {
+ /// Pixel Format
+ @ReadWrite(bits: 0..<3, as: PFValues.self)
+ var pf: PF
+ }
+
+ /// Layerx Constant Alpha Configuration Register
+ @Register(bitWidth: 32)
+ struct CACR {
+ /// Constant Alpha
+ @ReadWrite(bits: 0..<8)
+ var consta: CONSTA
+ }
+
+ /// Layerx Default Color Configuration Register
+ @Register(bitWidth: 32)
+ struct DCCR {
+ /// Default Color Alpha
+ @ReadWrite(bits: 24..<32)
+ var dcalpha: DCALPHA
+
+ /// Default Color Red
+ @ReadWrite(bits: 16..<24)
+ var dcred: DCRED
+
+ /// Default Color Green
+ @ReadWrite(bits: 8..<16)
+ var dcgreen: DCGREEN
+
+ /// Default Color Blue
+ @ReadWrite(bits: 0..<8)
+ var dcblue: DCBLUE
+ }
+
+ /// Layerx Blending Factors Configuration Register
+ @Register(bitWidth: 32)
+ struct BFCR {
+ /// Blending Factor 1
+ @ReadWrite(bits: 8..<11, as: BF1Values.self)
+ var bf1: BF1
+
+ /// Blending Factor 2
+ @ReadWrite(bits: 0..<3, as: BF2Values.self)
+ var bf2: BF2
+ }
+
+ /// Layerx Color Frame Buffer Address Register
+ @Register(bitWidth: 32)
+ struct CFBAR {
+ /// Color Frame Buffer Start Address
+ @ReadWrite(bits: 0..<32)
+ var cfbadd: CFBADD
+ }
+
+ /// Layerx Color Frame Buffer Length Register
+ @Register(bitWidth: 32)
+ struct CFBLR {
+ /// Color Frame Buffer Pitch in bytes
+ @ReadWrite(bits: 16..<29)
+ var cfbp: CFBP
+
+ /// Color Frame Buffer Line Length
+ @ReadWrite(bits: 0..<13)
+ var cfbll: CFBLL
+ }
+
+ /// Layerx ColorFrame Buffer Line Number Register
+ @Register(bitWidth: 32)
+ struct CFBLNR {
+ /// Frame Buffer Line Number
+ @ReadWrite(bits: 0..<11)
+ var cfblnbr: CFBLNBR
+ }
+
+ /// Layerx CLUT Write Register
+ @Register(bitWidth: 32)
+ struct CLUTWR {
+ /// CLUT Address
+ @WriteOnly(bits: 24..<32)
+ var clutadd: CLUTADD
+
+ /// Red value
+ @WriteOnly(bits: 16..<24)
+ var red: RED
+
+ /// Green value
+ @WriteOnly(bits: 8..<16)
+ var green: GREEN
+
+ /// Blue value
+ @WriteOnly(bits: 0..<8)
+ var blue: BLUE
+ }
+}
+
+extension LTDC.GCR {
+ struct HSPOLValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Horizontal synchronization polarity is active low
+ static let ActiveLow = Self(rawValue: 0x0)
+
+ /// Horizontal synchronization polarity is active high
+ static let ActiveHigh = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.GCR {
+ struct VSPOLValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Vertical synchronization polarity is active low
+ static let ActiveLow = Self(rawValue: 0x0)
+
+ /// Vertical synchronization polarity is active high
+ static let ActiveHigh = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.GCR {
+ struct DEPOLValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Data enable polarity is active low
+ static let ActiveLow = Self(rawValue: 0x0)
+
+ /// Data enable polarity is active high
+ static let ActiveHigh = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.GCR {
+ struct PCPOLValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Pixel clock on rising edge
+ static let RisingEdge = Self(rawValue: 0x0)
+
+ /// Pixel clock on falling edge
+ static let FallingEdge = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.GCR {
+ struct DENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Dither disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Dither enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.GCR {
+ struct LTDCENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// LCD-TFT controller disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// LCD-TFT controller enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.SRCR {
+ struct VBRValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// This bit is set by software and cleared only by hardware after reload (it cannot be cleared through register write once it is set)
+ static let NoEffect = Self(rawValue: 0x0)
+
+ /// The shadow registers are reloaded during the vertical blanking period (at the beginning of the first line after the active display area).
+ static let Reload = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.SRCR {
+ struct IMRValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// This bit is set by software and cleared only by hardware after reload (it cannot be cleared through register write once it is set)
+ static let NoEffect = Self(rawValue: 0x0)
+
+ /// The shadow registers are reloaded immediately. This bit is set by software and cleared only by hardware after reload
+ static let Reload = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.IER {
+ struct RRIEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Register reload interrupt disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Register reload interrupt enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.IER {
+ struct TERRIEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Transfer error interrupt disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Transfer error interrupt enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.IER {
+ struct FUIEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// FIFO underrun interrupt disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// FIFO underrun interrupt enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.IER {
+ struct LIEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Line interrupt disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Line interrupt enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.LAYER.CR {
+ struct CLUTENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Color look-up table disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Color look-up table enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.LAYER.CR {
+ struct COLKENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Color keying disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Color keying enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.LAYER.CR {
+ struct LENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Layer disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Layer enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.LAYER.PFCR {
+ struct PFValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 3
+
+ /// ARGB8888
+ static let ARGB8888 = Self(rawValue: 0x0)
+
+ /// RGB888
+ static let RGB888 = Self(rawValue: 0x1)
+
+ /// RGB565
+ static let RGB565 = Self(rawValue: 0x2)
+
+ /// ARGB1555
+ static let ARGB1555 = Self(rawValue: 0x3)
+
+ /// ARGB4444
+ static let ARGB4444 = Self(rawValue: 0x4)
+
+ /// L8 (8-bit luminance)
+ static let L8 = Self(rawValue: 0x5)
+
+ /// AL44 (4-bit alpha, 4-bit luminance)
+ static let AL44 = Self(rawValue: 0x6)
+
+ /// AL88 (8-bit alpha, 8-bit luminance)
+ static let AL88 = Self(rawValue: 0x7)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.LAYER.BFCR {
+ struct BF1Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 3
+
+ /// BF1 = constant alpha
+ static let Constant = Self(rawValue: 0x4)
+
+ /// BF1 = pixel alpha * constant alpha
+ static let Pixel = Self(rawValue: 0x6)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension LTDC.LAYER.BFCR {
+ struct BF2Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 3
+
+ /// BF2 = 1 - constant alpha
+ static let Constant = Self(rawValue: 0x5)
+
+ /// BF2 = 1 - pixel alpha * constant alpha
+ static let Pixel = Self(rawValue: 0x7)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
diff --git a/stm32-lcd-logo/Sources/Application/Registers/RCC.swift b/stm32-lcd-logo/Sources/Application/Registers/RCC.swift
new file mode 100644
index 00000000..4f5842ef
--- /dev/null
+++ b/stm32-lcd-logo/Sources/Application/Registers/RCC.swift
@@ -0,0 +1,2833 @@
+// Generated by svd2swift.
+
+import MMIO
+
+/// Reset and clock control
+@RegisterBlock
+struct RCC {
+ /// clock control register
+ @RegisterBlock(offset: 0x0)
+ var cr: Register
+
+ /// PLL configuration register
+ @RegisterBlock(offset: 0x4)
+ var pllcfgr: Register
+
+ /// clock configuration register
+ @RegisterBlock(offset: 0x8)
+ var cfgr: Register
+
+ /// clock interrupt register
+ @RegisterBlock(offset: 0xc)
+ var cir: Register
+
+ /// AHB1 peripheral reset register
+ @RegisterBlock(offset: 0x10)
+ var ahb1rstr: Register
+
+ /// AHB2 peripheral reset register
+ @RegisterBlock(offset: 0x14)
+ var ahb2rstr: Register
+
+ /// AHB3 peripheral reset register
+ @RegisterBlock(offset: 0x18)
+ var ahb3rstr: Register
+
+ /// APB1 peripheral reset register
+ @RegisterBlock(offset: 0x20)
+ var apb1rstr: Register
+
+ /// APB2 peripheral reset register
+ @RegisterBlock(offset: 0x24)
+ var apb2rstr: Register
+
+ /// AHB1 peripheral clock register
+ @RegisterBlock(offset: 0x30)
+ var ahb1enr: Register
+
+ /// AHB2 peripheral clock enable register
+ @RegisterBlock(offset: 0x34)
+ var ahb2enr: Register
+
+ /// AHB3 peripheral clock enable register
+ @RegisterBlock(offset: 0x38)
+ var ahb3enr: Register
+
+ /// APB1 peripheral clock enable register
+ @RegisterBlock(offset: 0x40)
+ var apb1enr: Register
+
+ /// APB2 peripheral clock enable register
+ @RegisterBlock(offset: 0x44)
+ var apb2enr: Register
+
+ /// AHB1 peripheral clock enable in low power mode register
+ @RegisterBlock(offset: 0x50)
+ var ahb1lpenr: Register
+
+ /// AHB2 peripheral clock enable in low power mode register
+ @RegisterBlock(offset: 0x54)
+ var ahb2lpenr: Register
+
+ /// AHB3 peripheral clock enable in low power mode register
+ @RegisterBlock(offset: 0x58)
+ var ahb3lpenr: Register
+
+ /// APB1 peripheral clock enable in low power mode register
+ @RegisterBlock(offset: 0x60)
+ var apb1lpenr: Register
+
+ /// APB2 peripheral clock enabled in low power mode register
+ @RegisterBlock(offset: 0x64)
+ var apb2lpenr: Register
+
+ /// Backup domain control register
+ @RegisterBlock(offset: 0x70)
+ var bdcr: Register
+
+ /// clock control & status register
+ @RegisterBlock(offset: 0x74)
+ var csr: Register
+
+ /// spread spectrum clock generation register
+ @RegisterBlock(offset: 0x80)
+ var sscgr: Register
+
+ /// PLLI2S configuration register
+ @RegisterBlock(offset: 0x84)
+ var plli2scfgr: Register
+
+ /// PLL configuration register
+ @RegisterBlock(offset: 0x88)
+ var pllsaicfgr: Register
+
+ /// dedicated clocks configuration register
+ @RegisterBlock(offset: 0x8c)
+ var dckcfgr1: Register
+
+ /// dedicated clocks configuration register
+ @RegisterBlock(offset: 0x90)
+ var dckcfgr2: Register
+}
+
+extension RCC {
+ /// clock control register
+ @Register(bitWidth: 32)
+ struct CR {
+ /// PLLI2S clock ready flag
+ @ReadOnly(bits: 27..<28)
+ var plli2srdy: PLLI2SRDY
+
+ /// PLLI2S enable
+ @ReadWrite(bits: 26..<27)
+ var plli2son: PLLI2SON
+
+ /// Main PLL (PLL) clock ready flag
+ @ReadOnly(bits: 25..<26)
+ var pllrdy: PLLRDY
+
+ /// Main PLL (PLL) enable
+ @ReadWrite(bits: 24..<25)
+ var pllon: PLLON
+
+ /// Clock security system enable
+ @ReadWrite(bits: 19..<20, as: CSSONValues.self)
+ var csson: CSSON
+
+ /// HSE clock bypass
+ @ReadWrite(bits: 18..<19, as: HSEBYPValues.self)
+ var hsebyp: HSEBYP
+
+ /// HSE clock ready flag
+ @ReadOnly(bits: 17..<18)
+ var hserdy: HSERDY
+
+ /// HSE clock enable
+ @ReadWrite(bits: 16..<17)
+ var hseon: HSEON
+
+ /// Internal high-speed clock calibration
+ @ReadOnly(bits: 8..<16)
+ var hsical: HSICAL
+
+ /// Internal high-speed clock trimming
+ @ReadWrite(bits: 3..<8)
+ var hsitrim: HSITRIM
+
+ /// Internal high-speed clock ready flag
+ @ReadOnly(bits: 1..<2)
+ var hsirdy: HSIRDY
+
+ /// Internal high-speed clock enable
+ @ReadWrite(bits: 0..<1, as: HSIONValues.self)
+ var hsion: HSION
+
+ /// PLLSAI clock ready flag
+ @ReadOnly(bits: 29..<30)
+ var pllsairdy: PLLSAIRDY
+
+ /// PLLSAI enable
+ @ReadWrite(bits: 28..<29)
+ var pllsaion: PLLSAION
+ }
+
+ /// PLL configuration register
+ @Register(bitWidth: 32)
+ struct PLLCFGR {
+ /// Main PLL(PLL) and audio PLL (PLLI2S) entry clock source
+ @ReadWrite(bits: 22..<23, as: PLLSRCValues.self)
+ var pllsrc: PLLSRC
+
+ /// Division factor for the main PLL (PLL) and audio PLL (PLLI2S) input clock
+ @ReadWrite(bits: 0..<6)
+ var pllm: PLLM
+
+ /// Main PLL (PLL) multiplication factor for VCO
+ @ReadWrite(bits: 6..<15)
+ var plln: PLLN
+
+ /// Main PLL (PLL) division factor for main system clock
+ @ReadWrite(bits: 16..<18, as: PLLPValues.self)
+ var pllp: PLLP
+
+ /// Main PLL (PLL) division factor for USB OTG FS, SDIO and random number generator clocks
+ @ReadWrite(bits: 24..<28)
+ var pllq: PLLQ
+ }
+
+ /// clock configuration register
+ @Register(bitWidth: 32)
+ struct CFGR {
+ /// Microcontroller clock output 2
+ @ReadWrite(bits: 30..<32, as: MCO2Values.self)
+ var mco2: MCO2
+
+ /// MCO2 prescaler
+ @ReadWrite(bits: 27..<30)
+ var mco2pre: MCO2PRE
+
+ /// MCO1 prescaler
+ @ReadWrite(bits: 24..<27, as: MCO1PREValues.self)
+ var mco1pre: MCO1PRE
+
+ /// I2S clock selection
+ @ReadWrite(bits: 23..<24, as: I2SSRCValues.self)
+ var i2ssrc: I2SSRC
+
+ /// Microcontroller clock output 1
+ @ReadWrite(bits: 21..<23, as: MCO1Values.self)
+ var mco1: MCO1
+
+ /// HSE division factor for RTC clock
+ @ReadWrite(bits: 16..<21)
+ var rtcpre: RTCPRE
+
+ /// APB high-speed prescaler (APB2)
+ @ReadWrite(bits: 13..<16)
+ var ppre2: PPRE2
+
+ /// APB Low speed prescaler (APB1)
+ @ReadWrite(bits: 10..<13, as: PPRE1Values.self)
+ var ppre1: PPRE1
+
+ /// AHB prescaler
+ @ReadWrite(bits: 4..<8, as: HPREValues.self)
+ var hpre: HPRE
+
+ /// System clock switch
+ @Reserved(bits: 0..<2, as: SWValues.self)
+ var sw: SW
+
+ /// System clock switch status
+ @Reserved(bits: 2..<4)
+ var sws: SWS
+ }
+
+ /// clock interrupt register
+ @Register(bitWidth: 32)
+ struct CIR {
+ /// Clock security system interrupt clear
+ @WriteOnly(bits: 23..<24)
+ var cssc: CSSC
+
+ /// PLLSAI Ready Interrupt Clear
+ @WriteOnly(bits: 22..<23)
+ var pllsairdyc: PLLSAIRDYC
+
+ /// PLLI2S ready interrupt clear
+ @WriteOnly(bits: 21..<22)
+ var plli2srdyc: PLLI2SRDYC
+
+ /// Main PLL(PLL) ready interrupt clear
+ @WriteOnly(bits: 20..<21)
+ var pllrdyc: PLLRDYC
+
+ /// HSE ready interrupt clear
+ @WriteOnly(bits: 19..<20)
+ var hserdyc: HSERDYC
+
+ /// HSI ready interrupt clear
+ @WriteOnly(bits: 18..<19)
+ var hsirdyc: HSIRDYC
+
+ /// LSE ready interrupt clear
+ @WriteOnly(bits: 17..<18)
+ var lserdyc: LSERDYC
+
+ /// LSI ready interrupt clear
+ @WriteOnly(bits: 16..<17)
+ var lsirdyc: LSIRDYC
+
+ /// PLLSAI Ready Interrupt Enable
+ @ReadWrite(bits: 14..<15)
+ var pllsairdyie: PLLSAIRDYIE
+
+ /// PLLI2S ready interrupt enable
+ @ReadWrite(bits: 13..<14)
+ var plli2srdyie: PLLI2SRDYIE
+
+ /// Main PLL (PLL) ready interrupt enable
+ @ReadWrite(bits: 12..<13)
+ var pllrdyie: PLLRDYIE
+
+ /// HSE ready interrupt enable
+ @ReadWrite(bits: 11..<12)
+ var hserdyie: HSERDYIE
+
+ /// HSI ready interrupt enable
+ @ReadWrite(bits: 10..<11)
+ var hsirdyie: HSIRDYIE
+
+ /// LSE ready interrupt enable
+ @ReadWrite(bits: 9..<10)
+ var lserdyie: LSERDYIE
+
+ /// LSI ready interrupt enable
+ @ReadWrite(bits: 8..<9, as: LSIRDYIEValues.self)
+ var lsirdyie: LSIRDYIE
+
+ /// Clock security system interrupt flag
+ @ReadOnly(bits: 7..<8)
+ var cssf: CSSF
+
+ /// PLLSAI ready interrupt flag
+ @ReadOnly(bits: 6..<7)
+ var pllsairdyf: PLLSAIRDYF
+
+ /// PLLI2S ready interrupt flag
+ @ReadOnly(bits: 5..<6)
+ var plli2srdyf: PLLI2SRDYF
+
+ /// Main PLL (PLL) ready interrupt flag
+ @ReadOnly(bits: 4..<5)
+ var pllrdyf: PLLRDYF
+
+ /// HSE ready interrupt flag
+ @ReadOnly(bits: 3..<4)
+ var hserdyf: HSERDYF
+
+ /// HSI ready interrupt flag
+ @ReadOnly(bits: 2..<3)
+ var hsirdyf: HSIRDYF
+
+ /// LSE ready interrupt flag
+ @ReadOnly(bits: 1..<2)
+ var lserdyf: LSERDYF
+
+ /// LSI ready interrupt flag
+ @ReadOnly(bits: 0..<1)
+ var lsirdyf: LSIRDYF
+ }
+
+ /// AHB1 peripheral reset register
+ @Register(bitWidth: 32)
+ struct AHB1RSTR {
+ /// USB OTG HS module reset
+ @ReadWrite(bits: 29..<30)
+ var otghsrst: OTGHSRST
+
+ /// Ethernet MAC reset
+ @ReadWrite(bits: 25..<26)
+ var ethmacrst: ETHMACRST
+
+ /// DMA2D reset
+ @ReadWrite(bits: 23..<24)
+ var dma2drst: DMA2DRST
+
+ /// DMA2 reset
+ @ReadWrite(bits: 22..<23)
+ var dma2rst: DMA2RST
+
+ /// DMA2 reset
+ @ReadWrite(bits: 21..<22)
+ var dma1rst: DMA1RST
+
+ /// CRC reset
+ @ReadWrite(bits: 12..<13)
+ var crcrst: CRCRST
+
+ /// IO port K reset
+ @ReadWrite(bits: 10..<11)
+ var gpiokrst: GPIOKRST
+
+ /// IO port J reset
+ @ReadWrite(bits: 9..<10)
+ var gpiojrst: GPIOJRST
+
+ /// IO port I reset
+ @ReadWrite(bits: 8..<9)
+ var gpioirst: GPIOIRST
+
+ /// IO port H reset
+ @ReadWrite(bits: 7..<8)
+ var gpiohrst: GPIOHRST
+
+ /// IO port G reset
+ @ReadWrite(bits: 6..<7)
+ var gpiogrst: GPIOGRST
+
+ /// IO port F reset
+ @ReadWrite(bits: 5..<6)
+ var gpiofrst: GPIOFRST
+
+ /// IO port E reset
+ @ReadWrite(bits: 4..<5)
+ var gpioerst: GPIOERST
+
+ /// IO port D reset
+ @ReadWrite(bits: 3..<4)
+ var gpiodrst: GPIODRST
+
+ /// IO port C reset
+ @ReadWrite(bits: 2..<3)
+ var gpiocrst: GPIOCRST
+
+ /// IO port B reset
+ @ReadWrite(bits: 1..<2)
+ var gpiobrst: GPIOBRST
+
+ /// IO port A reset
+ @ReadWrite(bits: 0..<1, as: GPIOARSTValues.self)
+ var gpioarst: GPIOARST
+ }
+
+ /// AHB2 peripheral reset register
+ @Register(bitWidth: 32)
+ struct AHB2RSTR {
+ /// USB OTG FS module reset
+ @ReadWrite(bits: 7..<8)
+ var otgfsrst: OTGFSRST
+
+ /// Random number generator module reset
+ @ReadWrite(bits: 6..<7)
+ var rngrst: RNGRST
+
+ /// Hash module reset
+ @ReadWrite(bits: 5..<6)
+ var hsahrst: HSAHRST
+
+ /// Cryptographic module reset
+ @ReadWrite(bits: 4..<5)
+ var cryprst: CRYPRST
+
+ /// Camera interface reset
+ @ReadWrite(bits: 0..<1, as: DCMIRSTValues.self)
+ var dcmirst: DCMIRST
+ }
+
+ /// AHB3 peripheral reset register
+ @Register(bitWidth: 32)
+ struct AHB3RSTR {
+ /// Flexible memory controller module reset
+ @ReadWrite(bits: 0..<1, as: FMCRSTValues.self)
+ var fmcrst: FMCRST
+
+ /// Quad SPI memory controller reset
+ @ReadWrite(bits: 1..<2)
+ var qspirst: QSPIRST
+ }
+
+ /// APB1 peripheral reset register
+ @Register(bitWidth: 32)
+ struct APB1RSTR {
+ /// TIM2 reset
+ @ReadWrite(bits: 0..<1, as: TIM2RSTValues.self)
+ var tim2rst: TIM2RST
+
+ /// TIM3 reset
+ @ReadWrite(bits: 1..<2)
+ var tim3rst: TIM3RST
+
+ /// TIM4 reset
+ @ReadWrite(bits: 2..<3)
+ var tim4rst: TIM4RST
+
+ /// TIM5 reset
+ @ReadWrite(bits: 3..<4)
+ var tim5rst: TIM5RST
+
+ /// TIM6 reset
+ @ReadWrite(bits: 4..<5)
+ var tim6rst: TIM6RST
+
+ /// TIM7 reset
+ @ReadWrite(bits: 5..<6)
+ var tim7rst: TIM7RST
+
+ /// TIM12 reset
+ @ReadWrite(bits: 6..<7)
+ var tim12rst: TIM12RST
+
+ /// TIM13 reset
+ @ReadWrite(bits: 7..<8)
+ var tim13rst: TIM13RST
+
+ /// TIM14 reset
+ @ReadWrite(bits: 8..<9)
+ var tim14rst: TIM14RST
+
+ /// Window watchdog reset
+ @ReadWrite(bits: 11..<12)
+ var wwdgrst: WWDGRST
+
+ /// SPI 2 reset
+ @ReadWrite(bits: 14..<15)
+ var spi2rst: SPI2RST
+
+ /// SPI 3 reset
+ @ReadWrite(bits: 15..<16)
+ var spi3rst: SPI3RST
+
+ /// USART 2 reset
+ @ReadWrite(bits: 17..<18)
+ var usart2rst: USART2RST
+
+ /// USART 3 reset
+ @ReadWrite(bits: 18..<19)
+ var usart3rst: USART3RST
+
+ /// USART 4 reset
+ @ReadWrite(bits: 19..<20)
+ var uart4rst: UART4RST
+
+ /// USART 5 reset
+ @ReadWrite(bits: 20..<21)
+ var uart5rst: UART5RST
+
+ /// I2C 1 reset
+ @ReadWrite(bits: 21..<22)
+ var i2c1rst: I2C1RST
+
+ /// I2C 2 reset
+ @ReadWrite(bits: 22..<23)
+ var i2c2rst: I2C2RST
+
+ /// I2C3 reset
+ @ReadWrite(bits: 23..<24)
+ var i2c3rst: I2C3RST
+
+ /// CAN1 reset
+ @ReadWrite(bits: 25..<26)
+ var can1rst: CAN1RST
+
+ /// CAN2 reset
+ @ReadWrite(bits: 26..<27)
+ var can2rst: CAN2RST
+
+ /// Power interface reset
+ @ReadWrite(bits: 28..<29)
+ var pwrrst: PWRRST
+
+ /// DAC reset
+ @ReadWrite(bits: 29..<30)
+ var dacrst: DACRST
+
+ /// UART7 reset
+ @ReadWrite(bits: 30..<31)
+ var uart7rst: UART7RST
+
+ /// UART8 reset
+ @ReadWrite(bits: 31..<32)
+ var uart8rst: UART8RST
+
+ /// SPDIF-RX reset
+ @ReadWrite(bits: 16..<17)
+ var spdifrxrst: SPDIFRXRST
+
+ /// HDMI-CEC reset
+ @ReadWrite(bits: 27..<28)
+ var cecrst: CECRST
+
+ /// Low power timer 1 reset
+ @ReadWrite(bits: 9..<10)
+ var lptim1rst: LPTIM1RST
+
+ /// I2C 4 reset
+ @ReadWrite(bits: 24..<25)
+ var i2c4rst: I2C4RST
+ }
+
+ /// APB2 peripheral reset register
+ @Register(bitWidth: 32)
+ struct APB2RSTR {
+ /// TIM1 reset
+ @ReadWrite(bits: 0..<1, as: TIM1RSTValues.self)
+ var tim1rst: TIM1RST
+
+ /// TIM8 reset
+ @ReadWrite(bits: 1..<2)
+ var tim8rst: TIM8RST
+
+ /// USART1 reset
+ @ReadWrite(bits: 4..<5)
+ var usart1rst: USART1RST
+
+ /// USART6 reset
+ @ReadWrite(bits: 5..<6)
+ var usart6rst: USART6RST
+
+ /// ADC interface reset (common to all ADCs)
+ @ReadWrite(bits: 8..<9)
+ var adcrst: ADCRST
+
+ /// SPI 1 reset
+ @ReadWrite(bits: 12..<13)
+ var spi1rst: SPI1RST
+
+ /// SPI4 reset
+ @ReadWrite(bits: 13..<14)
+ var spi4rst: SPI4RST
+
+ /// System configuration controller reset
+ @ReadWrite(bits: 14..<15)
+ var syscfgrst: SYSCFGRST
+
+ /// TIM9 reset
+ @ReadWrite(bits: 16..<17)
+ var tim9rst: TIM9RST
+
+ /// TIM10 reset
+ @ReadWrite(bits: 17..<18)
+ var tim10rst: TIM10RST
+
+ /// TIM11 reset
+ @ReadWrite(bits: 18..<19)
+ var tim11rst: TIM11RST
+
+ /// SPI5 reset
+ @ReadWrite(bits: 20..<21)
+ var spi5rst: SPI5RST
+
+ /// SPI6 reset
+ @ReadWrite(bits: 21..<22)
+ var spi6rst: SPI6RST
+
+ /// SAI1 reset
+ @ReadWrite(bits: 22..<23)
+ var sai1rst: SAI1RST
+
+ /// LTDC reset
+ @ReadWrite(bits: 26..<27)
+ var ltdcrst: LTDCRST
+
+ /// SAI2 reset
+ @ReadWrite(bits: 23..<24)
+ var sai2rst: SAI2RST
+
+ /// SDMMC1 reset
+ @ReadWrite(bits: 11..<12)
+ var sdmmc1rst: SDMMC1RST
+ }
+
+ /// AHB1 peripheral clock register
+ @Register(bitWidth: 32)
+ struct AHB1ENR {
+ /// USB OTG HSULPI clock enable
+ @ReadWrite(bits: 30..<31)
+ var otghsulpien: OTGHSULPIEN
+
+ /// USB OTG HS clock enable
+ @ReadWrite(bits: 29..<30)
+ var otghsen: OTGHSEN
+
+ /// Ethernet PTP clock enable
+ @ReadWrite(bits: 28..<29)
+ var ethmacptpen: ETHMACPTPEN
+
+ /// Ethernet Reception clock enable
+ @ReadWrite(bits: 27..<28)
+ var ethmacrxen: ETHMACRXEN
+
+ /// Ethernet Transmission clock enable
+ @ReadWrite(bits: 26..<27)
+ var ethmactxen: ETHMACTXEN
+
+ /// Ethernet MAC clock enable
+ @ReadWrite(bits: 25..<26)
+ var ethmacen: ETHMACEN
+
+ /// DMA2D clock enable
+ @ReadWrite(bits: 23..<24)
+ var dma2den: DMA2DEN
+
+ /// DMA2 clock enable
+ @ReadWrite(bits: 22..<23)
+ var dma2en: DMA2EN
+
+ /// DMA1 clock enable
+ @ReadWrite(bits: 21..<22)
+ var dma1en: DMA1EN
+
+ /// CCM data RAM clock enable
+ @ReadWrite(bits: 20..<21)
+ var dtcmramen: DTCMRAMEN
+
+ /// Backup SRAM interface clock enable
+ @ReadWrite(bits: 18..<19)
+ var bkpsramen: BKPSRAMEN
+
+ /// CRC clock enable
+ @ReadWrite(bits: 12..<13)
+ var crcen: CRCEN
+
+ /// IO port K clock enable
+ @ReadWrite(bits: 10..<11)
+ var gpioken: GPIOKEN
+
+ /// IO port J clock enable
+ @ReadWrite(bits: 9..<10)
+ var gpiojen: GPIOJEN
+
+ /// IO port I clock enable
+ @ReadWrite(bits: 8..<9)
+ var gpioien: GPIOIEN
+
+ /// IO port H clock enable
+ @ReadWrite(bits: 7..<8)
+ var gpiohen: GPIOHEN
+
+ /// IO port G clock enable
+ @ReadWrite(bits: 6..<7)
+ var gpiogen: GPIOGEN
+
+ /// IO port F clock enable
+ @ReadWrite(bits: 5..<6)
+ var gpiofen: GPIOFEN
+
+ /// IO port E clock enable
+ @ReadWrite(bits: 4..<5)
+ var gpioeen: GPIOEEN
+
+ /// IO port D clock enable
+ @ReadWrite(bits: 3..<4)
+ var gpioden: GPIODEN
+
+ /// IO port C clock enable
+ @ReadWrite(bits: 2..<3)
+ var gpiocen: GPIOCEN
+
+ /// IO port B clock enable
+ @ReadWrite(bits: 1..<2)
+ var gpioben: GPIOBEN
+
+ /// IO port A clock enable
+ @ReadWrite(bits: 0..<1, as: GPIOAENValues.self)
+ var gpioaen: GPIOAEN
+ }
+
+ /// AHB2 peripheral clock enable register
+ @Register(bitWidth: 32)
+ struct AHB2ENR {
+ /// USB OTG FS clock enable
+ @ReadWrite(bits: 7..<8)
+ var otgfsen: OTGFSEN
+
+ /// Random number generator clock enable
+ @ReadWrite(bits: 6..<7)
+ var rngen: RNGEN
+
+ /// Hash modules clock enable
+ @ReadWrite(bits: 5..<6)
+ var hashen: HASHEN
+
+ /// Cryptographic modules clock enable
+ @ReadWrite(bits: 4..<5)
+ var crypen: CRYPEN
+
+ /// Camera interface enable
+ @ReadWrite(bits: 0..<1, as: DCMIENValues.self)
+ var dcmien: DCMIEN
+ }
+
+ /// AHB3 peripheral clock enable register
+ @Register(bitWidth: 32)
+ struct AHB3ENR {
+ /// Flexible memory controller module clock enable
+ @ReadWrite(bits: 0..<1, as: FMCENValues.self)
+ var fmcen: FMCEN
+
+ /// Quad SPI memory controller clock enable
+ @ReadWrite(bits: 1..<2)
+ var qspien: QSPIEN
+ }
+
+ /// APB1 peripheral clock enable register
+ @Register(bitWidth: 32)
+ struct APB1ENR {
+ /// TIM2 clock enable
+ @ReadWrite(bits: 0..<1, as: TIM2ENValues.self)
+ var tim2en: TIM2EN
+
+ /// TIM3 clock enable
+ @ReadWrite(bits: 1..<2)
+ var tim3en: TIM3EN
+
+ /// TIM4 clock enable
+ @ReadWrite(bits: 2..<3)
+ var tim4en: TIM4EN
+
+ /// TIM5 clock enable
+ @ReadWrite(bits: 3..<4)
+ var tim5en: TIM5EN
+
+ /// TIM6 clock enable
+ @ReadWrite(bits: 4..<5)
+ var tim6en: TIM6EN
+
+ /// TIM7 clock enable
+ @ReadWrite(bits: 5..<6)
+ var tim7en: TIM7EN
+
+ /// TIM12 clock enable
+ @ReadWrite(bits: 6..<7)
+ var tim12en: TIM12EN
+
+ /// TIM13 clock enable
+ @ReadWrite(bits: 7..<8)
+ var tim13en: TIM13EN
+
+ /// TIM14 clock enable
+ @ReadWrite(bits: 8..<9)
+ var tim14en: TIM14EN
+
+ /// Window watchdog clock enable
+ @ReadWrite(bits: 11..<12)
+ var wwdgen: WWDGEN
+
+ /// SPI2 clock enable
+ @ReadWrite(bits: 14..<15)
+ var spi2en: SPI2EN
+
+ /// SPI3 clock enable
+ @ReadWrite(bits: 15..<16)
+ var spi3en: SPI3EN
+
+ /// USART 2 clock enable
+ @ReadWrite(bits: 17..<18)
+ var usart2en: USART2EN
+
+ /// USART3 clock enable
+ @ReadWrite(bits: 18..<19)
+ var usart3en: USART3EN
+
+ /// UART4 clock enable
+ @ReadWrite(bits: 19..<20)
+ var uart4en: UART4EN
+
+ /// UART5 clock enable
+ @ReadWrite(bits: 20..<21)
+ var uart5en: UART5EN
+
+ /// I2C1 clock enable
+ @ReadWrite(bits: 21..<22)
+ var i2c1en: I2C1EN
+
+ /// I2C2 clock enable
+ @ReadWrite(bits: 22..<23)
+ var i2c2en: I2C2EN
+
+ /// I2C3 clock enable
+ @ReadWrite(bits: 23..<24)
+ var i2c3en: I2C3EN
+
+ /// CAN 1 clock enable
+ @ReadWrite(bits: 25..<26)
+ var can1en: CAN1EN
+
+ /// CAN 2 clock enable
+ @ReadWrite(bits: 26..<27)
+ var can2en: CAN2EN
+
+ /// Power interface clock enable
+ @ReadWrite(bits: 28..<29)
+ var pwren: PWREN
+
+ /// DAC interface clock enable
+ @ReadWrite(bits: 29..<30)
+ var dacen: DACEN
+
+ /// UART7 clock enable
+ @ReadWrite(bits: 30..<31)
+ var uart7en: UART7EN
+
+ /// UART8 clock enable
+ @ReadWrite(bits: 31..<32)
+ var uart8en: UART8EN
+
+ /// SPDIF-RX clock enable
+ @ReadWrite(bits: 16..<17)
+ var spdifrxen: SPDIFRXEN
+
+ /// HDMI-CEN clock enable
+ @ReadWrite(bits: 27..<28)
+ var cecen: CECEN
+
+ /// Low power timer 1 clock enable
+ @ReadWrite(bits: 9..<10)
+ var lptim1en: LPTIM1EN
+
+ /// I2C4 clock enable
+ @ReadWrite(bits: 24..<25)
+ var i2c4en: I2C4EN
+ }
+
+ /// APB2 peripheral clock enable register
+ @Register(bitWidth: 32)
+ struct APB2ENR {
+ /// TIM1 clock enable
+ @ReadWrite(bits: 0..<1, as: TIM1ENValues.self)
+ var tim1en: TIM1EN
+
+ /// TIM8 clock enable
+ @ReadWrite(bits: 1..<2)
+ var tim8en: TIM8EN
+
+ /// USART1 clock enable
+ @ReadWrite(bits: 4..<5)
+ var usart1en: USART1EN
+
+ /// USART6 clock enable
+ @ReadWrite(bits: 5..<6)
+ var usart6en: USART6EN
+
+ /// ADC1 clock enable
+ @ReadWrite(bits: 8..<9)
+ var adc1en: ADC1EN
+
+ /// ADC2 clock enable
+ @ReadWrite(bits: 9..<10)
+ var adc2en: ADC2EN
+
+ /// ADC3 clock enable
+ @ReadWrite(bits: 10..<11)
+ var adc3en: ADC3EN
+
+ /// SPI1 clock enable
+ @ReadWrite(bits: 12..<13)
+ var spi1en: SPI1EN
+
+ /// SPI4 clock enable
+ @ReadWrite(bits: 13..<14)
+ var spi4en: SPI4EN
+
+ /// System configuration controller clock enable
+ @ReadWrite(bits: 14..<15)
+ var syscfgen: SYSCFGEN
+
+ /// TIM9 clock enable
+ @ReadWrite(bits: 16..<17)
+ var tim9en: TIM9EN
+
+ /// TIM10 clock enable
+ @ReadWrite(bits: 17..<18)
+ var tim10en: TIM10EN
+
+ /// TIM11 clock enable
+ @ReadWrite(bits: 18..<19)
+ var tim11en: TIM11EN
+
+ /// SPI5 clock enable
+ @ReadWrite(bits: 20..<21)
+ var spi5en: SPI5EN
+
+ /// SPI6 clock enable
+ @ReadWrite(bits: 21..<22)
+ var spi6en: SPI6EN
+
+ /// SAI1 clock enable
+ @ReadWrite(bits: 22..<23)
+ var sai1en: SAI1EN
+
+ /// LTDC clock enable
+ @ReadWrite(bits: 26..<27)
+ var ltdcen: LTDCEN
+
+ /// SAI2 clock enable
+ @ReadWrite(bits: 23..<24)
+ var sai2en: SAI2EN
+
+ /// SDMMC1 clock enable
+ @ReadWrite(bits: 11..<12)
+ var sdmmc1en: SDMMC1EN
+ }
+
+ /// AHB1 peripheral clock enable in low power mode register
+ @Register(bitWidth: 32)
+ struct AHB1LPENR {
+ /// IO port A clock enable during sleep mode
+ @ReadWrite(bits: 0..<1, as: GPIOALPENValues.self)
+ var gpioalpen: GPIOALPEN
+
+ /// IO port B clock enable during Sleep mode
+ @ReadWrite(bits: 1..<2)
+ var gpioblpen: GPIOBLPEN
+
+ /// IO port C clock enable during Sleep mode
+ @ReadWrite(bits: 2..<3)
+ var gpioclpen: GPIOCLPEN
+
+ /// IO port D clock enable during Sleep mode
+ @ReadWrite(bits: 3..<4)
+ var gpiodlpen: GPIODLPEN
+
+ /// IO port E clock enable during Sleep mode
+ @ReadWrite(bits: 4..<5)
+ var gpioelpen: GPIOELPEN
+
+ /// IO port F clock enable during Sleep mode
+ @ReadWrite(bits: 5..<6)
+ var gpioflpen: GPIOFLPEN
+
+ /// IO port G clock enable during Sleep mode
+ @ReadWrite(bits: 6..<7)
+ var gpioglpen: GPIOGLPEN
+
+ /// IO port H clock enable during Sleep mode
+ @ReadWrite(bits: 7..<8)
+ var gpiohlpen: GPIOHLPEN
+
+ /// IO port I clock enable during Sleep mode
+ @ReadWrite(bits: 8..<9)
+ var gpioilpen: GPIOILPEN
+
+ /// IO port J clock enable during Sleep mode
+ @ReadWrite(bits: 9..<10)
+ var gpiojlpen: GPIOJLPEN
+
+ /// IO port K clock enable during Sleep mode
+ @ReadWrite(bits: 10..<11)
+ var gpioklpen: GPIOKLPEN
+
+ /// CRC clock enable during Sleep mode
+ @ReadWrite(bits: 12..<13)
+ var crclpen: CRCLPEN
+
+ /// Flash interface clock enable during Sleep mode
+ @ReadWrite(bits: 15..<16)
+ var flitflpen: FLITFLPEN
+
+ /// SRAM 1interface clock enable during Sleep mode
+ @ReadWrite(bits: 16..<17)
+ var sram1lpen: SRAM1LPEN
+
+ /// SRAM 2 interface clock enable during Sleep mode
+ @ReadWrite(bits: 17..<18)
+ var sram2lpen: SRAM2LPEN
+
+ /// Backup SRAM interface clock enable during Sleep mode
+ @ReadWrite(bits: 18..<19)
+ var bkpsramlpen: BKPSRAMLPEN
+
+ /// SRAM 3 interface clock enable during Sleep mode
+ @ReadWrite(bits: 19..<20)
+ var sram3lpen: SRAM3LPEN
+
+ /// DMA1 clock enable during Sleep mode
+ @ReadWrite(bits: 21..<22)
+ var dma1lpen: DMA1LPEN
+
+ /// DMA2 clock enable during Sleep mode
+ @ReadWrite(bits: 22..<23)
+ var dma2lpen: DMA2LPEN
+
+ /// DMA2D clock enable during Sleep mode
+ @ReadWrite(bits: 23..<24)
+ var dma2dlpen: DMA2DLPEN
+
+ /// Ethernet MAC clock enable during Sleep mode
+ @ReadWrite(bits: 25..<26)
+ var ethmaclpen: ETHMACLPEN
+
+ /// Ethernet transmission clock enable during Sleep mode
+ @ReadWrite(bits: 26..<27)
+ var ethmactxlpen: ETHMACTXLPEN
+
+ /// Ethernet reception clock enable during Sleep mode
+ @ReadWrite(bits: 27..<28)
+ var ethmacrxlpen: ETHMACRXLPEN
+
+ /// Ethernet PTP clock enable during Sleep mode
+ @ReadWrite(bits: 28..<29)
+ var ethmacptplpen: ETHMACPTPLPEN
+
+ /// USB OTG HS clock enable during Sleep mode
+ @ReadWrite(bits: 29..<30)
+ var otghslpen: OTGHSLPEN
+
+ /// USB OTG HS ULPI clock enable during Sleep mode
+ @ReadWrite(bits: 30..<31)
+ var otghsulpilpen: OTGHSULPILPEN
+
+ /// AXI to AHB bridge clock enable during Sleep mode
+ @ReadWrite(bits: 13..<14)
+ var axilpen: AXILPEN
+
+ /// DTCM RAM interface clock enable during Sleep mode
+ @ReadWrite(bits: 20..<21)
+ var dtcmlpen: DTCMLPEN
+ }
+
+ /// AHB2 peripheral clock enable in low power mode register
+ @Register(bitWidth: 32)
+ struct AHB2LPENR {
+ /// USB OTG FS clock enable during Sleep mode
+ @ReadWrite(bits: 7..<8)
+ var otgfslpen: OTGFSLPEN
+
+ /// Random number generator clock enable during Sleep mode
+ @ReadWrite(bits: 6..<7)
+ var rnglpen: RNGLPEN
+
+ /// Hash modules clock enable during Sleep mode
+ @ReadWrite(bits: 5..<6)
+ var hashlpen: HASHLPEN
+
+ /// Cryptography modules clock enable during Sleep mode
+ @ReadWrite(bits: 4..<5)
+ var cryplpen: CRYPLPEN
+
+ /// Camera interface enable during Sleep mode
+ @ReadWrite(bits: 0..<1, as: DCMILPENValues.self)
+ var dcmilpen: DCMILPEN
+ }
+
+ /// AHB3 peripheral clock enable in low power mode register
+ @Register(bitWidth: 32)
+ struct AHB3LPENR {
+ /// Flexible memory controller module clock enable during Sleep mode
+ @ReadWrite(bits: 0..<1, as: FMCLPENValues.self)
+ var fmclpen: FMCLPEN
+
+ /// Quand SPI memory controller clock enable during Sleep mode
+ @ReadWrite(bits: 1..<2)
+ var qspilpen: QSPILPEN
+ }
+
+ /// APB1 peripheral clock enable in low power mode register
+ @Register(bitWidth: 32)
+ struct APB1LPENR {
+ /// TIM2 clock enable during Sleep mode
+ @ReadWrite(bits: 0..<1, as: TIM2LPENValues.self)
+ var tim2lpen: TIM2LPEN
+
+ /// TIM3 clock enable during Sleep mode
+ @ReadWrite(bits: 1..<2)
+ var tim3lpen: TIM3LPEN
+
+ /// TIM4 clock enable during Sleep mode
+ @ReadWrite(bits: 2..<3)
+ var tim4lpen: TIM4LPEN
+
+ /// TIM5 clock enable during Sleep mode
+ @ReadWrite(bits: 3..<4)
+ var tim5lpen: TIM5LPEN
+
+ /// TIM6 clock enable during Sleep mode
+ @ReadWrite(bits: 4..<5)
+ var tim6lpen: TIM6LPEN
+
+ /// TIM7 clock enable during Sleep mode
+ @ReadWrite(bits: 5..<6)
+ var tim7lpen: TIM7LPEN
+
+ /// TIM12 clock enable during Sleep mode
+ @ReadWrite(bits: 6..<7)
+ var tim12lpen: TIM12LPEN
+
+ /// TIM13 clock enable during Sleep mode
+ @ReadWrite(bits: 7..<8)
+ var tim13lpen: TIM13LPEN
+
+ /// TIM14 clock enable during Sleep mode
+ @ReadWrite(bits: 8..<9)
+ var tim14lpen: TIM14LPEN
+
+ /// Window watchdog clock enable during Sleep mode
+ @ReadWrite(bits: 11..<12)
+ var wwdglpen: WWDGLPEN
+
+ /// SPI2 clock enable during Sleep mode
+ @ReadWrite(bits: 14..<15)
+ var spi2lpen: SPI2LPEN
+
+ /// SPI3 clock enable during Sleep mode
+ @ReadWrite(bits: 15..<16)
+ var spi3lpen: SPI3LPEN
+
+ /// USART2 clock enable during Sleep mode
+ @ReadWrite(bits: 17..<18)
+ var usart2lpen: USART2LPEN
+
+ /// USART3 clock enable during Sleep mode
+ @ReadWrite(bits: 18..<19)
+ var usart3lpen: USART3LPEN
+
+ /// UART4 clock enable during Sleep mode
+ @ReadWrite(bits: 19..<20)
+ var uart4lpen: UART4LPEN
+
+ /// UART5 clock enable during Sleep mode
+ @ReadWrite(bits: 20..<21)
+ var uart5lpen: UART5LPEN
+
+ /// I2C1 clock enable during Sleep mode
+ @ReadWrite(bits: 21..<22)
+ var i2c1lpen: I2C1LPEN
+
+ /// I2C2 clock enable during Sleep mode
+ @ReadWrite(bits: 22..<23)
+ var i2c2lpen: I2C2LPEN
+
+ /// I2C3 clock enable during Sleep mode
+ @ReadWrite(bits: 23..<24)
+ var i2c3lpen: I2C3LPEN
+
+ /// CAN 1 clock enable during Sleep mode
+ @ReadWrite(bits: 25..<26)
+ var can1lpen: CAN1LPEN
+
+ /// CAN 2 clock enable during Sleep mode
+ @ReadWrite(bits: 26..<27)
+ var can2lpen: CAN2LPEN
+
+ /// Power interface clock enable during Sleep mode
+ @ReadWrite(bits: 28..<29)
+ var pwrlpen: PWRLPEN
+
+ /// DAC interface clock enable during Sleep mode
+ @ReadWrite(bits: 29..<30)
+ var daclpen: DACLPEN
+
+ /// UART7 clock enable during Sleep mode
+ @ReadWrite(bits: 30..<31)
+ var uart7lpen: UART7LPEN
+
+ /// UART8 clock enable during Sleep mode
+ @ReadWrite(bits: 31..<32)
+ var uart8lpen: UART8LPEN
+
+ /// SPDIF-RX clock enable during sleep mode
+ @ReadWrite(bits: 16..<17)
+ var spdifrxlpen: SPDIFRXLPEN
+
+ /// HDMI-CEN clock enable during Sleep mode
+ @ReadWrite(bits: 27..<28)
+ var ceclpen: CECLPEN
+
+ /// low power timer 1 clock enable during Sleep mode
+ @ReadWrite(bits: 9..<10)
+ var lptim1lpen: LPTIM1LPEN
+
+ /// I2C4 clock enable during Sleep mode
+ @ReadWrite(bits: 24..<25)
+ var i2c4lpen: I2C4LPEN
+ }
+
+ /// APB2 peripheral clock enabled in low power mode register
+ @Register(bitWidth: 32)
+ struct APB2LPENR {
+ /// TIM1 clock enable during Sleep mode
+ @ReadWrite(bits: 0..<1, as: TIM1LPENValues.self)
+ var tim1lpen: TIM1LPEN
+
+ /// TIM8 clock enable during Sleep mode
+ @ReadWrite(bits: 1..<2)
+ var tim8lpen: TIM8LPEN
+
+ /// USART1 clock enable during Sleep mode
+ @ReadWrite(bits: 4..<5)
+ var usart1lpen: USART1LPEN
+
+ /// USART6 clock enable during Sleep mode
+ @ReadWrite(bits: 5..<6)
+ var usart6lpen: USART6LPEN
+
+ /// ADC1 clock enable during Sleep mode
+ @ReadWrite(bits: 8..<9)
+ var adc1lpen: ADC1LPEN
+
+ /// ADC2 clock enable during Sleep mode
+ @ReadWrite(bits: 9..<10)
+ var adc2lpen: ADC2LPEN
+
+ /// ADC 3 clock enable during Sleep mode
+ @ReadWrite(bits: 10..<11)
+ var adc3lpen: ADC3LPEN
+
+ /// SPI 1 clock enable during Sleep mode
+ @ReadWrite(bits: 12..<13)
+ var spi1lpen: SPI1LPEN
+
+ /// SPI 4 clock enable during Sleep mode
+ @ReadWrite(bits: 13..<14)
+ var spi4lpen: SPI4LPEN
+
+ /// System configuration controller clock enable during Sleep mode
+ @ReadWrite(bits: 14..<15)
+ var syscfglpen: SYSCFGLPEN
+
+ /// TIM9 clock enable during sleep mode
+ @ReadWrite(bits: 16..<17)
+ var tim9lpen: TIM9LPEN
+
+ /// TIM10 clock enable during Sleep mode
+ @ReadWrite(bits: 17..<18)
+ var tim10lpen: TIM10LPEN
+
+ /// TIM11 clock enable during Sleep mode
+ @ReadWrite(bits: 18..<19)
+ var tim11lpen: TIM11LPEN
+
+ /// SPI 5 clock enable during Sleep mode
+ @ReadWrite(bits: 20..<21)
+ var spi5lpen: SPI5LPEN
+
+ /// SPI 6 clock enable during Sleep mode
+ @ReadWrite(bits: 21..<22)
+ var spi6lpen: SPI6LPEN
+
+ /// SAI1 clock enable during sleep mode
+ @ReadWrite(bits: 22..<23)
+ var sai1lpen: SAI1LPEN
+
+ /// LTDC clock enable during sleep mode
+ @ReadWrite(bits: 26..<27)
+ var ltdclpen: LTDCLPEN
+
+ /// SAI2 clock enable during sleep mode
+ @ReadWrite(bits: 23..<24)
+ var sai2lpen: SAI2LPEN
+
+ /// SDMMC1 clock enable during Sleep mode
+ @ReadWrite(bits: 11..<12)
+ var sdmmc1lpen: SDMMC1LPEN
+ }
+
+ /// Backup domain control register
+ @Register(bitWidth: 32)
+ struct BDCR {
+ /// Backup domain software reset
+ @ReadWrite(bits: 16..<17, as: BDRSTValues.self)
+ var bdrst: BDRST
+
+ /// RTC clock enable
+ @ReadWrite(bits: 15..<16, as: RTCENValues.self)
+ var rtcen: RTCEN
+
+ /// External low-speed oscillator bypass
+ @ReadWrite(bits: 2..<3, as: LSEBYPValues.self)
+ var lsebyp: LSEBYP
+
+ /// External low-speed oscillator ready
+ @ReadOnly(bits: 1..<2)
+ var lserdy: LSERDY
+
+ /// External low-speed oscillator enable
+ @ReadWrite(bits: 0..<1, as: LSEONValues.self)
+ var lseon: LSEON
+
+ /// LSE oscillator drive capability
+ @ReadWrite(bits: 3..<5, as: LSEDRVValues.self)
+ var lsedrv: LSEDRV
+
+ /// RTC clock source selection
+ @Reserved(bits: 8..<10, as: RTCSELValues.self)
+ var rtcsel: RTCSEL
+ }
+
+ /// clock control & status register
+ @Register(bitWidth: 32)
+ struct CSR {
+ /// Low-power reset flag
+ @ReadWrite(bits: 31..<32)
+ var lpwrrstf: LPWRRSTF
+
+ /// Window watchdog reset flag
+ @ReadWrite(bits: 30..<31)
+ var wwdgrstf: WWDGRSTF
+
+ /// Independent watchdog reset flag
+ @ReadWrite(bits: 29..<30)
+ var wdgrstf: WDGRSTF
+
+ /// Software reset flag
+ @ReadWrite(bits: 28..<29)
+ var sftrstf: SFTRSTF
+
+ /// POR/PDR reset flag
+ @ReadWrite(bits: 27..<28)
+ var porrstf: PORRSTF
+
+ /// PIN reset flag
+ @ReadWrite(bits: 26..<27)
+ var padrstf: PADRSTF
+
+ /// BOR reset flag
+ @ReadWrite(bits: 25..<26)
+ var borrstf: BORRSTF
+
+ /// Remove reset flag
+ @ReadWrite(bits: 24..<25)
+ var rmvf: RMVF
+
+ /// Internal low-speed oscillator ready
+ @ReadOnly(bits: 1..<2)
+ var lsirdy: LSIRDY
+
+ /// Internal low-speed oscillator enable
+ @ReadWrite(bits: 0..<1, as: LSIONValues.self)
+ var lsion: LSION
+ }
+
+ /// spread spectrum clock generation register
+ @Register(bitWidth: 32)
+ struct SSCGR {
+ /// Spread spectrum modulation enable
+ @ReadWrite(bits: 31..<32, as: SSCGENValues.self)
+ var sscgen: SSCGEN
+
+ /// Spread Select
+ @ReadWrite(bits: 30..<31, as: SPREADSELValues.self)
+ var spreadsel: SPREADSEL
+
+ /// Incrementation step
+ @ReadWrite(bits: 13..<28)
+ var incstep: INCSTEP
+
+ /// Modulation period
+ @ReadWrite(bits: 0..<13)
+ var modper: MODPER
+ }
+
+ /// PLLI2S configuration register
+ @Register(bitWidth: 32)
+ struct PLLI2SCFGR {
+ /// PLLI2S division factor for I2S clocks
+ @ReadWrite(bits: 28..<31)
+ var plli2sr: PLLI2SR
+
+ /// PLLI2S division factor for SAI1 clock
+ @ReadWrite(bits: 24..<28)
+ var plli2sq: PLLI2SQ
+
+ /// PLLI2S multiplication factor for VCO
+ @ReadWrite(bits: 6..<15)
+ var plli2sn: PLLI2SN
+
+ /// PLLI2S division factor for SPDIFRX clock
+ @ReadWrite(bits: 16..<18, as: PLLI2SPValues.self)
+ var plli2sp: PLLI2SP
+ }
+
+ /// PLL configuration register
+ @Register(bitWidth: 32)
+ struct PLLSAICFGR {
+ /// PLLSAI division factor for VCO
+ @ReadWrite(bits: 6..<15)
+ var pllsain: PLLSAIN
+
+ /// PLLSAI division factor for 48MHz clock
+ @ReadWrite(bits: 16..<18, as: PLLSAIPValues.self)
+ var pllsaip: PLLSAIP
+
+ /// PLLSAI division factor for SAI clock
+ @ReadWrite(bits: 24..<28)
+ var pllsaiq: PLLSAIQ
+
+ /// PLLSAI division factor for LCD clock
+ @ReadWrite(bits: 28..<31)
+ var pllsair: PLLSAIR
+ }
+
+ /// dedicated clocks configuration register
+ @Register(bitWidth: 32)
+ struct DCKCFGR1 {
+ /// PLLI2S division factor for SAI1 clock
+ @ReadWrite(bits: 0..<5, as: PLLI2SDIVQValues.self)
+ var plli2sdivq: PLLI2SDIVQ
+
+ /// PLLSAI division factor for SAI1 clock
+ @ReadWrite(bits: 8..<13, as: PLLSAIDIVQValues.self)
+ var pllsaidivq: PLLSAIDIVQ
+
+ /// division factor for LCD_CLK
+ @ReadWrite(bits: 16..<18, as: PLLSAIDIVRValues.self)
+ var pllsaidivr: PLLSAIDIVR
+
+ /// SAI1 clock source selection
+ @ReadWrite(bits: 20..<22, as: SAI1SELValues.self)
+ var sai1sel: SAI1SEL
+
+ /// SAI2 clock source selection
+ @ReadWrite(bits: 22..<24, as: SAI2SELValues.self)
+ var sai2sel: SAI2SEL
+
+ /// Timers clocks prescalers selection
+ @ReadWrite(bits: 24..<25, as: TIMPREValues.self)
+ var timpre: TIMPRE
+ }
+
+ /// dedicated clocks configuration register
+ @Register(bitWidth: 32)
+ struct DCKCFGR2 {
+ /// USART 1 clock source selection
+ @ReadWrite(bits: 0..<2, as: USART1SELValues.self)
+ var usart1sel: USART1SEL
+
+ /// USART 2 clock source selection
+ @ReadWrite(bits: 2..<4, as: USART2SELValues.self)
+ var usart2sel: USART2SEL
+
+ /// USART 3 clock source selection
+ @ReadWrite(bits: 4..<6)
+ var usart3sel: USART3SEL
+
+ /// UART 4 clock source selection
+ @ReadWrite(bits: 6..<8)
+ var uart4sel: UART4SEL
+
+ /// UART 5 clock source selection
+ @ReadWrite(bits: 8..<10)
+ var uart5sel: UART5SEL
+
+ /// USART 6 clock source selection
+ @ReadWrite(bits: 10..<12)
+ var usart6sel: USART6SEL
+
+ /// UART 7 clock source selection
+ @ReadWrite(bits: 12..<14)
+ var uart7sel: UART7SEL
+
+ /// UART 8 clock source selection
+ @ReadWrite(bits: 14..<16)
+ var uart8sel: UART8SEL
+
+ /// I2C1 clock source selection
+ @ReadWrite(bits: 16..<18, as: I2C1SELValues.self)
+ var i2c1sel: I2C1SEL
+
+ /// I2C2 clock source selection
+ @ReadWrite(bits: 18..<20)
+ var i2c2sel: I2C2SEL
+
+ /// I2C3 clock source selection
+ @ReadWrite(bits: 20..<22)
+ var i2c3sel: I2C3SEL
+
+ /// I2C4 clock source selection
+ @ReadWrite(bits: 22..<24)
+ var i2c4sel: I2C4SEL
+
+ /// Low power timer 1 clock source selection
+ @ReadWrite(bits: 24..<26, as: LPTIM1SELValues.self)
+ var lptim1sel: LPTIM1SEL
+
+ /// HDMI-CEC clock source selection
+ @ReadWrite(bits: 26..<27, as: CECSELValues.self)
+ var cecsel: CECSEL
+
+ /// 48MHz clock source selection
+ @ReadWrite(bits: 27..<28, as: CK48MSELValues.self)
+ var ck48msel: CK48MSEL
+
+ /// SDMMC clock source selection
+ @ReadWrite(bits: 28..<29, as: SDMMC1SELValues.self)
+ var sdmmc1sel: SDMMC1SEL
+ }
+}
+
+extension RCC.CR {
+ struct CSSONValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Clock security system disabled (clock detector OFF)
+ static let Off = Self(rawValue: 0x0)
+
+ /// Clock security system enable (clock detector ON if the HSE is ready, OFF if not)
+ static let On = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CR {
+ struct HSEBYPValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// HSE crystal oscillator not bypassed
+ static let NotBypassed = Self(rawValue: 0x0)
+
+ /// HSE crystal oscillator bypassed with external clock
+ static let Bypassed = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CR {
+ struct HSIONValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Clock Off
+ static let Off = Self(rawValue: 0x0)
+
+ /// Clock On
+ static let On = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.PLLCFGR {
+ struct PLLSRCValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// HSI clock selected as PLL and PLLI2S clock entry
+ static let HSI = Self(rawValue: 0x0)
+
+ /// HSE oscillator clock selected as PLL and PLLI2S clock entry
+ static let HSE = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.PLLCFGR {
+ struct PLLPValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// PLLP=2
+ static let Div2 = Self(rawValue: 0x0)
+
+ /// PLLP=4
+ static let Div4 = Self(rawValue: 0x1)
+
+ /// PLLP=6
+ static let Div6 = Self(rawValue: 0x2)
+
+ /// PLLP=8
+ static let Div8 = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CFGR {
+ struct MCO2Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// System clock (SYSCLK) selected
+ static let SYSCLK = Self(rawValue: 0x0)
+
+ /// PLLI2S clock selected
+ static let PLLI2S = Self(rawValue: 0x1)
+
+ /// HSE oscillator clock selected
+ static let HSE = Self(rawValue: 0x2)
+
+ /// PLL clock selected
+ static let PLL = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CFGR {
+ struct MCO1PREValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 3
+
+ /// No division
+ static let Div1 = Self(rawValue: 0x0)
+
+ /// Division by 2
+ static let Div2 = Self(rawValue: 0x4)
+
+ /// Division by 3
+ static let Div3 = Self(rawValue: 0x5)
+
+ /// Division by 4
+ static let Div4 = Self(rawValue: 0x6)
+
+ /// Division by 5
+ static let Div5 = Self(rawValue: 0x7)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CFGR {
+ struct I2SSRCValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// PLLI2S clock used as I2S clock source
+ static let PLLI2S = Self(rawValue: 0x0)
+
+ /// External clock mapped on the I2S_CKIN pin used as I2S clock source
+ static let CKIN = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CFGR {
+ struct MCO1Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// HSI clock selected
+ static let HSI = Self(rawValue: 0x0)
+
+ /// LSE oscillator selected
+ static let LSE = Self(rawValue: 0x1)
+
+ /// HSE oscillator clock selected
+ static let HSE = Self(rawValue: 0x2)
+
+ /// PLL clock selected
+ static let PLL = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CFGR {
+ struct PPRE1Values: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 3
+
+ /// HCLK not divided
+ static let Div1 = Self(rawValue: 0x0)
+
+ /// HCLK divided by 2
+ static let Div2 = Self(rawValue: 0x4)
+
+ /// HCLK divided by 4
+ static let Div4 = Self(rawValue: 0x5)
+
+ /// HCLK divided by 8
+ static let Div8 = Self(rawValue: 0x6)
+
+ /// HCLK divided by 16
+ static let Div16 = Self(rawValue: 0x7)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CFGR {
+ struct HPREValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 4
+
+ /// SYSCLK not divided
+ static let Div1 = Self(rawValue: 0x0)
+
+ /// SYSCLK divided by 2
+ static let Div2 = Self(rawValue: 0x8)
+
+ /// SYSCLK divided by 4
+ static let Div4 = Self(rawValue: 0x9)
+
+ /// SYSCLK divided by 8
+ static let Div8 = Self(rawValue: 0xa)
+
+ /// SYSCLK divided by 16
+ static let Div16 = Self(rawValue: 0xb)
+
+ /// SYSCLK divided by 64
+ static let Div64 = Self(rawValue: 0xc)
+
+ /// SYSCLK divided by 128
+ static let Div128 = Self(rawValue: 0xd)
+
+ /// SYSCLK divided by 256
+ static let Div256 = Self(rawValue: 0xe)
+
+ /// SYSCLK divided by 512
+ static let Div512 = Self(rawValue: 0xf)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CFGR {
+ struct SWValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// HSI selected as system clock
+ static let HSI = Self(rawValue: 0x0)
+
+ /// HSE selected as system clock
+ static let HSE = Self(rawValue: 0x1)
+
+ /// PLL selected as system clock
+ static let PLL = Self(rawValue: 0x2)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CIR {
+ struct LSIRDYIEValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Interrupt disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Interrupt enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB1RSTR {
+ struct GPIOARSTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Reset the selected module
+ static let Reset = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB2RSTR {
+ struct DCMIRSTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Reset the selected module
+ static let Reset = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB3RSTR {
+ struct FMCRSTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Reset the selected module
+ static let Reset = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.APB1RSTR {
+ struct TIM2RSTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Reset the selected module
+ static let Reset = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.APB2RSTR {
+ struct TIM1RSTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Reset the selected module
+ static let Reset = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB1ENR {
+ struct GPIOAENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// The selected clock is disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// The selected clock is enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB2ENR {
+ struct DCMIENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// The selected clock is disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// The selected clock is enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB3ENR {
+ struct FMCENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// The selected clock is disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// The selected clock is enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.APB1ENR {
+ struct TIM2ENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// The selected clock is disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// The selected clock is enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.APB2ENR {
+ struct TIM1ENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// The selected clock is disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// The selected clock is enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB1LPENR {
+ struct GPIOALPENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Selected module is disabled during Sleep mode
+ static let DisabledInSleep = Self(rawValue: 0x0)
+
+ /// Selected module is enabled during Sleep mode
+ static let EnabledInSleep = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB2LPENR {
+ struct DCMILPENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Selected module is disabled during Sleep mode
+ static let DisabledInSleep = Self(rawValue: 0x0)
+
+ /// Selected module is enabled during Sleep mode
+ static let EnabledInSleep = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.AHB3LPENR {
+ struct FMCLPENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Selected module is disabled during Sleep mode
+ static let DisabledInSleep = Self(rawValue: 0x0)
+
+ /// Selected module is enabled during Sleep mode
+ static let EnabledInSleep = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.APB1LPENR {
+ struct TIM2LPENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Selected module is disabled during Sleep mode
+ static let DisabledInSleep = Self(rawValue: 0x0)
+
+ /// Selected module is enabled during Sleep mode
+ static let EnabledInSleep = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.APB2LPENR {
+ struct TIM1LPENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Selected module is disabled during Sleep mode
+ static let DisabledInSleep = Self(rawValue: 0x0)
+
+ /// Selected module is enabled during Sleep mode
+ static let EnabledInSleep = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.BDCR {
+ struct BDRSTValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Reset not activated
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Reset the entire RTC domain
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.BDCR {
+ struct RTCENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// RTC clock disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// RTC clock enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.BDCR {
+ struct LSEBYPValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// LSE crystal oscillator not bypassed
+ static let NotBypassed = Self(rawValue: 0x0)
+
+ /// LSE crystal oscillator bypassed with external clock
+ static let Bypassed = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.BDCR {
+ struct LSEONValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// LSE oscillator Off
+ static let Off = Self(rawValue: 0x0)
+
+ /// LSE oscillator On
+ static let On = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.BDCR {
+ struct LSEDRVValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// Low drive capacity
+ static let Low = Self(rawValue: 0x0)
+
+ /// Medium-high drive capacity
+ static let MediumHigh = Self(rawValue: 0x1)
+
+ /// Medium-low drive capacity
+ static let MediumLow = Self(rawValue: 0x2)
+
+ /// High drive capacity
+ static let High = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.BDCR {
+ struct RTCSELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// No clock
+ static let NoClock = Self(rawValue: 0x0)
+
+ /// LSE oscillator clock used as RTC clock
+ static let LSE = Self(rawValue: 0x1)
+
+ /// LSI oscillator clock used as RTC clock
+ static let LSI = Self(rawValue: 0x2)
+
+ /// HSE oscillator clock divided by a prescaler used as RTC clock
+ static let HSE = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.CSR {
+ struct LSIONValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// LSI oscillator Off
+ static let Off = Self(rawValue: 0x0)
+
+ /// LSI oscillator On
+ static let On = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.SSCGR {
+ struct SSCGENValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Spread spectrum modulation disabled
+ static let Disabled = Self(rawValue: 0x0)
+
+ /// Spread spectrum modulation enabled
+ static let Enabled = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.SSCGR {
+ struct SPREADSELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// Center spread
+ static let Center = Self(rawValue: 0x0)
+
+ /// Down spread
+ static let Down = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.PLLI2SCFGR {
+ struct PLLI2SPValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// PLL*P=2
+ static let Div2 = Self(rawValue: 0x0)
+
+ /// PLL*P=4
+ static let Div4 = Self(rawValue: 0x1)
+
+ /// PLL*P=6
+ static let Div6 = Self(rawValue: 0x2)
+
+ /// PLL*P=8
+ static let Div8 = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.PLLSAICFGR {
+ struct PLLSAIPValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// PLL*P=2
+ static let Div2 = Self(rawValue: 0x0)
+
+ /// PLL*P=4
+ static let Div4 = Self(rawValue: 0x1)
+
+ /// PLL*P=6
+ static let Div6 = Self(rawValue: 0x2)
+
+ /// PLL*P=8
+ static let Div8 = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR1 {
+ struct PLLI2SDIVQValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 5
+
+ /// PLLI2SDIVQ = /1
+ static let Div1 = Self(rawValue: 0x0)
+
+ /// PLLI2SDIVQ = /2
+ static let Div2 = Self(rawValue: 0x1)
+
+ /// PLLI2SDIVQ = /3
+ static let Div3 = Self(rawValue: 0x2)
+
+ /// PLLI2SDIVQ = /4
+ static let Div4 = Self(rawValue: 0x3)
+
+ /// PLLI2SDIVQ = /5
+ static let Div5 = Self(rawValue: 0x4)
+
+ /// PLLI2SDIVQ = /6
+ static let Div6 = Self(rawValue: 0x5)
+
+ /// PLLI2SDIVQ = /7
+ static let Div7 = Self(rawValue: 0x6)
+
+ /// PLLI2SDIVQ = /8
+ static let Div8 = Self(rawValue: 0x7)
+
+ /// PLLI2SDIVQ = /9
+ static let Div9 = Self(rawValue: 0x8)
+
+ /// PLLI2SDIVQ = /10
+ static let Div10 = Self(rawValue: 0x9)
+
+ /// PLLI2SDIVQ = /11
+ static let Div11 = Self(rawValue: 0xa)
+
+ /// PLLI2SDIVQ = /12
+ static let Div12 = Self(rawValue: 0xb)
+
+ /// PLLI2SDIVQ = /13
+ static let Div13 = Self(rawValue: 0xc)
+
+ /// PLLI2SDIVQ = /14
+ static let Div14 = Self(rawValue: 0xd)
+
+ /// PLLI2SDIVQ = /15
+ static let Div15 = Self(rawValue: 0xe)
+
+ /// PLLI2SDIVQ = /16
+ static let Div16 = Self(rawValue: 0xf)
+
+ /// PLLI2SDIVQ = /17
+ static let Div17 = Self(rawValue: 0x10)
+
+ /// PLLI2SDIVQ = /18
+ static let Div18 = Self(rawValue: 0x11)
+
+ /// PLLI2SDIVQ = /19
+ static let Div19 = Self(rawValue: 0x12)
+
+ /// PLLI2SDIVQ = /20
+ static let Div20 = Self(rawValue: 0x13)
+
+ /// PLLI2SDIVQ = /21
+ static let Div21 = Self(rawValue: 0x14)
+
+ /// PLLI2SDIVQ = /22
+ static let Div22 = Self(rawValue: 0x15)
+
+ /// PLLI2SDIVQ = /23
+ static let Div23 = Self(rawValue: 0x16)
+
+ /// PLLI2SDIVQ = /24
+ static let Div24 = Self(rawValue: 0x17)
+
+ /// PLLI2SDIVQ = /25
+ static let Div25 = Self(rawValue: 0x18)
+
+ /// PLLI2SDIVQ = /26
+ static let Div26 = Self(rawValue: 0x19)
+
+ /// PLLI2SDIVQ = /27
+ static let Div27 = Self(rawValue: 0x1a)
+
+ /// PLLI2SDIVQ = /28
+ static let Div28 = Self(rawValue: 0x1b)
+
+ /// PLLI2SDIVQ = /29
+ static let Div29 = Self(rawValue: 0x1c)
+
+ /// PLLI2SDIVQ = /30
+ static let Div30 = Self(rawValue: 0x1d)
+
+ /// PLLI2SDIVQ = /31
+ static let Div31 = Self(rawValue: 0x1e)
+
+ /// PLLI2SDIVQ = /32
+ static let Div32 = Self(rawValue: 0x1f)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR1 {
+ struct PLLSAIDIVQValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 5
+
+ /// PLLSAIDIVQ = /1
+ static let Div1 = Self(rawValue: 0x0)
+
+ /// PLLSAIDIVQ = /2
+ static let Div2 = Self(rawValue: 0x1)
+
+ /// PLLSAIDIVQ = /3
+ static let Div3 = Self(rawValue: 0x2)
+
+ /// PLLSAIDIVQ = /4
+ static let Div4 = Self(rawValue: 0x3)
+
+ /// PLLSAIDIVQ = /5
+ static let Div5 = Self(rawValue: 0x4)
+
+ /// PLLSAIDIVQ = /6
+ static let Div6 = Self(rawValue: 0x5)
+
+ /// PLLSAIDIVQ = /7
+ static let Div7 = Self(rawValue: 0x6)
+
+ /// PLLSAIDIVQ = /8
+ static let Div8 = Self(rawValue: 0x7)
+
+ /// PLLSAIDIVQ = /9
+ static let Div9 = Self(rawValue: 0x8)
+
+ /// PLLSAIDIVQ = /10
+ static let Div10 = Self(rawValue: 0x9)
+
+ /// PLLSAIDIVQ = /11
+ static let Div11 = Self(rawValue: 0xa)
+
+ /// PLLSAIDIVQ = /12
+ static let Div12 = Self(rawValue: 0xb)
+
+ /// PLLSAIDIVQ = /13
+ static let Div13 = Self(rawValue: 0xc)
+
+ /// PLLSAIDIVQ = /14
+ static let Div14 = Self(rawValue: 0xd)
+
+ /// PLLSAIDIVQ = /15
+ static let Div15 = Self(rawValue: 0xe)
+
+ /// PLLSAIDIVQ = /16
+ static let Div16 = Self(rawValue: 0xf)
+
+ /// PLLSAIDIVQ = /17
+ static let Div17 = Self(rawValue: 0x10)
+
+ /// PLLSAIDIVQ = /18
+ static let Div18 = Self(rawValue: 0x11)
+
+ /// PLLSAIDIVQ = /19
+ static let Div19 = Self(rawValue: 0x12)
+
+ /// PLLSAIDIVQ = /20
+ static let Div20 = Self(rawValue: 0x13)
+
+ /// PLLSAIDIVQ = /21
+ static let Div21 = Self(rawValue: 0x14)
+
+ /// PLLSAIDIVQ = /22
+ static let Div22 = Self(rawValue: 0x15)
+
+ /// PLLSAIDIVQ = /23
+ static let Div23 = Self(rawValue: 0x16)
+
+ /// PLLSAIDIVQ = /24
+ static let Div24 = Self(rawValue: 0x17)
+
+ /// PLLSAIDIVQ = /25
+ static let Div25 = Self(rawValue: 0x18)
+
+ /// PLLSAIDIVQ = /26
+ static let Div26 = Self(rawValue: 0x19)
+
+ /// PLLSAIDIVQ = /27
+ static let Div27 = Self(rawValue: 0x1a)
+
+ /// PLLSAIDIVQ = /28
+ static let Div28 = Self(rawValue: 0x1b)
+
+ /// PLLSAIDIVQ = /29
+ static let Div29 = Self(rawValue: 0x1c)
+
+ /// PLLSAIDIVQ = /30
+ static let Div30 = Self(rawValue: 0x1d)
+
+ /// PLLSAIDIVQ = /31
+ static let Div31 = Self(rawValue: 0x1e)
+
+ /// PLLSAIDIVQ = /32
+ static let Div32 = Self(rawValue: 0x1f)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR1 {
+ struct PLLSAIDIVRValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// PLLSAIDIVR = /2
+ static let Div2 = Self(rawValue: 0x0)
+
+ /// PLLSAIDIVR = /4
+ static let Div4 = Self(rawValue: 0x1)
+
+ /// PLLSAIDIVR = /8
+ static let Div8 = Self(rawValue: 0x2)
+
+ /// PLLSAIDIVR = /16
+ static let Div16 = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR1 {
+ struct SAI1SELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// SAI1 clock frequency = f(PLLSAI_Q) / PLLSAIDIVQ
+ static let PLLSAI = Self(rawValue: 0x0)
+
+ /// SAI1 clock frequency = f(PLLI2S_Q) / PLLI2SDIVQ
+ static let PLLI2S = Self(rawValue: 0x1)
+
+ /// SAI1 clock frequency = Alternate function input frequency
+ static let AFIF = Self(rawValue: 0x2)
+
+ /// SAI1 clock frequency = HSI or HSE
+ static let HSI_HSE = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR1 {
+ struct SAI2SELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// SAI2 clock frequency = f(PLLSAI_Q) / PLLSAIDIVQ
+ static let PLLSAI = Self(rawValue: 0x0)
+
+ /// SAI2 clock frequency = f(PLLI2S_Q) / PLLI2SDIVQ
+ static let PLLI2S = Self(rawValue: 0x1)
+
+ /// SAI2 clock frequency = Alternate function input frequency
+ static let AFIF = Self(rawValue: 0x2)
+
+ /// SAI2 clock frequency = HSI or HSE
+ static let HSI_HSE = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR1 {
+ struct TIMPREValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// If the APB prescaler is configured 1, TIMxCLK = PCLKx. Otherwise, TIMxCLK = 2xPCLKx
+ static let Mul1Or2 = Self(rawValue: 0x0)
+
+ /// If the APB prescaler is configured 1, 2 or 4, TIMxCLK = HCLK. Otherwise, TIMxCLK = 4xPCLKx
+ static let Mul1Or4 = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR2 {
+ struct USART1SELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// APB2 clock (PCLK2) is selected as USART clock
+ static let APB2 = Self(rawValue: 0x0)
+
+ /// System clock is selected as USART clock
+ static let SYSCLK = Self(rawValue: 0x1)
+
+ /// HSI clock is selected as USART clock
+ static let HSI = Self(rawValue: 0x2)
+
+ /// LSE clock is selected as USART clock
+ static let LSE = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR2 {
+ struct USART2SELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// APB1 clock (PCLK1) is selected as USART clock
+ static let APB1 = Self(rawValue: 0x0)
+
+ /// System clock is selected as USART clock
+ static let SYSCLK = Self(rawValue: 0x1)
+
+ /// HSI clock is selected as USART clock
+ static let HSI = Self(rawValue: 0x2)
+
+ /// LSE clock is selected as USART clock
+ static let LSE = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR2 {
+ struct I2C1SELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// APB clock selected as I2C clock
+ static let APB = Self(rawValue: 0x0)
+
+ /// System clock selected as I2C clock
+ static let SYSCLK = Self(rawValue: 0x1)
+
+ /// HSI clock selected as I2C clock
+ static let HSI = Self(rawValue: 0x2)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR2 {
+ struct LPTIM1SELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 2
+
+ /// APB1 clock (PCLK1) selected as LPTILM1 clock
+ static let APB1 = Self(rawValue: 0x0)
+
+ /// LSI clock is selected as LPTILM1 clock
+ static let LSI = Self(rawValue: 0x1)
+
+ /// HSI clock is selected as LPTILM1 clock
+ static let HSI = Self(rawValue: 0x2)
+
+ /// LSE clock is selected as LPTILM1 clock
+ static let LSE = Self(rawValue: 0x3)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR2 {
+ struct CECSELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// LSE clock is selected as HDMI-CEC clock
+ static let LSE = Self(rawValue: 0x0)
+
+ /// HSI divided by 488 clock is selected as HDMI-CEC clock
+ static let HSI_Div488 = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR2 {
+ struct CK48MSELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// 48MHz clock from PLL is selected
+ static let PLL = Self(rawValue: 0x0)
+
+ /// 48MHz clock from PLLSAI is selected
+ static let PLLSAI = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
+
+extension RCC.DCKCFGR2 {
+ struct SDMMC1SELValues: BitFieldProjectable, RawRepresentable {
+ static let bitWidth = 1
+
+ /// 48 MHz clock is selected as SD clock
+ static let CK48M = Self(rawValue: 0x0)
+
+ /// System clock is selected as SD clock
+ static let SYSCLK = Self(rawValue: 0x1)
+
+ var rawValue: UInt8
+
+ @inlinable @inline(__always)
+ init(rawValue: Self.RawValue) {
+ self.rawValue = rawValue
+ }
+ }
+}
diff --git a/stm32-lcd-logo/Support/PixelData.c b/stm32-lcd-logo/Sources/Support/PixelData.c
similarity index 100%
rename from stm32-lcd-logo/Support/PixelData.c
rename to stm32-lcd-logo/Sources/Support/PixelData.c
diff --git a/stm32-lcd-logo/Support/Startup.c b/stm32-lcd-logo/Sources/Support/Startup.c
similarity index 76%
rename from stm32-lcd-logo/Support/Startup.c
rename to stm32-lcd-logo/Sources/Support/Startup.c
index 16ea6367..6838bdc0 100644
--- a/stm32-lcd-logo/Support/Startup.c
+++ b/stm32-lcd-logo/Sources/Support/Startup.c
@@ -14,6 +14,20 @@
extern int main(int argc, char *argv[]);
+void *memset(void *b, int c, size_t len) {
+ for (int i = 0; i < len; i++) {
+ ((char *)b)[i] = c;
+ }
+ return b;
+}
+
+void *memcpy(void *restrict dst, const void *restrict src, size_t n) {
+ for (int i = 0; i < n; i++) {
+ ((char *)dst)[i] = ((char *)src)[i];
+ }
+ return dst;
+}
+
void reset(void) {
main(0, NULL);
}
diff --git a/stm32-lcd-logo/Support/Volatile.swift b/stm32-lcd-logo/Sources/Support/include/Support.h
similarity index 66%
rename from stm32-lcd-logo/Support/Volatile.swift
rename to stm32-lcd-logo/Sources/Support/include/Support.h
index f7041c3b..3c103eae 100644
--- a/stm32-lcd-logo/Support/Volatile.swift
+++ b/stm32-lcd-logo/Sources/Support/include/Support.h
@@ -1,20 +1,20 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift open source project
-//
-// Copyright (c) 2023 Apple Inc. and the Swift project authors.
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-//
-//===----------------------------------------------------------------------===//
-
-extension UnsafeMutablePointer where Pointee == UInt32 {
- func volatileLoad() -> Pointee {
- volatile_load_uint32_t(self)
- }
-
- func volatileStore(_ value: Pointee) {
- volatile_store_uint32_t(self, value)
- }
-}
+//===----------------------------------------------------------------------===//
+//
+// This source file is part of the Swift open source project
+//
+// Copyright (c) 2023 Apple Inc. and the Swift project authors.
+// Licensed under Apache License v2.0 with Runtime Library Exception
+//
+// See https://swift.org/LICENSE.txt for license information
+//
+//===----------------------------------------------------------------------===//
+
+#pragma once
+
+#include
+
+static inline void nop() {
+ asm volatile("nop");
+}
+
+extern uint32_t const * const logoPixelDataStartPointer;
diff --git a/stm32-lcd-logo/Support/Board.swift b/stm32-lcd-logo/Support/Board.swift
deleted file mode 100644
index bf850d29..00000000
--- a/stm32-lcd-logo/Support/Board.swift
+++ /dev/null
@@ -1,79 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift open source project
-//
-// Copyright (c) 2023 Apple Inc. and the Swift project authors.
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-//
-//===----------------------------------------------------------------------===//
-
-struct STM32F746Board {
- var led: HALGPIO
-
- init() {
- // Configure LED on I1
- STM32F746.enableGPIOPortClock(.i)
- led = HALGPIO(pin: .init(port: .i, number: 1))
- led.configure(
- configuration: .init(
- mode: .output, outputType: .pushPull, outputSpeed: .high, pull: .down,
- alternateFunction: .none, activeHigh: true))
- led.deassert()
-
- STM32F746.initializeLTCD()
-
- STM32F746.configureFlash()
-
- STM32F746.configureLTCD()
- }
-
- mutating func ledOn() {
- led.assert()
- }
-
- mutating func ledOff() {
- led.deassert()
- }
-
- mutating func delay(milliseconds: Int) {
- for _ in 0..<100_000 * milliseconds {
- nop()
- }
- }
-
- mutating func moveLogo(to point: Point) {
- STM32F746.setLayer2Position(point)
- }
-
- mutating func setBackgroundColor(color: Color) {
- STM32F746.setBackgroundColor(color)
- }
-
- var displaySize: Size {
- Size(
- width: STM32F746.LTDCConstants.displayWidth,
- height: STM32F746.LTDCConstants.displayHeight)
- }
-
- var logoLayerSize: Size {
- Size(width: 50, height: 50)
- }
-}
-
-struct Point {
- var x, y: Int
-
- func offset(by: Point) -> Point {
- Point(x: x + by.x, y: y + by.y)
- }
-}
-
-struct Size {
- var width, height: Int
-}
-
-struct Color {
- var r, g, b: Int
-}
diff --git a/stm32-lcd-logo/Support/BridgingHeader.h b/stm32-lcd-logo/Support/BridgingHeader.h
deleted file mode 100644
index 7713eba8..00000000
--- a/stm32-lcd-logo/Support/BridgingHeader.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift open source project
-//
-// Copyright (c) 2023 Apple Inc. and the Swift project authors.
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-//
-//===----------------------------------------------------------------------===//
-
-#pragma once
-
-#include
-
-static inline uint32_t volatile_load_uint32_t(const volatile uint32_t * _Nonnull source) {
- return *((const volatile uint32_t * _Nonnull) source);
-}
-
-static inline void volatile_store_uint32_t(volatile uint32_t * _Nonnull destination, uint32_t value) {
- *((volatile uint32_t * _Nonnull) destination) = value;
-}
-
-static inline void nop() {
- asm volatile("nop");
-}
-
-extern uint32_t *logoPixelDataStartPointer;
diff --git a/stm32-lcd-logo/Support/GPIO.swift b/stm32-lcd-logo/Support/GPIO.swift
deleted file mode 100644
index 5f5eb996..00000000
--- a/stm32-lcd-logo/Support/GPIO.swift
+++ /dev/null
@@ -1,2097 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift open source project
-//
-// Copyright (c) 2023 Apple Inc. and the Swift project authors.
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-//
-//===----------------------------------------------------------------------===//
-
-// swift-format-ignore-file
-
-/// General-purpose I/Os
-struct GPIO {
- var baseAddress: UnsafeMutableRawPointer
-
- enum Offsets {
- static let MODER: Int32 = 0x0
- static let OTYPER: Int32 = 0x4
- static let OSPEEDR: Int32 = 0x8
- static let PUPDR: Int32 = 0xc
- static let IDR: Int32 = 0x10
- static let ODR: Int32 = 0x14
- static let BSRR: Int32 = 0x18
- static let LCKR: Int32 = 0x1c
- static let AFRL: Int32 = 0x20
- static let AFRH: Int32 = 0x24
- static let BRR: Int32 = 0x28
- }
-
- private func ld(_ offset: Int32) -> UInt32 {
- UnsafeMutablePointer(bitPattern: UInt(bitPattern: UnsafeMutableRawPointer(baseAddress).advanced(by: Int(offset))))!.volatileLoad()
- }
-
- private func st(_ offset: Int32, _ value: UInt32) {
- UnsafeMutablePointer(bitPattern: UInt(bitPattern: UnsafeMutableRawPointer(baseAddress).advanced(by: Int(offset))))!.volatileStore(value)
- }
-
- /// GPIO port mode register
- var moder: MODER {
- get { MODER(rawValue: ld(Offsets.MODER)) }
- set { st(Offsets.MODER, newValue.rawValue) }
- }
- /// GPIO port output type register
- var otyper: OTYPER {
- get { OTYPER(rawValue: ld(Offsets.OTYPER)) }
- set { st(Offsets.OTYPER, newValue.rawValue) }
- }
- /// GPIO port output speed register
- var ospeedr: OSPEEDR {
- get { OSPEEDR(rawValue: ld(Offsets.OSPEEDR)) }
- set { st(Offsets.OSPEEDR, newValue.rawValue) }
- }
- /// GPIO port pull-up/pull-down register
- var pupdr: PUPDR {
- get { PUPDR(rawValue: ld(Offsets.PUPDR)) }
- set { st(Offsets.PUPDR, newValue.rawValue) }
- }
- /// GPIO port input data register
- var idr: IDR {
- get { IDR(rawValue: ld(Offsets.IDR)) }
- set { st(Offsets.IDR, newValue.rawValue) }
- }
- /// GPIO port output data register
- var odr: ODR {
- get { ODR(rawValue: ld(Offsets.ODR)) }
- set { st(Offsets.ODR, newValue.rawValue) }
- }
- /// GPIO port bit set/reset register
- var bsrr: BSRR {
- get { BSRR(rawValue: ld(Offsets.BSRR)) }
- set { st(Offsets.BSRR, newValue.rawValue) }
- }
- /// GPIO port configuration lock register
- var lckr: LCKR {
- get { LCKR(rawValue: ld(Offsets.LCKR)) }
- set { st(Offsets.LCKR, newValue.rawValue) }
- }
- /// GPIO alternate function lowregister
- var afrl: AFRL {
- get { AFRL(rawValue: ld(Offsets.AFRL)) }
- set { st(Offsets.AFRL, newValue.rawValue) }
- }
- /// GPIO alternate function high register
- var afrh: AFRH {
- get { AFRH(rawValue: ld(Offsets.AFRH)) }
- set { st(Offsets.AFRH, newValue.rawValue) }
- }
- /// GPIO port bit reset register
- var brr: BRR {
- get { BRR(rawValue: ld(Offsets.BRR)) }
- set { st(Offsets.BRR, newValue.rawValue) }
- }
-}
-
-extension GPIO {
- struct MODER {
- var rawValue: UInt32
-
- static let moder15_offset = UInt32(30)
- static let moder15_mask = UInt32(0b11) &<< moder15_offset
- var moder15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder15_mask)) >> GPIO.MODER.moder15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder15_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder15_offset) & GPIO.MODER.moder15_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder14_offset = UInt32(28)
- static let moder14_mask = UInt32(0b11) &<< moder14_offset
- var moder14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder14_mask)) >> GPIO.MODER.moder14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder14_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder14_offset) & GPIO.MODER.moder14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder13_offset = UInt32(26)
- static let moder13_mask = UInt32(0b11) &<< moder13_offset
- var moder13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder13_mask)) >> GPIO.MODER.moder13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder13_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder13_offset) & GPIO.MODER.moder13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder12_offset = UInt32(24)
- static let moder12_mask = UInt32(0b11) &<< moder12_offset
- var moder12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder12_mask)) >> GPIO.MODER.moder12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder12_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder12_offset) & GPIO.MODER.moder12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder11_offset = UInt32(22)
- static let moder11_mask = UInt32(0b11) &<< moder11_offset
- var moder11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder11_mask)) >> GPIO.MODER.moder11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder11_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder11_offset) & GPIO.MODER.moder11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder10_offset = UInt32(20)
- static let moder10_mask = UInt32(0b11) &<< moder10_offset
- var moder10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder10_mask)) >> GPIO.MODER.moder10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder10_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder10_offset) & GPIO.MODER.moder10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder9_offset = UInt32(18)
- static let moder9_mask = UInt32(0b11) &<< moder9_offset
- var moder9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder9_mask)) >> GPIO.MODER.moder9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder9_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder9_offset) & GPIO.MODER.moder9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder8_offset = UInt32(16)
- static let moder8_mask = UInt32(0b11) &<< moder8_offset
- var moder8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder8_mask)) >> GPIO.MODER.moder8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder8_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder8_offset) & GPIO.MODER.moder8_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder7_offset = UInt32(14)
- static let moder7_mask = UInt32(0b11) &<< moder7_offset
- var moder7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder7_mask)) >> GPIO.MODER.moder7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder7_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder7_offset) & GPIO.MODER.moder7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder6_offset = UInt32(12)
- static let moder6_mask = UInt32(0b11) &<< moder6_offset
- var moder6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder6_mask)) >> GPIO.MODER.moder6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder6_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder6_offset) & GPIO.MODER.moder6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder5_offset = UInt32(10)
- static let moder5_mask = UInt32(0b11) &<< moder5_offset
- var moder5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder5_mask)) >> GPIO.MODER.moder5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder5_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder5_offset) & GPIO.MODER.moder5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder4_offset = UInt32(8)
- static let moder4_mask = UInt32(0b11) &<< moder4_offset
- var moder4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder4_mask)) >> GPIO.MODER.moder4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder4_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder4_offset) & GPIO.MODER.moder4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder3_offset = UInt32(6)
- static let moder3_mask = UInt32(0b11) &<< moder3_offset
- var moder3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder3_mask)) >> GPIO.MODER.moder3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder3_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder3_offset) & GPIO.MODER.moder3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder2_offset = UInt32(4)
- static let moder2_mask = UInt32(0b11) &<< moder2_offset
- var moder2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder2_mask)) >> GPIO.MODER.moder2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder2_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder2_offset) & GPIO.MODER.moder2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder1_offset = UInt32(2)
- static let moder1_mask = UInt32(0b11) &<< moder1_offset
- var moder1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder1_mask)) >> GPIO.MODER.moder1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder1_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder1_offset) & GPIO.MODER.moder1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let moder0_offset = UInt32(0)
- static let moder0_mask = UInt32(0b11) &<< moder0_offset
- var moder0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.MODER.moder0_mask)) >> GPIO.MODER.moder0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.MODER.moder0_mask
- let shift = (UInt32(newValue) << GPIO.MODER.moder0_offset) & GPIO.MODER.moder0_mask
- self.rawValue = preserve | shift
- }
- }
-
- func moder(n: Int) -> UInt8 {
- precondition(n >= 0 && n < 16)
- let moder_offset = n * 2
- let moder_mask = UInt32(0b11) &<< moder_offset
- return UInt8((self.rawValue & (moder_mask)) &>> moder_offset)
- }
-
- mutating func setModer(n: Int, value: UInt8) {
- precondition(n >= 0 && n < 16)
- precondition(value < 4)
- let moder_offset = n * 2
- let moder_mask = UInt32(0b11) &<< moder_offset
- let preserve = self.rawValue & ~moder_mask
- let shift = (UInt32(value) << moder_offset) & moder_mask
- self.rawValue = preserve | shift
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct OTYPER {
- var rawValue: UInt32
-
- static let ot15_offset = UInt32(15)
- static let ot15_mask = UInt32(0b1) &<< ot15_offset
- var ot15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot15_mask)) >> GPIO.OTYPER.ot15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot15_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot15_offset) & GPIO.OTYPER.ot15_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot14_offset = UInt32(14)
- static let ot14_mask = UInt32(0b1) &<< ot14_offset
- var ot14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot14_mask)) >> GPIO.OTYPER.ot14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot14_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot14_offset) & GPIO.OTYPER.ot14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot13_offset = UInt32(13)
- static let ot13_mask = UInt32(0b1) &<< ot13_offset
- var ot13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot13_mask)) >> GPIO.OTYPER.ot13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot13_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot13_offset) & GPIO.OTYPER.ot13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot12_offset = UInt32(12)
- static let ot12_mask = UInt32(0b1) &<< ot12_offset
- var ot12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot12_mask)) >> GPIO.OTYPER.ot12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot12_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot12_offset) & GPIO.OTYPER.ot12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot11_offset = UInt32(11)
- static let ot11_mask = UInt32(0b1) &<< ot11_offset
- var ot11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot11_mask)) >> GPIO.OTYPER.ot11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot11_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot11_offset) & GPIO.OTYPER.ot11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot10_offset = UInt32(10)
- static let ot10_mask = UInt32(0b1) &<< ot10_offset
- var ot10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot10_mask)) >> GPIO.OTYPER.ot10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot10_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot10_offset) & GPIO.OTYPER.ot10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot9_offset = UInt32(9)
- static let ot9_mask = UInt32(0b1) &<< ot9_offset
- var ot9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot9_mask)) >> GPIO.OTYPER.ot9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot9_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot9_offset) & GPIO.OTYPER.ot9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot8_offset = UInt32(8)
- static let ot8_mask = UInt32(0b1) &<< ot8_offset
- var ot8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot8_mask)) >> GPIO.OTYPER.ot8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot8_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot8_offset) & GPIO.OTYPER.ot8_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot7_offset = UInt32(7)
- static let ot7_mask = UInt32(0b1) &<< ot7_offset
- var ot7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot7_mask)) >> GPIO.OTYPER.ot7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot7_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot7_offset) & GPIO.OTYPER.ot7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot6_offset = UInt32(6)
- static let ot6_mask = UInt32(0b1) &<< ot6_offset
- var ot6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot6_mask)) >> GPIO.OTYPER.ot6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot6_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot6_offset) & GPIO.OTYPER.ot6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot5_offset = UInt32(5)
- static let ot5_mask = UInt32(0b1) &<< ot5_offset
- var ot5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot5_mask)) >> GPIO.OTYPER.ot5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot5_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot5_offset) & GPIO.OTYPER.ot5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot4_offset = UInt32(4)
- static let ot4_mask = UInt32(0b1) &<< ot4_offset
- var ot4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot4_mask)) >> GPIO.OTYPER.ot4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot4_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot4_offset) & GPIO.OTYPER.ot4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot3_offset = UInt32(3)
- static let ot3_mask = UInt32(0b1) &<< ot3_offset
- var ot3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot3_mask)) >> GPIO.OTYPER.ot3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot3_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot3_offset) & GPIO.OTYPER.ot3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot2_offset = UInt32(2)
- static let ot2_mask = UInt32(0b1) &<< ot2_offset
- var ot2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot2_mask)) >> GPIO.OTYPER.ot2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot2_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot2_offset) & GPIO.OTYPER.ot2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot1_offset = UInt32(1)
- static let ot1_mask = UInt32(0b1) &<< ot1_offset
- var ot1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot1_mask)) >> GPIO.OTYPER.ot1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot1_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot1_offset) & GPIO.OTYPER.ot1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ot0_offset = UInt32(0)
- static let ot0_mask = UInt32(0b1) &<< ot0_offset
- var ot0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OTYPER.ot0_mask)) >> GPIO.OTYPER.ot0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OTYPER.ot0_mask
- let shift = (UInt32(newValue) << GPIO.OTYPER.ot0_offset) & GPIO.OTYPER.ot0_mask
- self.rawValue = preserve | shift
- }
- }
-
- func ot(n: Int) -> UInt8 {
- precondition(n >= 0 && n < 16)
- let ot_offset = n * 1
- let ot_mask = UInt32(0b1) &<< ot_offset
- return UInt8((self.rawValue & (ot_mask)) &>> ot_offset)
- }
-
- mutating func setOt(n: Int, value: UInt8) {
- precondition(n >= 0 && n < 16)
- precondition(value < 2)
- let ot_offset = n * 1
- let ot_mask = UInt32(0b1) &<< ot_offset
- let preserve = self.rawValue & ~ot_mask
- let shift = (UInt32(value) << ot_offset) & ot_mask
- self.rawValue = preserve | shift
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct OSPEEDR {
- var rawValue: UInt32
-
- static let ospeedr15_offset = UInt32(30)
- static let ospeedr15_mask = UInt32(0b11) &<< ospeedr15_offset
- var ospeedr15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr15_mask)) >> GPIO.OSPEEDR.ospeedr15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr15_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr15_offset) & GPIO.OSPEEDR.ospeedr15_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr14_offset = UInt32(28)
- static let ospeedr14_mask = UInt32(0b11) &<< ospeedr14_offset
- var ospeedr14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr14_mask)) >> GPIO.OSPEEDR.ospeedr14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr14_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr14_offset) & GPIO.OSPEEDR.ospeedr14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr13_offset = UInt32(26)
- static let ospeedr13_mask = UInt32(0b11) &<< ospeedr13_offset
- var ospeedr13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr13_mask)) >> GPIO.OSPEEDR.ospeedr13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr13_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr13_offset) & GPIO.OSPEEDR.ospeedr13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr12_offset = UInt32(24)
- static let ospeedr12_mask = UInt32(0b11) &<< ospeedr12_offset
- var ospeedr12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr12_mask)) >> GPIO.OSPEEDR.ospeedr12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr12_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr12_offset) & GPIO.OSPEEDR.ospeedr12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr11_offset = UInt32(22)
- static let ospeedr11_mask = UInt32(0b11) &<< ospeedr11_offset
- var ospeedr11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr11_mask)) >> GPIO.OSPEEDR.ospeedr11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr11_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr11_offset) & GPIO.OSPEEDR.ospeedr11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr10_offset = UInt32(20)
- static let ospeedr10_mask = UInt32(0b11) &<< ospeedr10_offset
- var ospeedr10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr10_mask)) >> GPIO.OSPEEDR.ospeedr10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr10_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr10_offset) & GPIO.OSPEEDR.ospeedr10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr9_offset = UInt32(18)
- static let ospeedr9_mask = UInt32(0b11) &<< ospeedr9_offset
- var ospeedr9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr9_mask)) >> GPIO.OSPEEDR.ospeedr9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr9_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr9_offset) & GPIO.OSPEEDR.ospeedr9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr8_offset = UInt32(16)
- static let ospeedr8_mask = UInt32(0b11) &<< ospeedr8_offset
- var ospeedr8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr8_mask)) >> GPIO.OSPEEDR.ospeedr8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr8_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr8_offset) & GPIO.OSPEEDR.ospeedr8_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr7_offset = UInt32(14)
- static let ospeedr7_mask = UInt32(0b11) &<< ospeedr7_offset
- var ospeedr7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr7_mask)) >> GPIO.OSPEEDR.ospeedr7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr7_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr7_offset) & GPIO.OSPEEDR.ospeedr7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr6_offset = UInt32(12)
- static let ospeedr6_mask = UInt32(0b11) &<< ospeedr6_offset
- var ospeedr6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr6_mask)) >> GPIO.OSPEEDR.ospeedr6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr6_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr6_offset) & GPIO.OSPEEDR.ospeedr6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr5_offset = UInt32(10)
- static let ospeedr5_mask = UInt32(0b11) &<< ospeedr5_offset
- var ospeedr5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr5_mask)) >> GPIO.OSPEEDR.ospeedr5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr5_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr5_offset) & GPIO.OSPEEDR.ospeedr5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr4_offset = UInt32(8)
- static let ospeedr4_mask = UInt32(0b11) &<< ospeedr4_offset
- var ospeedr4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr4_mask)) >> GPIO.OSPEEDR.ospeedr4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr4_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr4_offset) & GPIO.OSPEEDR.ospeedr4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr3_offset = UInt32(6)
- static let ospeedr3_mask = UInt32(0b11) &<< ospeedr3_offset
- var ospeedr3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr3_mask)) >> GPIO.OSPEEDR.ospeedr3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr3_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr3_offset) & GPIO.OSPEEDR.ospeedr3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr2_offset = UInt32(4)
- static let ospeedr2_mask = UInt32(0b11) &<< ospeedr2_offset
- var ospeedr2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr2_mask)) >> GPIO.OSPEEDR.ospeedr2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr2_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr2_offset) & GPIO.OSPEEDR.ospeedr2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr1_offset = UInt32(2)
- static let ospeedr1_mask = UInt32(0b11) &<< ospeedr1_offset
- var ospeedr1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr1_mask)) >> GPIO.OSPEEDR.ospeedr1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr1_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr1_offset) & GPIO.OSPEEDR.ospeedr1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let ospeedr0_offset = UInt32(0)
- static let ospeedr0_mask = UInt32(0b11) &<< ospeedr0_offset
- var ospeedr0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.OSPEEDR.ospeedr0_mask)) >> GPIO.OSPEEDR.ospeedr0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.OSPEEDR.ospeedr0_mask
- let shift = (UInt32(newValue) << GPIO.OSPEEDR.ospeedr0_offset) & GPIO.OSPEEDR.ospeedr0_mask
- self.rawValue = preserve | shift
- }
- }
-
- func ospeed(n: Int) -> UInt8 {
- precondition(n >= 0 && n < 16)
- let ospeed_offset = n * 2
- let ospeed_mask = UInt32(0b11) &<< ospeed_offset
- return UInt8((self.rawValue & (ospeed_mask)) &>> ospeed_offset)
- }
-
- mutating func setOspeed(n: Int, value: UInt8) {
- precondition(n >= 0 && n < 16)
- precondition(value < 4)
- let ospeed_offset = n * 2
- let ospeed_mask = UInt32(0b11) &<< ospeed_offset
- let preserve = self.rawValue & ~ospeed_mask
- let shift = (UInt32(value) << ospeed_offset) & ospeed_mask
- self.rawValue = preserve | shift
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct PUPDR {
- var rawValue: UInt32
-
- static let pupdr15_offset = UInt32(30)
- static let pupdr15_mask = UInt32(0b11) &<< pupdr15_offset
- var pupdr15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr15_mask)) >> GPIO.PUPDR.pupdr15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr15_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr15_offset) & GPIO.PUPDR.pupdr15_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr14_offset = UInt32(28)
- static let pupdr14_mask = UInt32(0b11) &<< pupdr14_offset
- var pupdr14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr14_mask)) >> GPIO.PUPDR.pupdr14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr14_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr14_offset) & GPIO.PUPDR.pupdr14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr13_offset = UInt32(26)
- static let pupdr13_mask = UInt32(0b11) &<< pupdr13_offset
- var pupdr13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr13_mask)) >> GPIO.PUPDR.pupdr13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr13_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr13_offset) & GPIO.PUPDR.pupdr13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr12_offset = UInt32(24)
- static let pupdr12_mask = UInt32(0b11) &<< pupdr12_offset
- var pupdr12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr12_mask)) >> GPIO.PUPDR.pupdr12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr12_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr12_offset) & GPIO.PUPDR.pupdr12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr11_offset = UInt32(22)
- static let pupdr11_mask = UInt32(0b11) &<< pupdr11_offset
- var pupdr11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr11_mask)) >> GPIO.PUPDR.pupdr11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr11_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr11_offset) & GPIO.PUPDR.pupdr11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr10_offset = UInt32(20)
- static let pupdr10_mask = UInt32(0b11) &<< pupdr10_offset
- var pupdr10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr10_mask)) >> GPIO.PUPDR.pupdr10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr10_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr10_offset) & GPIO.PUPDR.pupdr10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr9_offset = UInt32(18)
- static let pupdr9_mask = UInt32(0b11) &<< pupdr9_offset
- var pupdr9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr9_mask)) >> GPIO.PUPDR.pupdr9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr9_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr9_offset) & GPIO.PUPDR.pupdr9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr8_offset = UInt32(16)
- static let pupdr8_mask = UInt32(0b11) &<< pupdr8_offset
- var pupdr8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr8_mask)) >> GPIO.PUPDR.pupdr8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr8_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr8_offset) & GPIO.PUPDR.pupdr8_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr7_offset = UInt32(14)
- static let pupdr7_mask = UInt32(0b11) &<< pupdr7_offset
- var pupdr7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr7_mask)) >> GPIO.PUPDR.pupdr7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr7_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr7_offset) & GPIO.PUPDR.pupdr7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr6_offset = UInt32(12)
- static let pupdr6_mask = UInt32(0b11) &<< pupdr6_offset
- var pupdr6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr6_mask)) >> GPIO.PUPDR.pupdr6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr6_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr6_offset) & GPIO.PUPDR.pupdr6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr5_offset = UInt32(10)
- static let pupdr5_mask = UInt32(0b11) &<< pupdr5_offset
- var pupdr5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr5_mask)) >> GPIO.PUPDR.pupdr5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr5_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr5_offset) & GPIO.PUPDR.pupdr5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr4_offset = UInt32(8)
- static let pupdr4_mask = UInt32(0b11) &<< pupdr4_offset
- var pupdr4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr4_mask)) >> GPIO.PUPDR.pupdr4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr4_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr4_offset) & GPIO.PUPDR.pupdr4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr3_offset = UInt32(6)
- static let pupdr3_mask = UInt32(0b11) &<< pupdr3_offset
- var pupdr3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr3_mask)) >> GPIO.PUPDR.pupdr3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr3_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr3_offset) & GPIO.PUPDR.pupdr3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr2_offset = UInt32(4)
- static let pupdr2_mask = UInt32(0b11) &<< pupdr2_offset
- var pupdr2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr2_mask)) >> GPIO.PUPDR.pupdr2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr2_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr2_offset) & GPIO.PUPDR.pupdr2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr1_offset = UInt32(2)
- static let pupdr1_mask = UInt32(0b11) &<< pupdr1_offset
- var pupdr1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr1_mask)) >> GPIO.PUPDR.pupdr1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr1_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr1_offset) & GPIO.PUPDR.pupdr1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let pupdr0_offset = UInt32(0)
- static let pupdr0_mask = UInt32(0b11) &<< pupdr0_offset
- var pupdr0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.PUPDR.pupdr0_mask)) >> GPIO.PUPDR.pupdr0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.PUPDR.pupdr0_mask
- let shift = (UInt32(newValue) << GPIO.PUPDR.pupdr0_offset) & GPIO.PUPDR.pupdr0_mask
- self.rawValue = preserve | shift
- }
- }
-
- func pupd(n: Int) -> UInt8 {
- precondition(n >= 0 && n < 16)
- let pupd_offset = n * 2
- let pupd_mask = UInt32(0b11) &<< pupd_offset
- return UInt8((self.rawValue & (pupd_mask)) &>> pupd_offset)
- }
-
- mutating func setPupd(n: Int, value: UInt8) {
- precondition(n >= 0 && n < 16)
- precondition(value < 4)
- let pupd_offset = n * 2
- let pupd_mask = UInt32(0b11) &<< pupd_offset
- let preserve = self.rawValue & ~pupd_mask
- let shift = (UInt32(value) << pupd_offset) & pupd_mask
- self.rawValue = preserve | shift
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct IDR {
- var rawValue: UInt32
-
- static let idr15_offset = UInt32(15)
- static let idr15_mask = UInt32(0b1) &<< idr15_offset
- var idr15: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr15_mask)) >> GPIO.IDR.idr15_offset)
- }
-
- static let idr14_offset = UInt32(14)
- static let idr14_mask = UInt32(0b1) &<< idr14_offset
- var idr14: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr14_mask)) >> GPIO.IDR.idr14_offset)
- }
-
- static let idr13_offset = UInt32(13)
- static let idr13_mask = UInt32(0b1) &<< idr13_offset
- var idr13: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr13_mask)) >> GPIO.IDR.idr13_offset)
- }
-
- static let idr12_offset = UInt32(12)
- static let idr12_mask = UInt32(0b1) &<< idr12_offset
- var idr12: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr12_mask)) >> GPIO.IDR.idr12_offset)
- }
-
- static let idr11_offset = UInt32(11)
- static let idr11_mask = UInt32(0b1) &<< idr11_offset
- var idr11: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr11_mask)) >> GPIO.IDR.idr11_offset)
- }
-
- static let idr10_offset = UInt32(10)
- static let idr10_mask = UInt32(0b1) &<< idr10_offset
- var idr10: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr10_mask)) >> GPIO.IDR.idr10_offset)
- }
-
- static let idr9_offset = UInt32(9)
- static let idr9_mask = UInt32(0b1) &<< idr9_offset
- var idr9: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr9_mask)) >> GPIO.IDR.idr9_offset)
- }
-
- static let idr8_offset = UInt32(8)
- static let idr8_mask = UInt32(0b1) &<< idr8_offset
- var idr8: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr8_mask)) >> GPIO.IDR.idr8_offset)
- }
-
- static let idr7_offset = UInt32(7)
- static let idr7_mask = UInt32(0b1) &<< idr7_offset
- var idr7: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr7_mask)) >> GPIO.IDR.idr7_offset)
- }
-
- static let idr6_offset = UInt32(6)
- static let idr6_mask = UInt32(0b1) &<< idr6_offset
- var idr6: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr6_mask)) >> GPIO.IDR.idr6_offset)
- }
-
- static let idr5_offset = UInt32(5)
- static let idr5_mask = UInt32(0b1) &<< idr5_offset
- var idr5: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr5_mask)) >> GPIO.IDR.idr5_offset)
- }
-
- static let idr4_offset = UInt32(4)
- static let idr4_mask = UInt32(0b1) &<< idr4_offset
- var idr4: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr4_mask)) >> GPIO.IDR.idr4_offset)
- }
-
- static let idr3_offset = UInt32(3)
- static let idr3_mask = UInt32(0b1) &<< idr3_offset
- var idr3: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr3_mask)) >> GPIO.IDR.idr3_offset)
- }
-
- static let idr2_offset = UInt32(2)
- static let idr2_mask = UInt32(0b1) &<< idr2_offset
- var idr2: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr2_mask)) >> GPIO.IDR.idr2_offset)
- }
-
- static let idr1_offset = UInt32(1)
- static let idr1_mask = UInt32(0b1) &<< idr1_offset
- var idr1: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr1_mask)) >> GPIO.IDR.idr1_offset)
- }
-
- static let idr0_offset = UInt32(0)
- static let idr0_mask = UInt32(0b1) &<< idr0_offset
- var idr0: UInt8 {
- UInt8((self.rawValue & (GPIO.IDR.idr0_mask)) >> GPIO.IDR.idr0_offset)
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct ODR {
- var rawValue: UInt32
-
- static let odr15_offset = UInt32(15)
- static let odr15_mask = UInt32(0b1) &<< odr15_offset
- var odr15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr15_mask)) >> GPIO.ODR.odr15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr15_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr15_offset) & GPIO.ODR.odr15_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr14_offset = UInt32(14)
- static let odr14_mask = UInt32(0b1) &<< odr14_offset
- var odr14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr14_mask)) >> GPIO.ODR.odr14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr14_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr14_offset) & GPIO.ODR.odr14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr13_offset = UInt32(13)
- static let odr13_mask = UInt32(0b1) &<< odr13_offset
- var odr13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr13_mask)) >> GPIO.ODR.odr13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr13_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr13_offset) & GPIO.ODR.odr13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr12_offset = UInt32(12)
- static let odr12_mask = UInt32(0b1) &<< odr12_offset
- var odr12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr12_mask)) >> GPIO.ODR.odr12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr12_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr12_offset) & GPIO.ODR.odr12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr11_offset = UInt32(11)
- static let odr11_mask = UInt32(0b1) &<< odr11_offset
- var odr11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr11_mask)) >> GPIO.ODR.odr11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr11_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr11_offset) & GPIO.ODR.odr11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr10_offset = UInt32(10)
- static let odr10_mask = UInt32(0b1) &<< odr10_offset
- var odr10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr10_mask)) >> GPIO.ODR.odr10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr10_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr10_offset) & GPIO.ODR.odr10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr9_offset = UInt32(9)
- static let odr9_mask = UInt32(0b1) &<< odr9_offset
- var odr9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr9_mask)) >> GPIO.ODR.odr9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr9_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr9_offset) & GPIO.ODR.odr9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr8_offset = UInt32(8)
- static let odr8_mask = UInt32(0b1) &<< odr8_offset
- var odr8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr8_mask)) >> GPIO.ODR.odr8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr8_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr8_offset) & GPIO.ODR.odr8_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr7_offset = UInt32(7)
- static let odr7_mask = UInt32(0b1) &<< odr7_offset
- var odr7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr7_mask)) >> GPIO.ODR.odr7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr7_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr7_offset) & GPIO.ODR.odr7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr6_offset = UInt32(6)
- static let odr6_mask = UInt32(0b1) &<< odr6_offset
- var odr6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr6_mask)) >> GPIO.ODR.odr6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr6_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr6_offset) & GPIO.ODR.odr6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr5_offset = UInt32(5)
- static let odr5_mask = UInt32(0b1) &<< odr5_offset
- var odr5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr5_mask)) >> GPIO.ODR.odr5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr5_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr5_offset) & GPIO.ODR.odr5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr4_offset = UInt32(4)
- static let odr4_mask = UInt32(0b1) &<< odr4_offset
- var odr4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr4_mask)) >> GPIO.ODR.odr4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr4_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr4_offset) & GPIO.ODR.odr4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr3_offset = UInt32(3)
- static let odr3_mask = UInt32(0b1) &<< odr3_offset
- var odr3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr3_mask)) >> GPIO.ODR.odr3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr3_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr3_offset) & GPIO.ODR.odr3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr2_offset = UInt32(2)
- static let odr2_mask = UInt32(0b1) &<< odr2_offset
- var odr2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr2_mask)) >> GPIO.ODR.odr2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr2_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr2_offset) & GPIO.ODR.odr2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr1_offset = UInt32(1)
- static let odr1_mask = UInt32(0b1) &<< odr1_offset
- var odr1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr1_mask)) >> GPIO.ODR.odr1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr1_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr1_offset) & GPIO.ODR.odr1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let odr0_offset = UInt32(0)
- static let odr0_mask = UInt32(0b1) &<< odr0_offset
- var odr0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.ODR.odr0_mask)) >> GPIO.ODR.odr0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.ODR.odr0_mask
- let shift = (UInt32(newValue) << GPIO.ODR.odr0_offset) & GPIO.ODR.odr0_mask
- self.rawValue = preserve | shift
- }
- }
-
- func od(n: Int) -> UInt8 {
- precondition(n >= 0 && n < 16)
- let od_offset = n * 1
- let od_mask = UInt32(0b1) &<< od_offset
- return UInt8((self.rawValue & (od_mask)) &>> od_offset)
- }
-
- mutating func setOd(n: Int, value: UInt8) {
- precondition(n >= 0 && n < 16)
- precondition(value < 2)
- let od_offset = n * 1
- let od_mask = UInt32(0b1) &<< od_offset
- let preserve = self.rawValue & ~od_mask
- let shift = (UInt32(value) << od_offset) & od_mask
- self.rawValue = preserve | shift
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct BSRR {
- var rawValue: UInt32
-
- static let br15_offset = UInt32(31)
- static let br15_mask = UInt32(0b1) &<< br15_offset
- var br15: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br15_offset) & GPIO.BSRR.br15_mask
- }
- }
-
- static let br14_offset = UInt32(30)
- static let br14_mask = UInt32(0b1) &<< br14_offset
- var br14: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br14_offset) & GPIO.BSRR.br14_mask
- }
- }
-
- static let br13_offset = UInt32(29)
- static let br13_mask = UInt32(0b1) &<< br13_offset
- var br13: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br13_offset) & GPIO.BSRR.br13_mask
- }
- }
-
- static let br12_offset = UInt32(28)
- static let br12_mask = UInt32(0b1) &<< br12_offset
- var br12: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br12_offset) & GPIO.BSRR.br12_mask
- }
- }
-
- static let br11_offset = UInt32(27)
- static let br11_mask = UInt32(0b1) &<< br11_offset
- var br11: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br11_offset) & GPIO.BSRR.br11_mask
- }
- }
-
- static let br10_offset = UInt32(26)
- static let br10_mask = UInt32(0b1) &<< br10_offset
- var br10: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br10_offset) & GPIO.BSRR.br10_mask
- }
- }
-
- static let br9_offset = UInt32(25)
- static let br9_mask = UInt32(0b1) &<< br9_offset
- var br9: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br9_offset) & GPIO.BSRR.br9_mask
- }
- }
-
- static let br8_offset = UInt32(24)
- static let br8_mask = UInt32(0b1) &<< br8_offset
- var br8: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br8_offset) & GPIO.BSRR.br8_mask
- }
- }
-
- static let br7_offset = UInt32(23)
- static let br7_mask = UInt32(0b1) &<< br7_offset
- var br7: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br7_offset) & GPIO.BSRR.br7_mask
- }
- }
-
- static let br6_offset = UInt32(22)
- static let br6_mask = UInt32(0b1) &<< br6_offset
- var br6: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br6_offset) & GPIO.BSRR.br6_mask
- }
- }
-
- static let br5_offset = UInt32(21)
- static let br5_mask = UInt32(0b1) &<< br5_offset
- var br5: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br5_offset) & GPIO.BSRR.br5_mask
- }
- }
-
- static let br4_offset = UInt32(20)
- static let br4_mask = UInt32(0b1) &<< br4_offset
- var br4: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br4_offset) & GPIO.BSRR.br4_mask
- }
- }
-
- static let br3_offset = UInt32(19)
- static let br3_mask = UInt32(0b1) &<< br3_offset
- var br3: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br3_offset) & GPIO.BSRR.br3_mask
- }
- }
-
- static let br2_offset = UInt32(18)
- static let br2_mask = UInt32(0b1) &<< br2_offset
- var br2: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br2_offset) & GPIO.BSRR.br2_mask
- }
- }
-
- static let br1_offset = UInt32(17)
- static let br1_mask = UInt32(0b1) &<< br1_offset
- var br1: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br1_offset) & GPIO.BSRR.br1_mask
- }
- }
-
- static let br0_offset = UInt32(16)
- static let br0_mask = UInt32(0b1) &<< br0_offset
- var br0: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.br0_offset) & GPIO.BSRR.br0_mask
- }
- }
-
- static let bs15_offset = UInt32(15)
- static let bs15_mask = UInt32(0b1) &<< bs15_offset
- var bs15: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs15_offset) & GPIO.BSRR.bs15_mask
- }
- }
-
- static let bs14_offset = UInt32(14)
- static let bs14_mask = UInt32(0b1) &<< bs14_offset
- var bs14: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs14_offset) & GPIO.BSRR.bs14_mask
- }
- }
-
- static let bs13_offset = UInt32(13)
- static let bs13_mask = UInt32(0b1) &<< bs13_offset
- var bs13: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs13_offset) & GPIO.BSRR.bs13_mask
- }
- }
-
- static let bs12_offset = UInt32(12)
- static let bs12_mask = UInt32(0b1) &<< bs12_offset
- var bs12: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs12_offset) & GPIO.BSRR.bs12_mask
- }
- }
-
- static let bs11_offset = UInt32(11)
- static let bs11_mask = UInt32(0b1) &<< bs11_offset
- var bs11: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs11_offset) & GPIO.BSRR.bs11_mask
- }
- }
-
- static let bs10_offset = UInt32(10)
- static let bs10_mask = UInt32(0b1) &<< bs10_offset
- var bs10: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs10_offset) & GPIO.BSRR.bs10_mask
- }
- }
-
- static let bs9_offset = UInt32(9)
- static let bs9_mask = UInt32(0b1) &<< bs9_offset
- var bs9: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs9_offset) & GPIO.BSRR.bs9_mask
- }
- }
-
- static let bs8_offset = UInt32(8)
- static let bs8_mask = UInt32(0b1) &<< bs8_offset
- var bs8: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs8_offset) & GPIO.BSRR.bs8_mask
- }
- }
-
- static let bs7_offset = UInt32(7)
- static let bs7_mask = UInt32(0b1) &<< bs7_offset
- var bs7: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs7_offset) & GPIO.BSRR.bs7_mask
- }
- }
-
- static let bs6_offset = UInt32(6)
- static let bs6_mask = UInt32(0b1) &<< bs6_offset
- var bs6: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs6_offset) & GPIO.BSRR.bs6_mask
- }
- }
-
- static let bs5_offset = UInt32(5)
- static let bs5_mask = UInt32(0b1) &<< bs5_offset
- var bs5: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs5_offset) & GPIO.BSRR.bs5_mask
- }
- }
-
- static let bs4_offset = UInt32(4)
- static let bs4_mask = UInt32(0b1) &<< bs4_offset
- var bs4: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs4_offset) & GPIO.BSRR.bs4_mask
- }
- }
-
- static let bs3_offset = UInt32(3)
- static let bs3_mask = UInt32(0b1) &<< bs3_offset
- var bs3: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs3_offset) & GPIO.BSRR.bs3_mask
- }
- }
-
- static let bs2_offset = UInt32(2)
- static let bs2_mask = UInt32(0b1) &<< bs2_offset
- var bs2: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs2_offset) & GPIO.BSRR.bs2_mask
- }
- }
-
- static let bs1_offset = UInt32(1)
- static let bs1_mask = UInt32(0b1) &<< bs1_offset
- var bs1: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs1_offset) & GPIO.BSRR.bs1_mask
- }
- }
-
- static let bs0_offset = UInt32(0)
- static let bs0_mask = UInt32(0b1) &<< bs0_offset
- var bs0: UInt8 {
- get { fatalError("Trying to read a write-only field") }
- set {
- self.rawValue = (UInt32(newValue) << GPIO.BSRR.bs0_offset) & GPIO.BSRR.bs0_mask
- }
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct LCKR {
- var rawValue: UInt32
-
- static let lckk_offset = UInt32(16)
- static let lckk_mask = UInt32(0b1) &<< lckk_offset
- var lckk: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lckk_mask)) >> GPIO.LCKR.lckk_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lckk_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lckk_offset) & GPIO.LCKR.lckk_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck15_offset = UInt32(15)
- static let lck15_mask = UInt32(0b1) &<< lck15_offset
- var lck15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck15_mask)) >> GPIO.LCKR.lck15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck15_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck15_offset) & GPIO.LCKR.lck15_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck14_offset = UInt32(14)
- static let lck14_mask = UInt32(0b1) &<< lck14_offset
- var lck14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck14_mask)) >> GPIO.LCKR.lck14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck14_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck14_offset) & GPIO.LCKR.lck14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck13_offset = UInt32(13)
- static let lck13_mask = UInt32(0b1) &<< lck13_offset
- var lck13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck13_mask)) >> GPIO.LCKR.lck13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck13_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck13_offset) & GPIO.LCKR.lck13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck12_offset = UInt32(12)
- static let lck12_mask = UInt32(0b1) &<< lck12_offset
- var lck12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck12_mask)) >> GPIO.LCKR.lck12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck12_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck12_offset) & GPIO.LCKR.lck12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck11_offset = UInt32(11)
- static let lck11_mask = UInt32(0b1) &<< lck11_offset
- var lck11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck11_mask)) >> GPIO.LCKR.lck11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck11_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck11_offset) & GPIO.LCKR.lck11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck10_offset = UInt32(10)
- static let lck10_mask = UInt32(0b1) &<< lck10_offset
- var lck10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck10_mask)) >> GPIO.LCKR.lck10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck10_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck10_offset) & GPIO.LCKR.lck10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck9_offset = UInt32(9)
- static let lck9_mask = UInt32(0b1) &<< lck9_offset
- var lck9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck9_mask)) >> GPIO.LCKR.lck9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck9_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck9_offset) & GPIO.LCKR.lck9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck8_offset = UInt32(8)
- static let lck8_mask = UInt32(0b1) &<< lck8_offset
- var lck8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck8_mask)) >> GPIO.LCKR.lck8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck8_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck8_offset) & GPIO.LCKR.lck8_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck7_offset = UInt32(7)
- static let lck7_mask = UInt32(0b1) &<< lck7_offset
- var lck7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck7_mask)) >> GPIO.LCKR.lck7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck7_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck7_offset) & GPIO.LCKR.lck7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck6_offset = UInt32(6)
- static let lck6_mask = UInt32(0b1) &<< lck6_offset
- var lck6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck6_mask)) >> GPIO.LCKR.lck6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck6_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck6_offset) & GPIO.LCKR.lck6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck5_offset = UInt32(5)
- static let lck5_mask = UInt32(0b1) &<< lck5_offset
- var lck5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck5_mask)) >> GPIO.LCKR.lck5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck5_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck5_offset) & GPIO.LCKR.lck5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck4_offset = UInt32(4)
- static let lck4_mask = UInt32(0b1) &<< lck4_offset
- var lck4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck4_mask)) >> GPIO.LCKR.lck4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck4_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck4_offset) & GPIO.LCKR.lck4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck3_offset = UInt32(3)
- static let lck3_mask = UInt32(0b1) &<< lck3_offset
- var lck3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck3_mask)) >> GPIO.LCKR.lck3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck3_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck3_offset) & GPIO.LCKR.lck3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck2_offset = UInt32(2)
- static let lck2_mask = UInt32(0b1) &<< lck2_offset
- var lck2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck2_mask)) >> GPIO.LCKR.lck2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck2_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck2_offset) & GPIO.LCKR.lck2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck1_offset = UInt32(1)
- static let lck1_mask = UInt32(0b1) &<< lck1_offset
- var lck1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck1_mask)) >> GPIO.LCKR.lck1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck1_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck1_offset) & GPIO.LCKR.lck1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let lck0_offset = UInt32(0)
- static let lck0_mask = UInt32(0b1) &<< lck0_offset
- var lck0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.LCKR.lck0_mask)) >> GPIO.LCKR.lck0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.LCKR.lck0_mask
- let shift = (UInt32(newValue) << GPIO.LCKR.lck0_offset) & GPIO.LCKR.lck0_mask
- self.rawValue = preserve | shift
- }
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct AFRL {
- var rawValue: UInt32
-
- static let afrl7_offset = UInt32(28)
- static let afrl7_mask = UInt32(0b1111) &<< afrl7_offset
- var afrl7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl7_mask)) >> GPIO.AFRL.afrl7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl7_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl7_offset) & GPIO.AFRL.afrl7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrl6_offset = UInt32(24)
- static let afrl6_mask = UInt32(0b1111) &<< afrl6_offset
- var afrl6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl6_mask)) >> GPIO.AFRL.afrl6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl6_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl6_offset) & GPIO.AFRL.afrl6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrl5_offset = UInt32(20)
- static let afrl5_mask = UInt32(0b1111) &<< afrl5_offset
- var afrl5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl5_mask)) >> GPIO.AFRL.afrl5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl5_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl5_offset) & GPIO.AFRL.afrl5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrl4_offset = UInt32(16)
- static let afrl4_mask = UInt32(0b1111) &<< afrl4_offset
- var afrl4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl4_mask)) >> GPIO.AFRL.afrl4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl4_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl4_offset) & GPIO.AFRL.afrl4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrl3_offset = UInt32(12)
- static let afrl3_mask = UInt32(0b1111) &<< afrl3_offset
- var afrl3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl3_mask)) >> GPIO.AFRL.afrl3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl3_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl3_offset) & GPIO.AFRL.afrl3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrl2_offset = UInt32(8)
- static let afrl2_mask = UInt32(0b1111) &<< afrl2_offset
- var afrl2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl2_mask)) >> GPIO.AFRL.afrl2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl2_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl2_offset) & GPIO.AFRL.afrl2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrl1_offset = UInt32(4)
- static let afrl1_mask = UInt32(0b1111) &<< afrl1_offset
- var afrl1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl1_mask)) >> GPIO.AFRL.afrl1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl1_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl1_offset) & GPIO.AFRL.afrl1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrl0_offset = UInt32(0)
- static let afrl0_mask = UInt32(0b1111) &<< afrl0_offset
- var afrl0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRL.afrl0_mask)) >> GPIO.AFRL.afrl0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRL.afrl0_mask
- let shift = (UInt32(newValue) << GPIO.AFRL.afrl0_offset) & GPIO.AFRL.afrl0_mask
- self.rawValue = preserve | shift
- }
- }
-
- func af(n: Int) -> UInt8 {
- precondition(n >= 0 && n < 8)
- let af_offset = n * 4
- let af_mask = UInt32(0b1111) &<< af_offset
- return UInt8((self.rawValue & (af_mask)) &>> af_offset)
- }
-
- mutating func setAf(n: Int, value: UInt8) {
- precondition(n >= 0 && n < 8)
- precondition(value < 16)
- let af_offset = n * 4
- let af_mask = UInt32(0b1111) &<< af_offset
- let preserve = self.rawValue & ~af_mask
- let shift = (UInt32(value) << af_offset) & af_mask
- self.rawValue = preserve | shift
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct AFRH {
- var rawValue: UInt32
-
- static let afrh15_offset = UInt32(28)
- static let afrh15_mask = UInt32(0b1111) &<< afrh15_offset
- var afrh15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh15_mask)) >> GPIO.AFRH.afrh15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh15_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh15_offset) & GPIO.AFRH.afrh15_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrh14_offset = UInt32(24)
- static let afrh14_mask = UInt32(0b1111) &<< afrh14_offset
- var afrh14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh14_mask)) >> GPIO.AFRH.afrh14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh14_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh14_offset) & GPIO.AFRH.afrh14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrh13_offset = UInt32(20)
- static let afrh13_mask = UInt32(0b1111) &<< afrh13_offset
- var afrh13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh13_mask)) >> GPIO.AFRH.afrh13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh13_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh13_offset) & GPIO.AFRH.afrh13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrh12_offset = UInt32(16)
- static let afrh12_mask = UInt32(0b1111) &<< afrh12_offset
- var afrh12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh12_mask)) >> GPIO.AFRH.afrh12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh12_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh12_offset) & GPIO.AFRH.afrh12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrh11_offset = UInt32(12)
- static let afrh11_mask = UInt32(0b1111) &<< afrh11_offset
- var afrh11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh11_mask)) >> GPIO.AFRH.afrh11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh11_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh11_offset) & GPIO.AFRH.afrh11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrh10_offset = UInt32(8)
- static let afrh10_mask = UInt32(0b1111) &<< afrh10_offset
- var afrh10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh10_mask)) >> GPIO.AFRH.afrh10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh10_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh10_offset) & GPIO.AFRH.afrh10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrh9_offset = UInt32(4)
- static let afrh9_mask = UInt32(0b1111) &<< afrh9_offset
- var afrh9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh9_mask)) >> GPIO.AFRH.afrh9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh9_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh9_offset) & GPIO.AFRH.afrh9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let afrh8_offset = UInt32(0)
- static let afrh8_mask = UInt32(0b1111) &<< afrh8_offset
- var afrh8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.AFRH.afrh8_mask)) >> GPIO.AFRH.afrh8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.AFRH.afrh8_mask
- let shift = (UInt32(newValue) << GPIO.AFRH.afrh8_offset) & GPIO.AFRH.afrh8_mask
- self.rawValue = preserve | shift
- }
- }
-
- func af(n: Int) -> UInt8 {
- precondition(n >= 8 && n < 16)
- let af_offset = (n - 8) * 4
- let af_mask = UInt32(0b1111) &<< af_offset
- return UInt8((self.rawValue & (af_mask)) &>> af_offset)
- }
-
- mutating func setAf(n: Int, value: UInt8) {
- precondition(n >= 8 && n < 16)
- precondition(value < 16)
- let af_offset = (n - 8) * 4
- let af_mask = UInt32(0b1111) &<< af_offset
- let preserve = self.rawValue & ~af_mask
- let shift = (UInt32(value) << af_offset) & af_mask
- self.rawValue = preserve | shift
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
- struct BRR {
- var rawValue: UInt32
-
- static let br0_offset = UInt32(0)
- static let br0_mask = UInt32(0b1) &<< br0_offset
- var br0: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br0_mask)) >> GPIO.BRR.br0_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br0_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br0_offset) & GPIO.BRR.br0_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br1_offset = UInt32(1)
- static let br1_mask = UInt32(0b1) &<< br1_offset
- var br1: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br1_mask)) >> GPIO.BRR.br1_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br1_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br1_offset) & GPIO.BRR.br1_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br2_offset = UInt32(2)
- static let br2_mask = UInt32(0b1) &<< br2_offset
- var br2: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br2_mask)) >> GPIO.BRR.br2_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br2_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br2_offset) & GPIO.BRR.br2_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br3_offset = UInt32(3)
- static let br3_mask = UInt32(0b1) &<< br3_offset
- var br3: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br3_mask)) >> GPIO.BRR.br3_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br3_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br3_offset) & GPIO.BRR.br3_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br4_offset = UInt32(4)
- static let br4_mask = UInt32(0b1) &<< br4_offset
- var br4: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br4_mask)) >> GPIO.BRR.br4_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br4_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br4_offset) & GPIO.BRR.br4_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br5_offset = UInt32(5)
- static let br5_mask = UInt32(0b1) &<< br5_offset
- var br5: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br5_mask)) >> GPIO.BRR.br5_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br5_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br5_offset) & GPIO.BRR.br5_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br6_offset = UInt32(6)
- static let br6_mask = UInt32(0b1) &<< br6_offset
- var br6: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br6_mask)) >> GPIO.BRR.br6_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br6_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br6_offset) & GPIO.BRR.br6_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br7_offset = UInt32(7)
- static let br7_mask = UInt32(0b1) &<< br7_offset
- var br7: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br7_mask)) >> GPIO.BRR.br7_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br7_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br7_offset) & GPIO.BRR.br7_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br8_offset = UInt32(8)
- static let br8_mask = UInt32(0b1) &<< br8_offset
- var br8: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br8_mask)) >> GPIO.BRR.br8_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br8_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br8_offset) & GPIO.BRR.br8_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br9_offset = UInt32(9)
- static let br9_mask = UInt32(0b1) &<< br9_offset
- var br9: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br9_mask)) >> GPIO.BRR.br9_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br9_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br9_offset) & GPIO.BRR.br9_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br10_offset = UInt32(10)
- static let br10_mask = UInt32(0b1) &<< br10_offset
- var br10: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br10_mask)) >> GPIO.BRR.br10_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br10_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br10_offset) & GPIO.BRR.br10_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br11_offset = UInt32(11)
- static let br11_mask = UInt32(0b1) &<< br11_offset
- var br11: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br11_mask)) >> GPIO.BRR.br11_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br11_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br11_offset) & GPIO.BRR.br11_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br12_offset = UInt32(12)
- static let br12_mask = UInt32(0b1) &<< br12_offset
- var br12: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br12_mask)) >> GPIO.BRR.br12_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br12_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br12_offset) & GPIO.BRR.br12_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br13_offset = UInt32(13)
- static let br13_mask = UInt32(0b1) &<< br13_offset
- var br13: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br13_mask)) >> GPIO.BRR.br13_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br13_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br13_offset) & GPIO.BRR.br13_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br14_offset = UInt32(14)
- static let br14_mask = UInt32(0b1) &<< br14_offset
- var br14: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br14_mask)) >> GPIO.BRR.br14_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br14_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br14_offset) & GPIO.BRR.br14_mask
- self.rawValue = preserve | shift
- }
- }
-
- static let br15_offset = UInt32(15)
- static let br15_mask = UInt32(0b1) &<< br15_offset
- var br15: UInt8 {
- get { UInt8((self.rawValue & (GPIO.BRR.br15_mask)) >> GPIO.BRR.br15_offset) }
- set {
- let preserve = self.rawValue & ~GPIO.BRR.br15_mask
- let shift = (UInt32(newValue) << GPIO.BRR.br15_offset) & GPIO.BRR.br15_mask
- self.rawValue = preserve | shift
- }
- }
-
- init(rawValue: UInt32) {
- self.rawValue = rawValue
- }
- }
-}
diff --git a/stm32-lcd-logo/Support/HAL.swift b/stm32-lcd-logo/Support/HAL.swift
deleted file mode 100644
index 0c89ddbf..00000000
--- a/stm32-lcd-logo/Support/HAL.swift
+++ /dev/null
@@ -1,687 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// This source file is part of the Swift open source project
-//
-// Copyright (c) 2023 Apple Inc. and the Swift project authors.
-// Licensed under Apache License v2.0 with Runtime Library Exception
-//
-// See https://swift.org/LICENSE.txt for license information
-//
-//===----------------------------------------------------------------------===//
-
-public protocol GPIOPlatform {
- associatedtype Pin
- static func configure(_ pin: Pin, _ configuration: GPIOConfiguration)
- static func assert(_ pin: Pin, _ configuration: GPIOConfiguration)
- static func deassert(_ pin: Pin, _ configuration: GPIOConfiguration)
- static func value(_ pin: Pin) -> Bool
-}
-public enum STM32F746 {}
-
-public enum Mode {
- case input
- case output
- case alternateFunction
- case analog
-}
-
-public enum OutputType {
- case pushPull
- case openDrain
-}
-
-public enum OutputSpeed {
- case low
- case medium
- case high
- case max
-}
-
-public enum Pull {
- case `none`
- case up
- case down
-}
-
-public enum AlternateFunction {
- case alternateFunction0
- case alternateFunction1
- case alternateFunction2
- case alternateFunction3
- case alternateFunction4
- case alternateFunction5
- case alternateFunction6
- case alternateFunction7
- case alternateFunction8
- case alternateFunction9
- case alternateFunction10
- case alternateFunction11
- case alternateFunction12
- case alternateFunction13
- case alternateFunction14
- case alternateFunction15
- case `none`
-}
-
-public struct GPIOConfiguration {
- public var mode: Mode
- public var outputType: OutputType
- public var outputSpeed: OutputSpeed
- public var pull: Pull
- public var alternateFunction: AlternateFunction
- public var activeHigh: Bool
-
- public init(
- mode: Mode, outputType: OutputType, outputSpeed: OutputSpeed, pull: Pull,
- alternateFunction: AlternateFunction, activeHigh: Bool
- ) {
- self.mode = mode
- self.outputType = outputType
- self.outputSpeed = outputSpeed
- self.pull = pull
- self.alternateFunction = alternateFunction
- self.activeHigh = activeHigh
- }
-}
-
-public struct HALGPIO {
- let pin: Platform.Pin
- var configuration: GPIOConfiguration?
-
- public init(pin: Platform.Pin) {
- self.pin = pin
- self.configuration = nil
- }
-
- public mutating func configure(configuration: GPIOConfiguration) {
- self.configuration = configuration
- guard let configuration = self.configuration else { return }
- Platform.configure(pin, configuration)
- }
-
- public func assert() {
- guard let configuration = self.configuration else { return }
- Platform.assert(pin, configuration)
- }
-
- public func deassert() {
- guard let configuration = self.configuration else { return }
- Platform.deassert(pin, configuration)
- }
-
- public func value() -> Bool {
- Platform.value(pin)
- }
-}
-
-// MARK: - Abstract GPIO -> Platform GPIO
-extension Mode {
- var rawValue: UInt8 {
- switch self {
- case .input: return 0x0
- case .output: return 0x1
- case .alternateFunction: return 0x2
- case .analog: return 0x3
- }
- }
-}
-
-extension OutputType {
- var rawValue: UInt8 {
- switch self {
- case .pushPull:
- return 0x0
- case .openDrain:
- return 0x1
- }
- }
-}
-
-extension OutputSpeed {
- var rawValue: UInt8 {
- switch self {
- case .low: return 0x0
- case .medium: return 0x1
- case .high: return 0x2
- case .max: return 0x3
- }
- }
-}
-
-extension Pull {
- var rawValue: UInt8 {
- switch self {
- case .none: return 0x0
- case .up: return 0x1
- case .down: return 0x2
- }
- }
-}
-
-extension AlternateFunction {
- var rawValue: UInt8 {
- switch self {
- case .alternateFunction0: return 0
- case .alternateFunction1: return 1
- case .alternateFunction2: return 2
- case .alternateFunction3: return 3
- case .alternateFunction4: return 4
- case .alternateFunction5: return 5
- case .alternateFunction6: return 6
- case .alternateFunction7: return 7
- case .alternateFunction8: return 8
- case .alternateFunction9: return 9
- case .alternateFunction10: return 10
- case .alternateFunction11: return 11
- case .alternateFunction12: return 12
- case .alternateFunction13: return 13
- case .alternateFunction14: return 14
- case .alternateFunction15: return 15
- case .none: return .max
- }
- }
-}
-
-// MARK: - GPIOPlatform Conformance
-extension STM32F746: GPIOPlatform {
- public struct Pin {
- var port: GPIOPort
- var number: UInt8
-
- public init(port: GPIOPort, number: UInt8) {
- self.port = port
- self.number = number
- }
-
- func checkValidPin() {
- if self.number < 0 || self.number > 16 {
- fatalError("STM32F746: invalid GPIO pin number")
- }
- }
-
- func setMode(_ mode: Mode) {
- var rawValue = self.port.port
- rawValue.moder.setModer(n: Int(self.number), value: mode.rawValue)
- }
-
- func setOutputType(_ outputType: OutputType) {
- var rawValue = self.port.port
- rawValue.otyper.setOt(n: Int(self.number), value: outputType.rawValue)
- }
-
- func setOutputSpeed(_ outputSpeed: OutputSpeed) {
- var rawValue = self.port.port
- rawValue.ospeedr.setOspeed(
- n: Int(self.number), value: outputSpeed.rawValue)
- }
-
- func setPull(_ pull: Pull) {
- var rawValue = self.port.port
- rawValue.pupdr.setPupd(n: Int(self.number), value: pull.rawValue)
- }
-
- func setAlternateFunction(_ alternateFunction: AlternateFunction) {
- var rawValue = self.port.port
- if self.number < 8 {
- rawValue.afrl.setAf(
- n: Int(self.number), value: alternateFunction.rawValue)
- } else {
- rawValue.afrh.setAf(
- n: Int(self.number), value: alternateFunction.rawValue)
- }
- }
-
- func setOutputData(_ data: UInt8) {
- var rawValue = self.port.port
- rawValue.odr.setOd(n: Int(self.number), value: data)
- }
-
- func getInputData() -> UInt8 {
- let rawValue = self.port.port
- switch self.number {
- case 0: return rawValue.idr.idr0
- case 1: return rawValue.idr.idr1
- case 2: return rawValue.idr.idr2
- case 3: return rawValue.idr.idr3
- case 4: return rawValue.idr.idr4
- case 5: return rawValue.idr.idr5
- case 6: return rawValue.idr.idr6
- case 7: return rawValue.idr.idr7
- case 8: return rawValue.idr.idr8
- case 9: return rawValue.idr.idr9
- case 10: return rawValue.idr.idr10
- case 11: return rawValue.idr.idr11
- case 12: return rawValue.idr.idr12
- case 13: return rawValue.idr.idr13
- case 14: return rawValue.idr.idr14
- case 15: return rawValue.idr.idr15
- default: fatalError("STM32F746: invalid GPIO pin number")
- }
- }
- }
-
- public static func configure(_ pin: Pin, _ configuration: GPIOConfiguration) {
- pin.checkValidPin()
-
- pin.setMode(configuration.mode)
- pin.setOutputType(configuration.outputType)
- pin.setOutputSpeed(configuration.outputSpeed)
- pin.setPull(configuration.pull)
-
- if configuration.mode == .alternateFunction {
- pin.setAlternateFunction(configuration.alternateFunction)
- }
-
- }
-
- public static func assert(_ pin: Pin, _ configuration: GPIOConfiguration) {
- if configuration.activeHigh {
- pin.setOutputData(1)
- } else {
- pin.setOutputData(0)
- }
- }
-
- public static func deassert(_ pin: Pin, _ configuration: GPIOConfiguration) {
- if configuration.activeHigh {
- pin.setOutputData(0)
- } else {
- pin.setOutputData(1)
- }
- }
-
- public static func value(_ pin: Pin) -> Bool {
- (pin.getInputData() & 0x1) != 0
- }
-}
-
-public enum GPIOPort: Int {
- case a, b, c, d, e, f, g, h, i, j, k
-
- var port: GPIO {
- // swift-format-ignore: NeverForceUnwrap
- GPIO(
- baseAddress: UnsafeMutableRawPointer(
- bitPattern: (0x4002_0000 + 0x400 * UInt(self.rawValue - Self.a.rawValue))
- )!)
- }
-}
-
-extension STM32F746 {
- public static func enableGPIOPortClock(_ port: GPIOPort) {
- // swift-format-ignore: NeverForceUnwrap
- var rcc = RCC(
- baseAddress: UnsafeMutableRawPointer(bitPattern: 0x4002_3800)!)
- switch port {
- case .a: rcc.ahb1enr.gpioaen = 1
- case .b: rcc.ahb1enr.gpioben = 1
- case .c: rcc.ahb1enr.gpiocen = 1
- case .d: rcc.ahb1enr.gpioden = 1
- case .e: rcc.ahb1enr.gpioeen = 1
- case .f: rcc.ahb1enr.gpiofen = 1
- case .g: rcc.ahb1enr.gpiogen = 1
- case .h: rcc.ahb1enr.gpiohen = 1
- case .i: rcc.ahb1enr.gpioien = 1
- case .j: rcc.ahb1enr.gpiojen = 1
- case .k: rcc.ahb1enr.gpioken = 1
- }
- }
-
- public static func enableUARTClock(_ uartNum: UInt8) {
- // swift-format-ignore: NeverForceUnwrap
- var rcc = RCC(
- baseAddress: UnsafeMutableRawPointer(bitPattern: 0x4002_3800)!)
- switch uartNum {
- case 1: rcc.apb2enr.usart1en = 1
- case 2: rcc.apb1enr.usart2en = 1
- case 3: rcc.apb1enr.usart3en = 1
- case 4: rcc.apb1enr.uart4en = 1
- case 5: rcc.apb1enr.uart5en = 1
- case 6: rcc.apb2enr.usart6en = 1
- case 7: rcc.apb1enr.uart7enr = 1
- case 8: rcc.apb1enr.uart8enr = 1
- default: return
- }
- }
-
- public static func enableI2CClock(_ i2cNum: UInt8) {
- // swift-format-ignore: NeverForceUnwrap
- var rcc = RCC(
- baseAddress: UnsafeMutableRawPointer(bitPattern: 0x4002_3800)!)
- switch i2cNum {
- case 1: rcc.apb1enr.i2c1en = 1
- case 2: rcc.apb1enr.i2c2en = 1
- case 3: rcc.apb1enr.i2c3en = 1
- case 4: rcc.apb1enr.i2c4en = 1
- default: return
- }
- }
-
- public static func enableSPIClock(_ spiNum: UInt8) {
- // swift-format-ignore: NeverForceUnwrap
- var rcc = RCC(
- baseAddress: UnsafeMutableRawPointer(bitPattern: 0x4002_3800)!)
- switch spiNum {
- case 1: rcc.apb2enr.spi1en = 1
- case 2: rcc.apb1enr.spi2en = 1
- case 3: rcc.apb1enr.spi3en = 1
- case 4: rcc.apb2enr.spi4enr = 1
- case 5: rcc.apb2enr.spi5enr = 1
- case 6: rcc.apb2enr.spi6enr = 1
- default: return
- }
- }
-
- public static func configureFlash() {
- let flash = UnsafeMutableRawPointer(bitPattern: (0x4002_3C00))
- // swift-format-ignore: NeverForceUnwrap
- let flashAcr = UnsafeMutablePointer