profile
viewpoint
David Nadlinger dnadlinger Oxford, UK http://klickverbot.at Formerly known as @klickverbot.

dnadlinger/d4 8

A simple software rasterizer for demonstration purposes written in D.

dnadlinger/3d-mathematics 3

A paper (in German) about the mathematical backgrounds of 3D computer graphics.

dnadlinger/devil_server 2

A high-performance, distributed C++ server to stream PID loop monitoring data to the network.

dnadlinger/as2api 1

My local fork of as2api.

dnadlinger/DigitalWhip 1

Programming languages domination benchmark

dnadlinger/dil 1

dil is a hand-written compiler for the D programming language.

dnadlinger/dlang.org 1

Pages for the dlang.org web site

dnadlinger/dmd 1

dmd D Programming Language compiler

dnadlinger/druntime 1

Low level runtime library for the D programming language

issue openedazonenberg/scopehal

Cache Filter::FindZeroCrossings results

Clear the cache each trigger.

When we call FindZeroCrossings on a waveform, it should be evaluated a max of once no matter how many times we call it.

created time in 6 minutes

issue openedazonenberg/scopehal

Add flag to Waveform indicating "waveform is dense packed"

This flag would default to false.

If set on an input, filters can avoid excessive copying of timestamps and durations as long as the sample count hasn't changed.

created time in 11 minutes

pull request commentdlang/dmd

Fixup PR11989: Remove pascal from LINK in global.h

Done

Geod24

comment created time in 30 minutes

GollumEvent

push eventNetHack/NetHack

PatR

commit sha de8337f402ea7a1b38d885e4965b3c1b7ae88af3

Qt extended commands When responding to '#', the Qt interface puts up a grid of buttons labelled with the names of commands. Then if the user types instead of clicking on a button, buttons which can no longer match are removed rather than grayed out. The remaining ones keep their same relative positions. Once whole rows or whole columns were gone, it looked awful. With rows gone, the size of the grid shrank but the popup stayed the same size, so the one-line prompt area expanded to fill up the vacated vertical space. That caused the prompt and partial response to move as they stayed centered in their growing area. With columns gone, the width of the buttons in remaining columns expanded and they spread out to take up vacated horizontal space. Once the candidate commands were all in one column, the buttons spanned the width of the grid. (That's mostly my fault due to changing the grid from being row-oriented [a b c] [d e ] to column oriented [a d] [b e] [c ] which resulted in columns going away a lot faster and possibly down to one when the old layout always had at least two. But old layout could drop to one row; the current layout always has at least two.) Also, accept ^[ as ESC. Typing ESC when partial input is present kills that input but keeps prompting. Typing ESC when no input is present (none entered yet or a second of two consecutive ESCs) cancels the operation. Allow ^U to kill partial input. If used when no input is present, nothing happens, similar to backspace. Unlike tty and curses, it's hardcoded here. That shouldn't be a problem because ESC can be used as a substitute if ^U isn't what the player normally uses.

view details

push time in an hour

push eventazonenberg/scopehal

Andrew D. Zonenberg

commit sha 625dc6c888d1e3723cf0cce63b2cba6183b02a6b

TappedDelayLineFilter: now fixed size of 8 taps

view details

Andrew D. Zonenberg

commit sha 30ed2c393219144a2c133b9c4d56b9b873864f06

TappedDelayLineFilter: AVX optimizations

view details

push time in an hour

issue commentquartiq/phaser

Interpolation filter initialization

@RHanley1 can you open a new issue for that? https://github.com/quartiq/phaser/issues/5#issuecomment-735813634

jordens

comment created time in 2 hours

push eventquartiq/stabilizer

Robert Jördens

commit sha 34d59dac5dd876b1f1ae2ea20333f1cc35cdfb70

adc: merge acquire_buffer and release_buffer again

view details

push time in 2 hours

Pull request review commentquartiq/stabilizer

Feature/adc dac io macros

 static mut SPI_START: [u16; 1] = [0x00]; // The following global buffers are used for the ADC sample DMA transfers. Two buffers are used for // each transfer in a ping-pong buffer configuration (one is being acquired while the other is being // processed). Note that the contents of AXI SRAM is uninitialized, so the buffer contents on-// startup are undefined.+// startup are undefined. The dimension are `ADC_BUF[adc_index][ping_pong_index][sample_index]`. #[link_section = ".axisram.buffers"]-static mut ADC0_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC0_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--/// SPI2 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI2 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI2 {-    _channel: sampling_timer::tim2::Channel1,-}-impl SPI2 {-    pub fn new(_channel: sampling_timer::tim2::Channel1) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 1 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI2 {-    /// SPI2 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI2 DMA requests are generated whenever TIM2 CH1 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH1 as u8);--    /// Whenever the DMA request occurs, it should write into SPI2's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI2 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI2::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// SPI3 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI3 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI3 {-    _channel: sampling_timer::tim2::Channel2,-}-impl SPI3 {-    pub fn new(_channel: sampling_timer::tim2::Channel2) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 2 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI3 {-    /// SPI3 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI3 DMA requests are generated whenever TIM2 CH2 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH2 as u8);--    /// Whenever the DMA request occurs, it should write into SPI3's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI3 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI3::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// Represents both ADC input channels.-pub struct AdcInputs {-    adc0: Adc0Input,-    adc1: Adc1Input,-}--impl AdcInputs {-    /// Construct the ADC inputs.-    pub fn new(adc0: Adc0Input, adc1: Adc1Input) -> Self {-        Self { adc0, adc1 }-    }--    /// Interrupt handler to handle when the sample collection DMA transfer completes.-    ///-    /// # Returns-    /// (adc0, adc1) where adcN is a reference to the collected ADC samples. Two array references-    /// are returned - one for each ADC sample stream.-    pub fn transfer_complete_handler(-        &mut self,-    ) -> (&[u16; SAMPLE_BUFFER_SIZE], &[u16; SAMPLE_BUFFER_SIZE]) {-        let adc0_buffer = self.adc0.transfer_complete_handler();-        let adc1_buffer = self.adc1.transfer_complete_handler();-        (adc0_buffer, adc1_buffer)-    }-}--/// Represents data associated with ADC0.-pub struct Adc0Input {-    next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,-    transfer: Transfer<-        hal::dma::dma::Stream1<hal::stm32::DMA1>,-        hal::spi::Spi<hal::stm32::SPI2, hal::spi::Disabled, u16>,-        PeripheralToMemory,-        &'static mut [u16; SAMPLE_BUFFER_SIZE],-    >,-    _trigger_transfer: Transfer<-        hal::dma::dma::Stream0<hal::stm32::DMA1>,-        SPI2,-        MemoryToPeripheral,-        &'static mut [u16; 1],-    >,-}--impl Adc0Input {-    /// Construct the ADC0 input channel.-    ///-    /// # Args-    /// * `spi` - The SPI interface used to communicate with the ADC.-    /// * `trigger_stream` - The DMA stream used to trigger each ADC transfer by writing a word into-    ///   the SPI TX FIFO.-    /// * `data_stream` - The DMA stream used to read samples received over SPI into a data buffer.-    /// * `_trigger_channel` - The ADC sampling timer output compare channel for read triggers.-    pub fn new(-        spi: hal::spi::Spi<hal::stm32::SPI2, hal::spi::Enabled, u16>,-        trigger_stream: hal::dma::dma::Stream0<hal::stm32::DMA1>,-        data_stream: hal::dma::dma::Stream1<hal::stm32::DMA1>,-        trigger_channel: sampling_timer::tim2::Channel1,-    ) -> Self {-        // Generate DMA events when an output compare of the timer hitting zero (timer roll over)-        // occurs.-        trigger_channel.listen_dma();-        trigger_channel.to_output_compare(0);--        // The trigger stream constantly writes to the TX FIFO using a static word (dont-care-        // contents). Thus, neither the memory or peripheral address ever change. This is run in-        // circular mode to be completed at every DMA request.-        let trigger_config = DmaConfig::default()-            .priority(Priority::High)-            .circular_buffer(true);--        // Construct the trigger stream to write from memory to the peripheral.-        let mut trigger_transfer: Transfer<_, _, MemoryToPeripheral, _> =-            Transfer::init(-                trigger_stream,-                SPI2::new(trigger_channel),-                // Note(unsafe): Because this is a Memory->Peripheral transfer, this data is never-                // actually modified. It technically only needs to be immutably borrowed, but the-                // current HAL API only supports mutable borrows.-                unsafe { &mut SPI_START },-                None,-                trigger_config,-            );--        // The data stream constantly reads from the SPI RX FIFO into a RAM buffer. The peripheral-        // stalls reads of the SPI RX FIFO until data is available, so the DMA transfer completes-        // after the requested number of samples have been collected. Note that only ADC1's data-        // stream is used to trigger a transfer completion interrupt.-        let data_config = DmaConfig::default()-            .memory_increment(true)-            .priority(Priority::VeryHigh);--        // A SPI peripheral error interrupt is used to determine if the RX FIFO overflows. This-        // indicates that samples were dropped due to excessive processing time in the main-        // application (e.g. a second DMA transfer completes before the first was done with-        // processing). This is used as a flow control indicator to guarantee that no ADC samples-        // are lost.-        let mut spi = spi.disable();-        spi.listen(hal::spi::Event::Error);--        // The data transfer is always a transfer of data from the peripheral to a RAM buffer.-        let mut data_transfer: Transfer<_, _, PeripheralToMemory, _> =-            Transfer::init(-                data_stream,-                spi,-                // Note(unsafe): The ADC0_BUF0 is "owned" by this peripheral. It shall not be used-                // anywhere else in the module.-                unsafe { &mut ADC0_BUF0 },-                None,-                data_config,-            );--        data_transfer.start(|spi| {-            // Allow the SPI FIFOs to operate using only DMA data channels.-            spi.enable_dma_rx();-            spi.enable_dma_tx();--            // Enable SPI and start it in infinite transaction mode.-            spi.inner().cr1.modify(|_, w| w.spe().set_bit());-            spi.inner().cr1.modify(|_, w| w.cstart().started());-        });--        trigger_transfer.start(|_| {});--        Self {-            // Note(unsafe): The ADC0_BUF1 is "owned" by this peripheral. It shall not be used-            // anywhere else in the module.-            next_buffer: unsafe { Some(&mut ADC0_BUF1) },-            transfer: data_transfer,-            _trigger_transfer: trigger_transfer,+static mut ADC_BUF: [[[u16; SAMPLE_BUFFER_SIZE]; 2]; 2] =+    [[[0; SAMPLE_BUFFER_SIZE]; 2]; 2];++macro_rules! adc_input {+    ($name:ident, $index:literal, $trigger_stream:ident, $data_stream:ident,+     $spi:ident, $trigger_channel:ident, $dma_req:ident) => {+        /// $spi is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI TX FIFO+        /// whenever the tim2 update dma request occurs.+        struct $spi {+            _channel: sampling_timer::tim2::$trigger_channel,         }-    }--    /// Handle a transfer completion.-    ///-    /// # Returns-    /// A reference to the underlying buffer that has been filled with ADC samples.-    pub fn transfer_complete_handler(&mut self) -> &[u16; SAMPLE_BUFFER_SIZE] {-        let next_buffer = self.next_buffer.take().unwrap();--        // Wait for the transfer to fully complete before continuing.-        // Note: If a device hangs up, check that this conditional is passing correctly, as there is-        // no time-out checks here in the interest of execution speed.-        while self.transfer.get_transfer_complete_flag() == false {}--        // Start the next transfer.-        self.transfer.clear_interrupts();-        let (prev_buffer, _) =-            self.transfer.next_transfer(next_buffer).unwrap();--        self.next_buffer.replace(prev_buffer);-        self.next_buffer.as_ref().unwrap()-    }-}--/// Represents the data input stream from ADC1-pub struct Adc1Input {-    next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,-    transfer: Transfer<-        hal::dma::dma::Stream3<hal::stm32::DMA1>,-        hal::spi::Spi<hal::stm32::SPI3, hal::spi::Disabled, u16>,-        PeripheralToMemory,-        &'static mut [u16; SAMPLE_BUFFER_SIZE],-    >,-    _trigger_transfer: Transfer<-        hal::dma::dma::Stream2<hal::stm32::DMA1>,-        SPI3,-        MemoryToPeripheral,-        &'static mut [u16; 1],-    >,-}--impl Adc1Input {-    /// Construct a new ADC1 input data stream.-    ///-    /// # Args-    /// * `spi` - The SPI interface connected to ADC1.-    /// * `trigger_stream` - The DMA stream used to trigger ADC conversions on the SPI interface.-    /// * `data_stream` - The DMA stream used to read ADC samples from the SPI RX FIFO.-    /// * `trigger_channel` - The ADC sampling timer output compare channel for read triggers.-    pub fn new(-        spi: hal::spi::Spi<hal::stm32::SPI3, hal::spi::Enabled, u16>,-        trigger_stream: hal::dma::dma::Stream2<hal::stm32::DMA1>,-        data_stream: hal::dma::dma::Stream3<hal::stm32::DMA1>,-        trigger_channel: sampling_timer::tim2::Channel2,-    ) -> Self {-        // Generate DMA events when an output compare of the timer hitting zero (timer roll over)-        // occurs.-        trigger_channel.listen_dma();-        trigger_channel.to_output_compare(0);--        // The trigger stream constantly writes to the TX FIFO using a static word (dont-care-        // contents). Thus, neither the memory or peripheral address ever change. This is run in-        // circular mode to be completed at every DMA request.-        let trigger_config = DmaConfig::default()-            .priority(Priority::High)-            .circular_buffer(true);--        // Construct the trigger stream to write from memory to the peripheral.-        let mut trigger_transfer: Transfer<_, _, MemoryToPeripheral, _> =-            Transfer::init(-                trigger_stream,-                SPI3::new(trigger_channel),-                // Note(unsafe). This transaction is read-only and SPI_START is a dont-care value,-                // so it is always safe to share.-                unsafe { &mut SPI_START },-                None,-                trigger_config,-            );--        // The data stream constantly reads from the SPI RX FIFO into a RAM buffer. The peripheral-        // stalls reads of the SPI RX FIFO until data is available, so the DMA transfer completes-        // after the requested number of samples have been collected. Note that only ADC1's data-        // stream is used to trigger a transfer completion interrupt.-        let data_config = DmaConfig::default()-            .memory_increment(true)-            .transfer_complete_interrupt(true)-            .priority(Priority::VeryHigh);--        // A SPI peripheral error interrupt is used to determine if the RX FIFO overflows. This-        // indicates that samples were dropped due to excessive processing time in the main-        // application (e.g. a second DMA transfer completes before the first was done with-        // processing). This is used as a flow control indicator to guarantee that no ADC samples-        // are lost.-        let mut spi = spi.disable();-        spi.listen(hal::spi::Event::Error);--        // The data transfer is always a transfer of data from the peripheral to a RAM buffer.-        let mut data_transfer: Transfer<_, _, PeripheralToMemory, _> =-            Transfer::init(-                data_stream,-                spi,-                // Note(unsafe): The ADC1_BUF0 is "owned" by this peripheral. It shall not be used-                // anywhere else in the module.-                unsafe { &mut ADC1_BUF0 },-                None,-                data_config,-            );--        data_transfer.start(|spi| {-            // Allow the SPI FIFOs to operate using only DMA data channels.-            spi.enable_dma_rx();-            spi.enable_dma_tx();--            // Enable SPI and start it in infinite transaction mode.-            spi.inner().cr1.modify(|_, w| w.spe().set_bit());-            spi.inner().cr1.modify(|_, w| w.cstart().started());-        });--        trigger_transfer.start(|_| {});--        Self {-            // Note(unsafe): The ADC1_BUF1 is "owned" by this peripheral. It shall not be used-            // anywhere else in the module.-            next_buffer: unsafe { Some(&mut ADC1_BUF1) },-            transfer: data_transfer,-            _trigger_transfer: trigger_transfer,+        impl $spi {+            pub fn new(+                _channel: sampling_timer::tim2::$trigger_channel,+            ) -> Self {+                Self { _channel }+            }         }-    } -    /// Handle a transfer completion.-    ///-    /// # Returns-    /// A reference to the underlying buffer that has been filled with ADC samples.-    pub fn transfer_complete_handler(&mut self) -> &[u16; SAMPLE_BUFFER_SIZE] {-        let next_buffer = self.next_buffer.take().unwrap();--        // Wait for the transfer to fully complete before continuing.-        // Note: If a device hangs up, check that this conditional is passing correctly, as there is-        // no time-out checks here in the interest of execution speed.-        while self.transfer.get_transfer_complete_flag() == false {}+        // Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and+        // may only be used if ownership of the timer2 $trigger_channel compare channel is assured, which is+        // ensured by maintaining ownership of the channel.+        unsafe impl TargetAddress<MemoryToPeripheral> for $spi {+            /// SPI is configured to operate using 16-bit transfer words.+            type MemSize = u16;++            /// SPI DMA requests are generated whenever TIM2 CHx ($dma_req) comparison occurs.+            const REQUEST_LINE: Option<u8> = Some(DMAReq::$dma_req as u8);++            /// Whenever the DMA request occurs, it should write into SPI's TX FIFO to start a DMA+            /// transfer.+            fn address(&self) -> u32 {+                // Note(unsafe): It is assumed that SPI is owned by another DMA transfer and this DMA is+                // only used for the transmit-half of DMA.+                let regs = unsafe { &*hal::stm32::$spi::ptr() };+                &regs.txdr as *const _ as u32+            }+        } -        // Start the next transfer.-        self.transfer.clear_interrupts();-        let (prev_buffer, _) =-            self.transfer.next_transfer(next_buffer).unwrap();+        /// Represents data associated with ADC.+        pub struct $name {+            next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,+            transfer: Transfer<+                hal::dma::dma::$data_stream<hal::stm32::DMA1>,+                hal::spi::Spi<hal::stm32::$spi, hal::spi::Disabled, u16>,+                PeripheralToMemory,+                &'static mut [u16; SAMPLE_BUFFER_SIZE],+            >,+            _trigger_transfer: Transfer<+                hal::dma::dma::$trigger_stream<hal::stm32::DMA1>,+                $spi,+                MemoryToPeripheral,+                &'static mut [u16; 1],+            >,+        } -        self.next_buffer.replace(prev_buffer);-        self.next_buffer.as_ref().unwrap()-    }+        impl $name {+            /// Construct the ADC input channel.+            ///+            /// # Args+            /// * `spi` - The SPI interface used to communicate with the ADC.+            /// * `trigger_stream` - The DMA stream used to trigger each ADC transfer by writing a word into+            ///   the SPI TX FIFO.+            /// * `data_stream` - The DMA stream used to read samples received over SPI into a data buffer.+            /// * `_trigger_channel` - The ADC sampling timer output compare channel for read triggers.+            pub fn new(+                spi: hal::spi::Spi<hal::stm32::$spi, hal::spi::Enabled, u16>,+                trigger_stream: hal::dma::dma::$trigger_stream<+                    hal::stm32::DMA1,+                >,+                data_stream: hal::dma::dma::$data_stream<hal::stm32::DMA1>,+                trigger_channel: sampling_timer::tim2::$trigger_channel,+            ) -> Self {+                // Generate DMA events when an output compare of the timer hitting zero (timer roll over)+                // occurs.+                trigger_channel.listen_dma();+                trigger_channel.to_output_compare(0);++                // The trigger stream constantly writes to the TX FIFO using a static word (dont-care+                // contents). Thus, neither the memory or peripheral address ever change. This is run in+                // circular mode to be completed at every DMA request.+                let trigger_config = DmaConfig::default()+                    .priority(Priority::High)+                    .circular_buffer(true);++                // Construct the trigger stream to write from memory to the peripheral.+                let mut trigger_transfer: Transfer<+                    _,+                    _,+                    MemoryToPeripheral,+                    _,+                > = Transfer::init(+                    trigger_stream,+                    $spi::new(trigger_channel),+                    // Note(unsafe): Because this is a Memory->Peripheral transfer, this data is never+                    // actually modified. It technically only needs to be immutably borrowed, but the+                    // current HAL API only supports mutable borrows.+                    unsafe { &mut SPI_START },+                    None,+                    trigger_config,+                );++                // The data stream constantly reads from the SPI RX FIFO into a RAM buffer. The peripheral+                // stalls reads of the SPI RX FIFO until data is available, so the DMA transfer completes+                // after the requested number of samples have been collected. Note that only ADC1's (sic!)+                // data stream is used to trigger a transfer completion interrupt.+                let data_config = DmaConfig::default()+                    .memory_increment(true)+                    .transfer_complete_interrupt($index == 1)+                    .priority(Priority::VeryHigh);++                // A SPI peripheral error interrupt is used to determine if the RX FIFO overflows. This+                // indicates that samples were dropped due to excessive processing time in the main+                // application (e.g. a second DMA transfer completes before the first was done with+                // processing). This is used as a flow control indicator to guarantee that no ADC samples+                // are lost.+                let mut spi = spi.disable();+                spi.listen(hal::spi::Event::Error);++                // The data transfer is always a transfer of data from the peripheral to a RAM buffer.+                let mut data_transfer: Transfer<_, _, PeripheralToMemory, _> =+                    Transfer::init(+                        data_stream,+                        spi,+                        // Note(unsafe): The ADC_BUF[$index][0] is "owned" by this peripheral.+                        // It shall not be used anywhere else in the module.+                        unsafe { &mut ADC_BUF[$index][0] },+                        None,+                        data_config,+                    );++                data_transfer.start(|spi| {+                    // Allow the SPI FIFOs to operate using only DMA data channels.+                    spi.enable_dma_rx();+                    spi.enable_dma_tx();++                    // Enable SPI and start it in infinite transaction mode.+                    spi.inner().cr1.modify(|_, w| w.spe().set_bit());+                    spi.inner().cr1.modify(|_, w| w.cstart().started());+                });++                trigger_transfer.start(|_| {});++                Self {+                    // Note(unsafe): The ADC_BUF[$index][1] is "owned" by this peripheral. It shall not be used+                    // anywhere else in the module.+                    next_buffer: unsafe { Some(&mut ADC_BUF[$index][1]) },+                    transfer: data_transfer,+                    _trigger_transfer: trigger_transfer,+                }+            }++            /// Obtain a buffer filled with ADC samples.+            ///+            /// # Returns+            /// A reference to the underlying buffer that has been filled with ADC samples.+            pub fn acquire_buffer(+                &mut self,+            ) -> &'static mut [u16; SAMPLE_BUFFER_SIZE] {+                // Wait for the transfer to fully complete before continuing.+                // Note: If a device hangs up, check that this conditional is passing correctly, as there is+                // no time-out checks here in the interest of execution speed.+                while !self.transfer.get_transfer_complete_flag() {}++                let next_buffer = self.next_buffer.take().unwrap();++                // Start the next transfer.+                self.transfer.clear_interrupts();+                let (prev_buffer, _) =+                    self.transfer.next_transfer(next_buffer).unwrap();++                prev_buffer+            }++            /// Release a buffer of ADC samples to the pool.+            ///+            /// # Args+            /// * `next_buffer` - Buffer of ADC samples to be re-used.+            pub fn release_buffer(+                &mut self,+                next_buffer: &'static mut [u16; SAMPLE_BUFFER_SIZE],+            ) {+                self.next_buffer.replace(next_buffer); // .unwrap_none() https://github.com/rust-lang/rust/issues/62633

It was. And also to keep up the symmetry with the DAC API to help me understand things and differential design. Let's revert that and see whether there are further changes around that DMA API that may warrant this.

jordens

comment created time in 2 hours

push eventNetHack/NetHack

Pasi Kallinen

commit sha a8ed1ab5fdb987ad28e6be5659a80298730dc1a8

Test wishing "bags of tricks"

view details

push time in 2 hours

issue commentquartiq/phaser

Interpolation filter initialization

@RHanley1 please stop posting unrelated stuff on this issue.

jordens

comment created time in 2 hours

issue commentquartiq/phaser

Interpolation filter initialization

On I2C flashing: as I explained, the code is there, you need to try it. It will be very slow. Don't magically expect to be comfortable. I don't have a Kasli-v1.1 to test it with.

On the Phaser resets, please re-read my explanations. There is no need to do a dance with reloading Kasli to work around this issue. Let's first fix the easy silly issues and then see whether the remaining are blockers.

Vivado can leave a hw_server and a cs_server around if it is unhappy about something. That'll block.

jordens

comment created time in 2 hours

issue commentquartiq/phaser

Interpolation filter initialization

Current situation:

Number of tones Plot
Single tone at 0MHz image
Two tones, +/- 5MHz image
Three tones, 0MHz and +/- 5MHz image
jordens

comment created time in 2 hours

issue commentquartiq/phaser

Interpolation filter initialization

@RHanley1 should comment, but I believe that the specific issue he's seeing is that he's getting spurious output when using 3 tones on phaser. This had previously been working so it's likely that phaser just needs to be reloaded, but vivado is now playing up.

jordens

comment created time in 3 hours

push eventquartiq/stabilizer

dependabot[bot]

commit sha 7e6cabe9c163f2c1e0ea01132cf86aa34a030404

build(deps): bump panic-semihosting from 0.5.4 to 0.5.6 Bumps [panic-semihosting](https://github.com/rust-embedded/cortex-m) from 0.5.4 to 0.5.6. - [Release notes](https://github.com/rust-embedded/cortex-m/releases) - [Changelog](https://github.com/rust-embedded/cortex-m/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-embedded/cortex-m/compare/v0.5.4...v0.5.6) Signed-off-by: dependabot[bot] <support@github.com>

view details

bors[bot]

commit sha 506d59c20654357fd0edf0c97f10fcc4864da511

Merge #169 169: build(deps): bump panic-semihosting from 0.5.4 to 0.5.6 r=jordens a=dependabot[bot] [//]: # (dependabot-start) ⚠️ **Dependabot is rebasing this PR** ⚠️ If you make any changes to it yourself then they will take precedence over the rebase. --- [//]: # (dependabot-end) Bumps [panic-semihosting](https://github.com/rust-embedded/cortex-m) from 0.5.4 to 0.5.6. <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/rust-embedded/cortex-m/blob/master/CHANGELOG.md">panic-semihosting's changelog</a>.</em></p> <blockquote> <h2>[v0.5.6] - 2018-08-27</h2> <h3>Fixed</h3> <ul> <li> <p>Removed duplicated symbols from binary blobs</p> </li> <li> <p>The check-blobs.sh script</p> </li> </ul> <h2>[v0.5.5] - 2018-08-27 - YANKED</h2> <h3>Changed</h3> <ul> <li>This crate no longer depends on <code>arm-none-eabi-gcc</code>.</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/rust-embedded/cortex-m/commit/278ab0d5b929dc23e6d9538faf1bc2ac633b9caa"><code>278ab0d</code></a> Merge <a href="https://github-redirect.dependabot.com/rust-embedded/cortex-m/issues/110">#110</a></li> <li><a href="https://github.com/rust-embedded/cortex-m/commit/6cbe16430b8d0c319b64d579801290e4b957104c"><code>6cbe164</code></a> fix check-blobs.sh</li> <li><a href="https://github.com/rust-embedded/cortex-m/commit/399793b26b94ba1e59b85bc0b4714a0efd772479"><code>399793b</code></a> Merge <a href="https://github-redirect.dependabot.com/rust-embedded/cortex-m/issues/109">#109</a></li> <li><a href="https://github.com/rust-embedded/cortex-m/commit/ca61baec53c707f6a7814b97045f522d01b338c3"><code>ca61bae</code></a> v0.5.5</li> <li><a href="https://github.com/rust-embedded/cortex-m/commit/478418c0eb38b9311e574d18d12cac69d3044e63"><code>478418c</code></a> Merge <a href="https://github-redirect.dependabot.com/rust-embedded/cortex-m/issues/108">#108</a></li> <li><a href="https://github.com/rust-embedded/cortex-m/commit/945e2683f89a031b44b65d25e1917f3157c49fa1"><code>945e268</code></a> test PRs</li> <li><a href="https://github.com/rust-embedded/cortex-m/commit/c33d890dcb5a03649f07dd6c46729e7873468b40"><code>c33d890</code></a> remove build dependency on arm-none-eabi-gcc</li> <li>See full diff in <a href="https://github.com/rust-embedded/cortex-m/compare/v0.5.4...v0.5.6">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=panic-semihosting&package-manager=cargo&previous-version=0.5.4&new-version=0.5.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/configuring-github-dependabot-security-updates) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

view details

dependabot[bot]

commit sha de827acdc8ef9d8db407fea9d6e8a19522a805bc

build(deps): bump paste from 1.0.2 to 1.0.3 Bumps [paste](https://github.com/dtolnay/paste) from 1.0.2 to 1.0.3. - [Release notes](https://github.com/dtolnay/paste/releases) - [Commits](https://github.com/dtolnay/paste/compare/1.0.2...1.0.3) Signed-off-by: dependabot[bot] <support@github.com>

view details

bors[bot]

commit sha 9478df253cfd31f12f2186f2a0b58079f63c532a

Merge #179 179: build(deps): bump paste from 1.0.2 to 1.0.3 r=jordens a=dependabot[bot] Bumps [paste](https://github.com/dtolnay/paste) from 1.0.2 to 1.0.3. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/dtolnay/paste/releases">paste's releases</a>.</em></p> <blockquote> <h2>1.0.3</h2> <ul> <li>Support paste inside cfg and other name-value attributes (<a href="https://github-redirect.dependabot.com/dtolnay/paste/issues/56">#56</a>, <a href="https://github-redirect.dependabot.com/dtolnay/paste/issues/57">#57</a>)</li> </ul> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/dtolnay/paste/commit/a3e4ace7092f5f0b750efe22fe8c4b65e8495d94"><code>a3e4ace</code></a> Release 1.0.3</li> <li><a href="https://github.com/dtolnay/paste/commit/466556ee997f0636a8c7db6db0ecf7624d5f2adc"><code>466556e</code></a> Resolve clippy collapsible_if lint</li> <li><a href="https://github.com/dtolnay/paste/commit/97cd2b7c85ca64ce16b8f784d85ec2c3a6d34847"><code>97cd2b7</code></a> Restore support for rustc 1.31</li> <li><a href="https://github.com/dtolnay/paste/commit/4d04c18a136a857b568637ec07c09c4b8d7278b1"><code>4d04c18</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/dtolnay/paste/issues/57">#57</a> from scalexm/attr</li> <li><a href="https://github.com/dtolnay/paste/commit/82e3f0346d8d1a42d58aa803e5ef5cd2489467dd"><code>82e3f03</code></a> Support paste in arbitrary name-value attributes</li> <li>See full diff in <a href="https://github.com/dtolnay/paste/compare/1.0.2...1.0.3">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=paste&package-manager=cargo&previous-version=1.0.2&new-version=1.0.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/configuring-github-dependabot-security-updates) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

view details

Robert Jördens

commit sha fe764a47a5c26bb79dd7cc77d2d12df7dffd8d92

gha: clippy-check

view details

bors[bot]

commit sha 6bdec8239cbbe00793d884b4fe341c331470a467

Merge #181 181: gha: clippy-check r=jordens a=jordens Co-authored-by: Robert Jördens <rj@quartiq.de>

view details

Robert Jördens

commit sha 7fc6f5c4adfa3276ce92a40f3785130dda90d812

clippy lints

view details

Robert Jördens

commit sha 128e7dd78ea57b0bc2be3cc440fc4bd92ff91c90

more nightly clippy lints

view details

Robert Jördens

commit sha 8ef6c0679feab592baa9fc4f078e1021fe830188

Merge pull request #182 from quartiq/feature/clippy-lints clippy lints

view details

Robert Jördens

commit sha c72f95993321944880c1fa96a4a4dc073559502d

Merge remote-tracking branch 'origin/master' into feature/adc-dac-io-macros * origin/master: more nightly clippy lints clippy lints gha: clippy-check build(deps): bump paste from 1.0.2 to 1.0.3 build(deps): bump panic-semihosting from 0.5.4 to 0.5.6

view details

Robert Jördens

commit sha b1301a61849ef0fe7669073ed178130d72d66f53

dac,adc: spelling

view details

push time in 3 hours

Pull request review commentquartiq/stabilizer

Feature/adc dac io macros

 static mut SPI_START: [u16; 1] = [0x00]; // The following global buffers are used for the ADC sample DMA transfers. Two buffers are used for // each transfer in a ping-pong buffer configuration (one is being acquired while the other is being // processed). Note that the contents of AXI SRAM is uninitialized, so the buffer contents on-// startup are undefined.+// startup are undefined. The dimension are `ADC_BUF[adc_index][ping_pong_index][sample_index]`. #[link_section = ".axisram.buffers"]-static mut ADC0_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC0_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--/// SPI2 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI2 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI2 {-    _channel: sampling_timer::tim2::Channel1,-}-impl SPI2 {-    pub fn new(_channel: sampling_timer::tim2::Channel1) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 1 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI2 {-    /// SPI2 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI2 DMA requests are generated whenever TIM2 CH1 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH1 as u8);--    /// Whenever the DMA request occurs, it should write into SPI2's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI2 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI2::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// SPI3 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI3 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI3 {-    _channel: sampling_timer::tim2::Channel2,-}-impl SPI3 {-    pub fn new(_channel: sampling_timer::tim2::Channel2) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 2 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI3 {-    /// SPI3 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI3 DMA requests are generated whenever TIM2 CH2 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH2 as u8);--    /// Whenever the DMA request occurs, it should write into SPI3's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI3 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI3::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// Represents both ADC input channels.-pub struct AdcInputs {-    adc0: Adc0Input,-    adc1: Adc1Input,-}--impl AdcInputs {-    /// Construct the ADC inputs.-    pub fn new(adc0: Adc0Input, adc1: Adc1Input) -> Self {-        Self { adc0, adc1 }-    }--    /// Interrupt handler to handle when the sample collection DMA transfer completes.-    ///-    /// # Returns-    /// (adc0, adc1) where adcN is a reference to the collected ADC samples. Two array references-    /// are returned - one for each ADC sample stream.-    pub fn transfer_complete_handler(-        &mut self,-    ) -> (&[u16; SAMPLE_BUFFER_SIZE], &[u16; SAMPLE_BUFFER_SIZE]) {-        let adc0_buffer = self.adc0.transfer_complete_handler();-        let adc1_buffer = self.adc1.transfer_complete_handler();-        (adc0_buffer, adc1_buffer)-    }-}--/// Represents data associated with ADC0.-pub struct Adc0Input {-    next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,-    transfer: Transfer<-        hal::dma::dma::Stream1<hal::stm32::DMA1>,-        hal::spi::Spi<hal::stm32::SPI2, hal::spi::Disabled, u16>,-        PeripheralToMemory,-        &'static mut [u16; SAMPLE_BUFFER_SIZE],-    >,-    _trigger_transfer: Transfer<-        hal::dma::dma::Stream0<hal::stm32::DMA1>,-        SPI2,-        MemoryToPeripheral,-        &'static mut [u16; 1],-    >,-}--impl Adc0Input {-    /// Construct the ADC0 input channel.-    ///-    /// # Args-    /// * `spi` - The SPI interface used to communicate with the ADC.-    /// * `trigger_stream` - The DMA stream used to trigger each ADC transfer by writing a word into-    ///   the SPI TX FIFO.-    /// * `data_stream` - The DMA stream used to read samples received over SPI into a data buffer.-    /// * `_trigger_channel` - The ADC sampling timer output compare channel for read triggers.-    pub fn new(-        spi: hal::spi::Spi<hal::stm32::SPI2, hal::spi::Enabled, u16>,-        trigger_stream: hal::dma::dma::Stream0<hal::stm32::DMA1>,-        data_stream: hal::dma::dma::Stream1<hal::stm32::DMA1>,-        trigger_channel: sampling_timer::tim2::Channel1,-    ) -> Self {-        // Generate DMA events when an output compare of the timer hitting zero (timer roll over)-        // occurs.-        trigger_channel.listen_dma();-        trigger_channel.to_output_compare(0);--        // The trigger stream constantly writes to the TX FIFO using a static word (dont-care-        // contents). Thus, neither the memory or peripheral address ever change. This is run in-        // circular mode to be completed at every DMA request.-        let trigger_config = DmaConfig::default()-            .priority(Priority::High)-            .circular_buffer(true);--        // Construct the trigger stream to write from memory to the peripheral.-        let mut trigger_transfer: Transfer<_, _, MemoryToPeripheral, _> =-            Transfer::init(-                trigger_stream,-                SPI2::new(trigger_channel),-                // Note(unsafe): Because this is a Memory->Peripheral transfer, this data is never-                // actually modified. It technically only needs to be immutably borrowed, but the-                // current HAL API only supports mutable borrows.-                unsafe { &mut SPI_START },-                None,-                trigger_config,-            );--        // The data stream constantly reads from the SPI RX FIFO into a RAM buffer. The peripheral-        // stalls reads of the SPI RX FIFO until data is available, so the DMA transfer completes-        // after the requested number of samples have been collected. Note that only ADC1's data-        // stream is used to trigger a transfer completion interrupt.-        let data_config = DmaConfig::default()-            .memory_increment(true)-            .priority(Priority::VeryHigh);--        // A SPI peripheral error interrupt is used to determine if the RX FIFO overflows. This-        // indicates that samples were dropped due to excessive processing time in the main-        // application (e.g. a second DMA transfer completes before the first was done with-        // processing). This is used as a flow control indicator to guarantee that no ADC samples-        // are lost.-        let mut spi = spi.disable();-        spi.listen(hal::spi::Event::Error);--        // The data transfer is always a transfer of data from the peripheral to a RAM buffer.-        let mut data_transfer: Transfer<_, _, PeripheralToMemory, _> =-            Transfer::init(-                data_stream,-                spi,-                // Note(unsafe): The ADC0_BUF0 is "owned" by this peripheral. It shall not be used-                // anywhere else in the module.-                unsafe { &mut ADC0_BUF0 },-                None,-                data_config,-            );--        data_transfer.start(|spi| {-            // Allow the SPI FIFOs to operate using only DMA data channels.-            spi.enable_dma_rx();-            spi.enable_dma_tx();--            // Enable SPI and start it in infinite transaction mode.-            spi.inner().cr1.modify(|_, w| w.spe().set_bit());-            spi.inner().cr1.modify(|_, w| w.cstart().started());-        });--        trigger_transfer.start(|_| {});--        Self {-            // Note(unsafe): The ADC0_BUF1 is "owned" by this peripheral. It shall not be used-            // anywhere else in the module.-            next_buffer: unsafe { Some(&mut ADC0_BUF1) },-            transfer: data_transfer,-            _trigger_transfer: trigger_transfer,+static mut ADC_BUF: [[[u16; SAMPLE_BUFFER_SIZE]; 2]; 2] =+    [[[0; SAMPLE_BUFFER_SIZE]; 2]; 2];

Ah, that must not work in static mut scope then. That's rather annoying, but I guess we can live with how this looks. Sorry for leading you down the wrong path

jordens

comment created time in 3 hours

Pull request review commentquartiq/stabilizer

Feature/adc dac io macros

 static mut SPI_START: [u16; 1] = [0x00]; // The following global buffers are used for the ADC sample DMA transfers. Two buffers are used for // each transfer in a ping-pong buffer configuration (one is being acquired while the other is being // processed). Note that the contents of AXI SRAM is uninitialized, so the buffer contents on-// startup are undefined.+// startup are undefined. The dimension are `ADC_BUF[adc_index][ping_pong_index][sample_index]`. #[link_section = ".axisram.buffers"]-static mut ADC0_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC0_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--/// SPI2 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI2 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI2 {-    _channel: sampling_timer::tim2::Channel1,-}-impl SPI2 {-    pub fn new(_channel: sampling_timer::tim2::Channel1) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 1 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI2 {-    /// SPI2 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI2 DMA requests are generated whenever TIM2 CH1 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH1 as u8);--    /// Whenever the DMA request occurs, it should write into SPI2's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI2 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI2::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// SPI3 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI3 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI3 {-    _channel: sampling_timer::tim2::Channel2,-}-impl SPI3 {-    pub fn new(_channel: sampling_timer::tim2::Channel2) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 2 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI3 {-    /// SPI3 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI3 DMA requests are generated whenever TIM2 CH2 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH2 as u8);--    /// Whenever the DMA request occurs, it should write into SPI3's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI3 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI3::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// Represents both ADC input channels.-pub struct AdcInputs {-    adc0: Adc0Input,-    adc1: Adc1Input,-}--impl AdcInputs {-    /// Construct the ADC inputs.-    pub fn new(adc0: Adc0Input, adc1: Adc1Input) -> Self {-        Self { adc0, adc1 }-    }--    /// Interrupt handler to handle when the sample collection DMA transfer completes.-    ///-    /// # Returns-    /// (adc0, adc1) where adcN is a reference to the collected ADC samples. Two array references-    /// are returned - one for each ADC sample stream.-    pub fn transfer_complete_handler(-        &mut self,-    ) -> (&[u16; SAMPLE_BUFFER_SIZE], &[u16; SAMPLE_BUFFER_SIZE]) {-        let adc0_buffer = self.adc0.transfer_complete_handler();-        let adc1_buffer = self.adc1.transfer_complete_handler();-        (adc0_buffer, adc1_buffer)-    }-}--/// Represents data associated with ADC0.-pub struct Adc0Input {-    next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,-    transfer: Transfer<-        hal::dma::dma::Stream1<hal::stm32::DMA1>,-        hal::spi::Spi<hal::stm32::SPI2, hal::spi::Disabled, u16>,-        PeripheralToMemory,-        &'static mut [u16; SAMPLE_BUFFER_SIZE],-    >,-    _trigger_transfer: Transfer<-        hal::dma::dma::Stream0<hal::stm32::DMA1>,-        SPI2,-        MemoryToPeripheral,-        &'static mut [u16; 1],-    >,-}--impl Adc0Input {-    /// Construct the ADC0 input channel.-    ///-    /// # Args-    /// * `spi` - The SPI interface used to communicate with the ADC.-    /// * `trigger_stream` - The DMA stream used to trigger each ADC transfer by writing a word into-    ///   the SPI TX FIFO.-    /// * `data_stream` - The DMA stream used to read samples received over SPI into a data buffer.-    /// * `_trigger_channel` - The ADC sampling timer output compare channel for read triggers.-    pub fn new(-        spi: hal::spi::Spi<hal::stm32::SPI2, hal::spi::Enabled, u16>,-        trigger_stream: hal::dma::dma::Stream0<hal::stm32::DMA1>,-        data_stream: hal::dma::dma::Stream1<hal::stm32::DMA1>,-        trigger_channel: sampling_timer::tim2::Channel1,-    ) -> Self {-        // Generate DMA events when an output compare of the timer hitting zero (timer roll over)-        // occurs.-        trigger_channel.listen_dma();-        trigger_channel.to_output_compare(0);--        // The trigger stream constantly writes to the TX FIFO using a static word (dont-care-        // contents). Thus, neither the memory or peripheral address ever change. This is run in-        // circular mode to be completed at every DMA request.-        let trigger_config = DmaConfig::default()-            .priority(Priority::High)-            .circular_buffer(true);--        // Construct the trigger stream to write from memory to the peripheral.-        let mut trigger_transfer: Transfer<_, _, MemoryToPeripheral, _> =-            Transfer::init(-                trigger_stream,-                SPI2::new(trigger_channel),-                // Note(unsafe): Because this is a Memory->Peripheral transfer, this data is never-                // actually modified. It technically only needs to be immutably borrowed, but the-                // current HAL API only supports mutable borrows.-                unsafe { &mut SPI_START },-                None,-                trigger_config,-            );--        // The data stream constantly reads from the SPI RX FIFO into a RAM buffer. The peripheral-        // stalls reads of the SPI RX FIFO until data is available, so the DMA transfer completes-        // after the requested number of samples have been collected. Note that only ADC1's data-        // stream is used to trigger a transfer completion interrupt.-        let data_config = DmaConfig::default()-            .memory_increment(true)-            .priority(Priority::VeryHigh);--        // A SPI peripheral error interrupt is used to determine if the RX FIFO overflows. This-        // indicates that samples were dropped due to excessive processing time in the main-        // application (e.g. a second DMA transfer completes before the first was done with-        // processing). This is used as a flow control indicator to guarantee that no ADC samples-        // are lost.-        let mut spi = spi.disable();-        spi.listen(hal::spi::Event::Error);--        // The data transfer is always a transfer of data from the peripheral to a RAM buffer.-        let mut data_transfer: Transfer<_, _, PeripheralToMemory, _> =-            Transfer::init(-                data_stream,-                spi,-                // Note(unsafe): The ADC0_BUF0 is "owned" by this peripheral. It shall not be used-                // anywhere else in the module.-                unsafe { &mut ADC0_BUF0 },-                None,-                data_config,-            );--        data_transfer.start(|spi| {-            // Allow the SPI FIFOs to operate using only DMA data channels.-            spi.enable_dma_rx();-            spi.enable_dma_tx();--            // Enable SPI and start it in infinite transaction mode.-            spi.inner().cr1.modify(|_, w| w.spe().set_bit());-            spi.inner().cr1.modify(|_, w| w.cstart().started());-        });--        trigger_transfer.start(|_| {});--        Self {-            // Note(unsafe): The ADC0_BUF1 is "owned" by this peripheral. It shall not be used-            // anywhere else in the module.-            next_buffer: unsafe { Some(&mut ADC0_BUF1) },-            transfer: data_transfer,-            _trigger_transfer: trigger_transfer,+static mut ADC_BUF: [[[u16; SAMPLE_BUFFER_SIZE]; 2]; 2] =+    [[[0; SAMPLE_BUFFER_SIZE]; 2]; 2];

It doesn't work.

jordens

comment created time in 3 hours

issue commentquartiq/phaser

Interpolation filter initialization

@jordens currently we're seeing quit a bit of non-reproducible behaviour. We have also been swapping Kasli bitstreams around (both debugging issues with why our bitstreams weren't working and changing clocking options on Kasli to debug noise issues). Having to get into a dance of restarting Kasli and reloading phaser until things behave as expected is quite a time sink. It also means that if things happen that we don't expect, it's hard to understand if we're doing something silly or if phaser just didn't initialise correctly without going through a few reset cycles.

Annoyingly vivado is playing up and refusing to recognise the hardware on the computer we're using. This is not directly an issue with phaser, but it is annoying that we need to have a programmer hooked up to allow us to do the reloading dance even though we're not changing phaser bit streams. Having the I2C tool working would at least make this process easier at our end (we're using a kasli 1.1 so no 2.0 support needed atm).

jordens

comment created time in 3 hours

pull request commentdlang/dmd

Fix issue 14188 - implement makefile compatible dependency file

Thanks for your pull request and interest in making D better, @rtbo! We are looking forward to reviewing it, and you should be hearing from a maintainer soon. Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#12011"
rtbo

comment created time in 3 hours

PR opened dlang/dmd

Reviewers
Fix issue 14188 - implement makefile compatible dependency file

This PR fixes issue 14188 to allow emitting makefile compatible dependency file and enable proper D builds with ninja. I am aware #6961 and #11357. IMO #6961 is too complex, introducing many switches and stales for nearly two years. This one is closer in spirit to #11137, but with simpler and more efficient implementation. In particular, it follows advice given by @rainers to not use the same semantics than the current -deps switch, which do much more than collecting depending modules (it triggers additional semantic pass).

Only one switch is introduced: -makefiledeps, which can take an optional filename argument. if filename is omitted, dependencies are printed to stdout.

I collect module dependencies in dmodule.Module.read. I collect in addition imported files (with the -J switch) in the expression semantics visitor. Nothing else is collected or analysed, compilation time should not be affected more than strictly necessary.

I've tested this to work with Ninja.

+283 -0

0 comment

6 changed files

pr created time in 3 hours

push eventNetHack/NetHack

PatR

commit sha df8e2dcd74e29519a85f7cada470115730cfe809

-Wshadow fix Not caused by a hidden macro this time... |mon.c:1549:10: warning: declaration shadows a variable in the | global scope [-Wshadow] | long flags = 0L; | ^ |../include/flag.h:392:29: note: previous declaration is here |extern NEARDATA struct flag flags;

view details

Pasi Kallinen

commit sha f2218839a329ca4f5406a8c845b480d933a9b54c

Move some function names to start of line

view details

Pasi Kallinen

commit sha 74565c890db2d13560dc91bd705bd2b4e5c5cff0

Split readobjnam into multiple functions Also add several new tests for it

view details

PatR

commit sha 69dd0485fb3b61bc0a642a75237a652873eadfa4

Qt message window: horizontal scrolling Multiple stints of flailing about without a clue finally led to a breakthrough. When writing a new message to the multi-line message window, force the view back to showing the starts of lines if player has scrolled it to the side and left it that way. Put another way, if it has been scrolled to the right, scroll it as far as possible back to the left.

view details

nhmall

commit sha 071b126c1d9e27aecdfdaa874704244813b7486a

Merge branch 'NetHack-3.7' into travis_test

view details

push time in 3 hours

push eventazonenberg/scopehal

Andrew D. Zonenberg

commit sha 1e7ba074cfd07cb68e40c5ac67eea311e5b367bb

EmphasisRemovalFilter: added pre-emphasis support

view details

push time in 3 hours

Pull request review commentquartiq/stabilizer

Feature/adc dac io macros

 static mut SPI_START: [u16; 1] = [0x00]; // The following global buffers are used for the ADC sample DMA transfers. Two buffers are used for // each transfer in a ping-pong buffer configuration (one is being acquired while the other is being // processed). Note that the contents of AXI SRAM is uninitialized, so the buffer contents on-// startup are undefined.+// startup are undefined. The dimension are `ADC_BUF[adc_index][ping_pong_index][sample_index]`. #[link_section = ".axisram.buffers"]-static mut ADC0_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC0_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut ADC1_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--/// SPI2 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI2 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI2 {-    _channel: sampling_timer::tim2::Channel1,-}-impl SPI2 {-    pub fn new(_channel: sampling_timer::tim2::Channel1) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 1 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI2 {-    /// SPI2 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI2 DMA requests are generated whenever TIM2 CH1 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH1 as u8);--    /// Whenever the DMA request occurs, it should write into SPI2's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI2 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI2::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// SPI3 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI3 TX FIFO-/// whenever the tim2 update dma request occurs.-struct SPI3 {-    _channel: sampling_timer::tim2::Channel2,-}-impl SPI3 {-    pub fn new(_channel: sampling_timer::tim2::Channel2) -> Self {-        Self { _channel }-    }-}--// Note(unsafe): This structure is only safe to instantiate once. The DMA request is hard-coded and-// may only be used if ownership of the timer2 channel 2 compare channel is assured, which is-// ensured by maintaining ownership of the channel.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI3 {-    /// SPI3 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI3 DMA requests are generated whenever TIM2 CH2 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH2 as u8);--    /// Whenever the DMA request occurs, it should write into SPI3's TX FIFO to start a DMA-    /// transfer.-    fn address(&self) -> u32 {-        // Note(unsafe): It is assumed that SPI3 is owned by another DMA transfer and this DMA is-        // only used for the transmit-half of DMA.-        let regs = unsafe { &*hal::stm32::SPI3::ptr() };-        &regs.txdr as *const _ as u32-    }-}--/// Represents both ADC input channels.-pub struct AdcInputs {-    adc0: Adc0Input,-    adc1: Adc1Input,-}--impl AdcInputs {-    /// Construct the ADC inputs.-    pub fn new(adc0: Adc0Input, adc1: Adc1Input) -> Self {-        Self { adc0, adc1 }-    }--    /// Interrupt handler to handle when the sample collection DMA transfer completes.-    ///-    /// # Returns-    /// (adc0, adc1) where adcN is a reference to the collected ADC samples. Two array references-    /// are returned - one for each ADC sample stream.-    pub fn transfer_complete_handler(-        &mut self,-    ) -> (&[u16; SAMPLE_BUFFER_SIZE], &[u16; SAMPLE_BUFFER_SIZE]) {-        let adc0_buffer = self.adc0.transfer_complete_handler();-        let adc1_buffer = self.adc1.transfer_complete_handler();-        (adc0_buffer, adc1_buffer)-    }-}--/// Represents data associated with ADC0.-pub struct Adc0Input {-    next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,-    transfer: Transfer<-        hal::dma::dma::Stream1<hal::stm32::DMA1>,-        hal::spi::Spi<hal::stm32::SPI2, hal::spi::Disabled, u16>,-        PeripheralToMemory,-        &'static mut [u16; SAMPLE_BUFFER_SIZE],-    >,-    _trigger_transfer: Transfer<-        hal::dma::dma::Stream0<hal::stm32::DMA1>,-        SPI2,-        MemoryToPeripheral,-        &'static mut [u16; 1],-    >,-}--impl Adc0Input {-    /// Construct the ADC0 input channel.-    ///-    /// # Args-    /// * `spi` - The SPI interface used to communicate with the ADC.-    /// * `trigger_stream` - The DMA stream used to trigger each ADC transfer by writing a word into-    ///   the SPI TX FIFO.-    /// * `data_stream` - The DMA stream used to read samples received over SPI into a data buffer.-    /// * `_trigger_channel` - The ADC sampling timer output compare channel for read triggers.-    pub fn new(-        spi: hal::spi::Spi<hal::stm32::SPI2, hal::spi::Enabled, u16>,-        trigger_stream: hal::dma::dma::Stream0<hal::stm32::DMA1>,-        data_stream: hal::dma::dma::Stream1<hal::stm32::DMA1>,-        trigger_channel: sampling_timer::tim2::Channel1,-    ) -> Self {-        // Generate DMA events when an output compare of the timer hitting zero (timer roll over)-        // occurs.-        trigger_channel.listen_dma();-        trigger_channel.to_output_compare(0);--        // The trigger stream constantly writes to the TX FIFO using a static word (dont-care-        // contents). Thus, neither the memory or peripheral address ever change. This is run in-        // circular mode to be completed at every DMA request.-        let trigger_config = DmaConfig::default()-            .priority(Priority::High)-            .circular_buffer(true);--        // Construct the trigger stream to write from memory to the peripheral.-        let mut trigger_transfer: Transfer<_, _, MemoryToPeripheral, _> =-            Transfer::init(-                trigger_stream,-                SPI2::new(trigger_channel),-                // Note(unsafe): Because this is a Memory->Peripheral transfer, this data is never-                // actually modified. It technically only needs to be immutably borrowed, but the-                // current HAL API only supports mutable borrows.-                unsafe { &mut SPI_START },-                None,-                trigger_config,-            );--        // The data stream constantly reads from the SPI RX FIFO into a RAM buffer. The peripheral-        // stalls reads of the SPI RX FIFO until data is available, so the DMA transfer completes-        // after the requested number of samples have been collected. Note that only ADC1's data-        // stream is used to trigger a transfer completion interrupt.-        let data_config = DmaConfig::default()-            .memory_increment(true)-            .priority(Priority::VeryHigh);--        // A SPI peripheral error interrupt is used to determine if the RX FIFO overflows. This-        // indicates that samples were dropped due to excessive processing time in the main-        // application (e.g. a second DMA transfer completes before the first was done with-        // processing). This is used as a flow control indicator to guarantee that no ADC samples-        // are lost.-        let mut spi = spi.disable();-        spi.listen(hal::spi::Event::Error);--        // The data transfer is always a transfer of data from the peripheral to a RAM buffer.-        let mut data_transfer: Transfer<_, _, PeripheralToMemory, _> =-            Transfer::init(-                data_stream,-                spi,-                // Note(unsafe): The ADC0_BUF0 is "owned" by this peripheral. It shall not be used-                // anywhere else in the module.-                unsafe { &mut ADC0_BUF0 },-                None,-                data_config,-            );--        data_transfer.start(|spi| {-            // Allow the SPI FIFOs to operate using only DMA data channels.-            spi.enable_dma_rx();-            spi.enable_dma_tx();--            // Enable SPI and start it in infinite transaction mode.-            spi.inner().cr1.modify(|_, w| w.spe().set_bit());-            spi.inner().cr1.modify(|_, w| w.cstart().started());-        });--        trigger_transfer.start(|_| {});--        Self {-            // Note(unsafe): The ADC0_BUF1 is "owned" by this peripheral. It shall not be used-            // anywhere else in the module.-            next_buffer: unsafe { Some(&mut ADC0_BUF1) },-            transfer: data_transfer,-            _trigger_transfer: trigger_transfer,+static mut ADC_BUF: [[[u16; SAMPLE_BUFFER_SIZE]; 2]; 2] =+    [[[0; SAMPLE_BUFFER_SIZE]; 2]; 2];

Sure. This is just using the same style as before.

jordens

comment created time in 3 hours

Pull request review commentquartiq/stabilizer

Feature/adc dac io macros

 use super::{ // The following global buffers are used for the DAC code DMA transfers. Two buffers are used for // each transfer in a ping-pong buffer configuration (one is being prepared while the other is being // processed). Note that the contents of AXI SRAM is uninitialized, so the buffer contents on-// startup are undefined.+// startup are undefined. The dimension are `ADC_BUF[adc_index][ping_pong_index][sample_index]`. #[link_section = ".axisram.buffers"]-static mut DAC0_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut DAC0_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut DAC1_BUF0: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--#[link_section = ".axisram.buffers"]-static mut DAC1_BUF1: [u16; SAMPLE_BUFFER_SIZE] = [0; SAMPLE_BUFFER_SIZE];--/// SPI4 is used as a type for indicating a DMA transfer into the SPI4 TX FIFO-struct SPI4 {-    spi: hal::spi::Spi<hal::stm32::SPI4, hal::spi::Disabled, u16>,-    _channel: sampling_timer::tim2::Channel3,-}--impl SPI4 {-    pub fn new(-        _channel: sampling_timer::tim2::Channel3,-        spi: hal::spi::Spi<hal::stm32::SPI4, hal::spi::Disabled, u16>,-    ) -> Self {-        Self { _channel, spi }-    }-}--// Note(unsafe): This is safe because the DMA request line is logically owned by this module.-// Additionally, the SPI is owned by this structure and is known to be configured for u16 word-// sizes.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI4 {-    /// SPI2 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI4 DMA requests are generated whenever TIM2 CH3 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH3 as u8);--    /// Whenever the DMA request occurs, it should write into SPI4's TX FIFO.-    fn address(&self) -> u32 {-        &self.spi.inner().txdr as *const _ as u32-    }-}--/// SPI5 is used as a ZST (zero-sized type) for indicating a DMA transfer into the SPI5 TX FIFO-struct SPI5 {-    _channel: sampling_timer::tim2::Channel4,-    spi: hal::spi::Spi<hal::stm32::SPI5, hal::spi::Disabled, u16>,-}--impl SPI5 {-    pub fn new(-        _channel: sampling_timer::tim2::Channel4,-        spi: hal::spi::Spi<hal::stm32::SPI5, hal::spi::Disabled, u16>,-    ) -> Self {-        Self { _channel, spi }-    }-}--// Note(unsafe): This is safe because the DMA request line is logically owned by this module.-// Additionally, the SPI is owned by this structure and is known to be configured for u16 word-// sizes.-unsafe impl TargetAddress<MemoryToPeripheral> for SPI5 {-    /// SPI5 is configured to operate using 16-bit transfer words.-    type MemSize = u16;--    /// SPI5 DMA requests are generated whenever TIM2 CH4 comparison occurs.-    const REQUEST_LINE: Option<u8> = Some(DMAReq::TIM2_CH4 as u8);--    /// Whenever the DMA request occurs, it should write into SPI5's TX FIFO-    fn address(&self) -> u32 {-        &self.spi.inner().txdr as *const _ as u32-    }-}--/// Represents both DAC output channels.-pub struct DacOutputs {-    dac0: Dac0Output,-    dac1: Dac1Output,-}--impl DacOutputs {-    /// Construct the DAC outputs.-    pub fn new(dac0: Dac0Output, dac1: Dac1Output) -> Self {-        Self { dac0, dac1 }-    }--    /// Borrow the next DAC output buffers to populate the DAC output codes in-place.-    ///-    /// # Returns-    /// (dac0, dac1) where each value is a mutable reference to the output code array for DAC0 and-    /// DAC1 respectively.-    pub fn prepare_data(-        &mut self,-    ) -> (-        &mut [u16; SAMPLE_BUFFER_SIZE],-        &mut [u16; SAMPLE_BUFFER_SIZE],-    ) {-        (self.dac0.prepare_buffer(), self.dac1.prepare_buffer())-    }--    /// Enqueue the next DAC output codes for transmission.-    ///-    /// # Note-    /// It is assumed that data was populated using `prepare_data()` before this function is-    /// called.-    pub fn commit_data(&mut self) {-        self.dac0.commit_buffer();-        self.dac1.commit_buffer();-    }-}--/// Represents data associated with DAC0.-pub struct Dac0Output {-    next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,-    // Note: SPI TX functionality may not be used from this structure to ensure safety with DMA.-    transfer: Transfer<-        hal::dma::dma::Stream4<hal::stm32::DMA1>,-        SPI4,-        MemoryToPeripheral,-        &'static mut [u16; SAMPLE_BUFFER_SIZE],-    >,-    first_transfer: bool,-}--impl Dac0Output {-    /// Construct the DAC0 output channel.-    ///-    /// # Args-    /// * `spi` - The SPI interface used to communicate with the ADC.-    /// * `stream` - The DMA stream used to write DAC codes over SPI.-    /// * `trigger_channel` - The sampling timer output compare channel for update triggers.-    pub fn new(-        spi: hal::spi::Spi<hal::stm32::SPI4, hal::spi::Enabled, u16>,-        stream: hal::dma::dma::Stream4<hal::stm32::DMA1>,-        trigger_channel: sampling_timer::tim2::Channel3,-    ) -> Self {-        // Generate DMA events when an output compare of the timer hitting zero (timer roll over)-        // occurs.-        trigger_channel.listen_dma();-        trigger_channel.to_output_compare(0);--        // The stream constantly writes to the TX FIFO to write new update codes.-        let trigger_config = DmaConfig::default()-            .memory_increment(true)-            .peripheral_increment(false);--        // Listen for any potential SPI error signals, which may indicate that we are not generating-        // update codes.-        let mut spi = spi.disable();-        spi.listen(hal::spi::Event::Error);--        // Allow the SPI FIFOs to operate using only DMA data channels.-        spi.enable_dma_tx();--        // Enable SPI and start it in infinite transaction mode.-        spi.inner().cr1.modify(|_, w| w.spe().set_bit());-        spi.inner().cr1.modify(|_, w| w.cstart().started());--        // Construct the trigger stream to write from memory to the peripheral.-        let transfer: Transfer<_, _, MemoryToPeripheral, _> = Transfer::init(-            stream,-            SPI4::new(trigger_channel, spi),-            // Note(unsafe): This buffer is only used once and provided for the DMA transfer.-            unsafe { &mut DAC0_BUF0 },-            None,-            trigger_config,-        );--        Self {-            transfer,-            // Note(unsafe): This buffer is only used once and provided for the next DMA transfer.-            next_buffer: unsafe { Some(&mut DAC0_BUF1) },-            first_transfer: true,+static mut DAC_BUF: [[[u16; SAMPLE_BUFFER_SIZE]; 2]; 2] =+    [[[0; SAMPLE_BUFFER_SIZE]; 2]; 2];++macro_rules! dac_output {+    ($name:ident, $index:literal, $data_stream:ident,+     $spi:ident, $trigger_channel:ident, $dma_req:ident) => {+        /// $spi is used as a type for indicating a DMA transfer into the SPI TX FIFO+        struct $spi {+            spi: hal::spi::Spi<hal::stm32::$spi, hal::spi::Disabled, u16>,+            _channel: sampling_timer::tim2::$trigger_channel,         }-    } -    /// Mutably borrow the next output buffer to populate it with DAC codes.-    pub fn prepare_buffer(&mut self) -> &mut [u16; SAMPLE_BUFFER_SIZE] {-        self.next_buffer.as_mut().unwrap()-    }--    /// Enqueue the next buffer for transmission to the DAC.-    ///-    /// # Args-    /// * `data` - The next data to write to the DAC.-    pub fn commit_buffer(&mut self) {-        let next_buffer = self.next_buffer.take().unwrap();--        // If the last transfer was not complete, we didn't write all our previous DAC codes.-        // Wait for all the DAC codes to get written as well.-        if self.first_transfer {-            self.first_transfer = false-        } else {-            // Note: If a device hangs up, check that this conditional is passing correctly, as-            // there is no time-out checks here in the interest of execution speed.-            while self.transfer.get_transfer_complete_flag() == false {}+        impl $spi {+            pub fn new(+                _channel: sampling_timer::tim2::$trigger_channel,+                spi: hal::spi::Spi<hal::stm32::$spi, hal::spi::Disabled, u16>,+            ) -> Self {+                Self { _channel, spi }+            }         } -        // Start the next transfer.-        self.transfer.clear_interrupts();-        let (prev_buffer, _) =-            self.transfer.next_transfer(next_buffer).unwrap();--        self.next_buffer.replace(prev_buffer);-    }-}--/// Represents the data output stream from DAC1.-pub struct Dac1Output {-    next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,-    transfer: Transfer<-        hal::dma::dma::Stream5<hal::stm32::DMA1>,-        SPI5,-        MemoryToPeripheral,-        &'static mut [u16; SAMPLE_BUFFER_SIZE],-    >,-    first_transfer: bool,-}--impl Dac1Output {-    /// Construct a new DAC1 output data stream.-    ///-    /// # Args-    /// * `spi` - The SPI interface connected to DAC1.-    /// * `stream` - The DMA stream used to write DAC codes the SPI TX FIFO.-    /// * `trigger_channel` - The timer channel used to generate DMA requests for DAC updates.-    pub fn new(-        spi: hal::spi::Spi<hal::stm32::SPI5, hal::spi::Enabled, u16>,-        stream: hal::dma::dma::Stream5<hal::stm32::DMA1>,-        trigger_channel: sampling_timer::tim2::Channel4,-    ) -> Self {-        // Generate DMA events when an output compare of the timer hitting zero (timer roll over)-        // occurs.-        trigger_channel.listen_dma();-        trigger_channel.to_output_compare(0);--        // The trigger stream constantly writes to the TX FIFO to generate DAC updates.-        let trigger_config = DmaConfig::default()-            .memory_increment(true)-            .peripheral_increment(false)-            .circular_buffer(true);--        // Listen for any SPI errors, as this may indicate that we are not generating updates on the-        // DAC.-        let mut spi = spi.disable();-        spi.listen(hal::spi::Event::Error);--        // Allow the SPI FIFOs to operate using only DMA data channels.-        spi.enable_dma_tx();+        // Note(unsafe): This is safe because the DMA request line is logically owned by this module.+        // Additionally, the SPI is owned by this structure and is known to be configured for u16 word+        // sizes.+        unsafe impl TargetAddress<MemoryToPeripheral> for $spi {+            /// SPI is configured to operate using 16-bit transfer words.+            type MemSize = u16; -        // Enable SPI and start it in infinite transaction mode.-        spi.inner().cr1.modify(|_, w| w.spe().set_bit());-        spi.inner().cr1.modify(|_, w| w.cstart().started());+            /// SPI DMA requests are generated whenever TIM2 CHx ($dma_req) comparison occurs.+            const REQUEST_LINE: Option<u8> = Some(DMAReq::$dma_req as u8); -        // Construct the stream to write from memory to the peripheral.-        let transfer: Transfer<_, _, MemoryToPeripheral, _> = Transfer::init(-            stream,-            SPI5::new(trigger_channel, spi),-            // Note(unsafe): This buffer is only used once and provided to the transfer.-            unsafe { &mut DAC1_BUF0 },-            None,-            trigger_config,-        );--        Self {-            // Note(unsafe): This buffer is only used once and provided for the next DMA transfer.-            next_buffer: unsafe { Some(&mut DAC1_BUF1) },-            transfer,-            first_transfer: true,+            /// Whenever the DMA request occurs, it should write into SPI's TX FIFO.+            fn address(&self) -> u32 {+                &self.spi.inner().txdr as *const _ as u32+            }         }-    }--    /// Mutably borrow the next output buffer to populate it with DAC codes.-    pub fn prepare_buffer(&mut self) -> &mut [u16; SAMPLE_BUFFER_SIZE] {-        self.next_buffer.as_mut().unwrap()-    }--    /// Enqueue the next buffer for transmission to the DAC.-    ///-    /// # Args-    /// * `data` - The next data to write to the DAC.-    pub fn commit_buffer(&mut self) {-        let next_buffer = self.next_buffer.take().unwrap(); -        // If the last transfer was not complete, we didn't write all our previous DAC codes.-        // Wait for all the DAC codes to get written as well.-        if self.first_transfer {-            self.first_transfer = false-        } else {-            // Note: If a device hangs up, check that this conditional is passing correctly, as-            // there is no time-out checks here in the interest of execution speed.-            while self.transfer.get_transfer_complete_flag() == false {}+        /// Represents data associated with DAC.+        pub struct $name {+            next_buffer: Option<&'static mut [u16; SAMPLE_BUFFER_SIZE]>,+            // Note: SPI TX functionality may not be used from this structure to ensure safety with DMA.+            transfer: Transfer<+                hal::dma::dma::$data_stream<hal::stm32::DMA1>,+                $spi,+                MemoryToPeripheral,+                &'static mut [u16; SAMPLE_BUFFER_SIZE],+            >,+            first_transfer: bool,         } -        // Start the next transfer.-        self.transfer.clear_interrupts();-        let (prev_buffer, _) =-            self.transfer.next_transfer(next_buffer).unwrap();--        self.next_buffer.replace(prev_buffer);-    }+        impl $name {+            /// Construct the DAC output channel.+            ///+            /// # Args+            /// * `spi` - The SPI interface used to communicate with the ADC.+            /// * `stream` - The DMA stream used to write DAC codes over SPI.+            /// * `trigger_channel` - The sampling timer output compare channel for update triggers.+            pub fn new(+                spi: hal::spi::Spi<hal::stm32::$spi, hal::spi::Enabled, u16>,+                stream: hal::dma::dma::$data_stream<hal::stm32::DMA1>,+                trigger_channel: sampling_timer::tim2::$trigger_channel,+            ) -> Self {+                // Generate DMA events when an output compare of the timer hitting zero (timer roll over)+                // occurs.+                trigger_channel.listen_dma();+                trigger_channel.to_output_compare(0);++                // The stream constantly writes to the TX FIFO to write new update codes.+                let trigger_config = DmaConfig::default()+                    .memory_increment(true)+                    .peripheral_increment(false);++                // Listen for any potential SPI error signals, which may indicate that we are not generating+                // update codes.+                let mut spi = spi.disable();+                spi.listen(hal::spi::Event::Error);++                // Allow the SPI FIFOs to operate using only DMA data channels.+                spi.enable_dma_tx();++                // Enable SPI and start it in infinite transaction mode.+                spi.inner().cr1.modify(|_, w| w.spe().set_bit());+                spi.inner().cr1.modify(|_, w| w.cstart().started());++                // Construct the trigger stream to write from memory to the peripheral.+                let transfer: Transfer<_, _, MemoryToPeripheral, _> =+                    Transfer::init(+                        stream,+                        $spi::new(trigger_channel, spi),+                        // Note(unsafe): This buffer is only used once and provided for the DMA transfer.+                        unsafe { &mut DAC_BUF[$index][0] },+                        None,+                        trigger_config,+                    );++                Self {+                    transfer,+                    // Note(unsafe): This buffer is only used once and provided for the next DMA transfer.+                    next_buffer: unsafe { Some(&mut DAC_BUF[$index][1]) },+                    first_transfer: true,+                }+            }++            /// Acquire the next output buffer to populate it with DAC codes.+            pub fn acquire_buffer(+                &mut self,+            ) -> &'static mut [u16; SAMPLE_BUFFER_SIZE] {+                self.next_buffer.take().unwrap()+            }++            /// Enqueue the next buffer for transmission to the DAC.+            ///+            /// # Args+            /// * `data` - The next data to write to the DAC.+            pub fn release_buffer(+                &mut self,+                next_buffer: &'static mut [u16; SAMPLE_BUFFER_SIZE],+            ) {+                // If the last transfer was not complete, we didn't write all our previous DAC codes.+                // Wait for all the DAC codes to get written as well.+                if self.first_transfer {+                    self.first_transfer = false+                } else {+                    // Note: If a device hangs up, check that this conditional is passing correctly, as+                    // there is no time-out checks here in the interest of execution speed.+                    while !self.transfer.get_transfer_complete_flag() {}+                }++                // Start the next transfer.+                self.transfer.clear_interrupts();+                let (prev_buffer, _) =+                    self.transfer.next_transfer(next_buffer).unwrap();++                // .unwrap_none() https://github.com/rust-lang/rust/issues/62633+                self.next_buffer.replace(prev_buffer);

There wasn't any documentation. This makes it clear that we are expecting a None in return by design. And we can enforce it once that is stabilized.

jordens

comment created time in 3 hours

issue commentsinara-hw/meta

[RFC] ASICs for Sinara / ARTIQ

I wrote up a document to summarize the idea and requirements. This is a very early draft, so any feedback appreciated. cheko_wp.pdf

gkasprow

comment created time in 4 hours

issue openedquartiq/stabilizer

First DAC output code may not be synchronized with the sampling timer

The very first output code when scheduling a set of DAC output codes may not occur at the timer roll-over event. Instead, the first sample will be generated immediately when the samples are scheduled. It will then stay active until the next roll-over and the second code will be generated.

This is likely caused by the DMA request being asserted before the transfer is started. Thus, immediately after the stream is enabled, the request is handled (as opposed to waiting for the next compare event to generate a request).

To resolve this, we will need to ensure that there is no pending DMA request for the channel before enabling the output stream or we will need to ensure that we are scheduling DAC outputs at the sample timer rollover point.

DS4_QuickPrint13

In the above image, CH4 indicates when ADC and DAC DMA transfers are swapped (first pulse is ADC, second is DAC). CH1 is the DAC0 output and CH2 is DAC0. The sample timer rate can be seen to be the distinct, regular transitions in the outputs. Immediately at the DAC DMA update, it can be seen that a spuriously short DAC output code is generated as a result of this bug.

created time in 4 hours

issue commentm-labs/artiq

DMA: Increase buffer size

Looks like a simple out-of-memory error. The memory layout is currently less than optimal for the amount of SDRAM we have, so we should be able to get much larger DMA buffers. A number of things would need tweaking, including:

  • runtime linker script artiq/artiq/firmware/runtime/runtime.ld
  • kernel support code linker script artiq/artiq/firmware/ksupport/ksupport.ld
  • kernel CPU reset vector address in artiq/artiq/gateware/amp/kernel_cpu.py
hermitdemschoenenleben

comment created time in 4 hours

issue commentm-labs/artiq

DMA: Increase buffer size

[    57.889119s]  INFO(runtime::mgmt): changing UART log level to DEBUG
[    69.124864s]  INFO(runtime::session): new connection from 192.168.0.24:37226
[    69.281113s]  INFO(runtime::kern_hwreq): resetting RTIO
panic at runtime/main.rs:278:5heap view: BUSY 0x40147000 + 0xc + 0x24 -> 0x40147030
BUSY 0x40147030 + 0xc + 0xc -> 0x40147048
BUSY 0x40147048 + 0xc + 0xc -> 0x40147060
BUSY 0x40147060 + 0xc + 0xc -> 0x40147078
BUSY 0x40147078 + 0xc + 0x18 -> 0x4014709c
BUSY 0x4014709c + 0xc + 0x24 -> 0x401470cc
BUSY 0x401470cc + 0xc + 0x1008 -> 0x401480e0
BUSY 0x401480e0 + 0xc + 0x3c -> 0x40148128
IDLE 0x40148128 + 0xc + 0xc -> 0x40148140
BUSY 0x40148140 + 0xc + 0x1008 -> 0x40149154
BUSY 0x40149154 + 0xc + 0x3c -> 0x4014919c
BUSY 0x4014919c + 0xc + 0xc -> 0x401491b4
BUSY 0x401491b4 + 0xc + 0x4008 -> 0x4014d1c8
BUSY 0x4014d1c8 + 0xc + 0x3c -> 0x4014d210
IDLE 0x4014d210 + 0xc + 0x18 -> 0x4014d234
BUSY 0x4014d234 + 0xc + 0x1008 -> 0x4014e248
BUSY 0x4014e248 + 0xc + 0x3c -> 0x4014e290
BUSY 0x4014e290 + 0xc + 0x1008 -> 0x4014f2a4
BUSY 0x4014f2a4 + 0xc + 0x3c -> 0x4014f2ec
BUSY 0x4014f2ec + 0xc + 0x24 -> 0x4014f31c
BUSY 0x4014f31c + 0xc + 0x3c -> 0x4014f364
IDLE 0x4014f364 + 0xc + 0xc0 -> 0x4014f430
BUSY 0x4014f430 + 0xc + 0x108 -> 0x4014f544
BUSY 0x4014f544 + 0xc + 0x198 -> 0x4014f6e8
BUSY 0x4014f6e8 + 0xc + 0x2004 -> 0x401516f8
IDLE 0x401516f8 + 0xc + 0x108 -> 0x4015180c
BUSY 0x4015180c + 0xc + 0x108 -> 0x40151920
BUSY 0x40151920 + 0xc + 0x108 -> 0x40151a34
IDLE 0x40151a34 + 0xc + 0x18fc -> 0x4015333c
BUSY 0x4015333c + 0xc + 0x48 -> 0x40153390
IDLE 0x40153390 + 0xc + 0x3c -> 0x401533d8
BUSY 0x401533d8 + 0xc + 0x30 -> 0x40153414
BUSY 0x40153414 + 0xc + 0x2004 -> 0x40155424
BUSY 0x40155424 + 0xc + 0x10008 -> 0x40165438
BUSY 0x40165438 + 0xc + 0x4008 -> 0x4016944c
IDLE 0x4016944c + 0xc + 0xa23c -> 0x40173694
BUSY 0x40173694 + 0xc + 0x108 -> 0x401737a8
IDLE 0x401737a8 + 0xc + 0x420c -> 0x401779c0
BUSY 0x401779c0 + 0xc + 0x804 -> 0x401781d0
BUSY 0x401781d0 + 0xc + 0x804 -> 0x401789e0
IDLE 0x401789e0 + 0xc + 0x3e4 -> 0x40178dd0
BUSY 0x40178dd0 + 0xc + 0x10008 -> 0x40188de4
BUSY 0x40188de4 + 0xc + 0x10008 -> 0x40198df8
BUSY 0x40198df8 + 0xc + 0x108 -> 0x40198f0c
BUSY 0x40198f0c + 0xc + 0x174 -> 0x4019908c
IDLE 0x4019908c + 0xc + 0x4014 -> 0x4019d0ac
BUSY 0x4019d0ac + 0xc + 0x7c8 -> 0x4019d880
BUSY 0x4019d880 + 0xc + 0x10008 -> 0x401ad894
BUSY 0x401ad894 + 0xc + 0x10008 -> 0x401bd8a8
IDLE 0x401bd8a8 + 0xc + 0x3528 -> 0x401c0ddc
BUSY 0x401c0ddc + 0xc + 0x10008 -> 0x401d0df0
IDLE 0x401d0df0 + 0xc + 0xf0024 -> 0x402c0e20
BUSY 0x402c0e20 + 0xc + 0xffff0 -> 0x403c0e1c
IDLE 0x403c0e1c + 0xc + 0x3f1d8 -> 0x0
 === busy: 0x1722f0 idle: 0x146a88 meta: 0x288 total: 0x2b9000

cannot allocate layout: Layout { size_: 2097120, align_: 1 }
backtrace for software version 5.7136.15bb0fa9;hub:
0x40043ff8
0x4002118c
0x40043dfc
0x4001b4ac
0x4001b0e8
0x4001b53c
0x40032d88
0x40025b3c
0x40024610
halting.
use `artiq_coremgmt config write -s panic_reset 1` to restart instead
hermitdemschoenenleben

comment created time in 4 hours

issue commentm-labs/artiq

Queueing events blocked

Thank you for the quick reply!

The buffer size can be increased at compilation time. Is it possible to increase this value a lot, i.e. to a few thousand? Or will this lead to problems?

Where did you get your Kasli system and do you know the variant? We have artiq-kasli-hub (kasli 1.1) and afaik we bought it from quartiq

hermitdemschoenenleben

comment created time in 5 hours

issue commentjonathan-laurent/AlphaZero.jl

LSTM support

You can look at the following comment in src/learning.jl:

# A samples collection is represented on the learning side as a (W, X, A, P, V)
# tuple. Each component is a `Float32` tensor whose last dimension corresponds
# to the sample index. Writing `n` the number of samples and `a` the total
# number of actions:
# - W (size 1×n) contains the samples weights
# - X (size …×n) contains the board representations
# - A (size a×n) contains the action masks (values are either 0 or 1)
# - P (size a×n) contains the recorded MCTS policies
# - V (size 1×n) contains the recorded values
# Note that the weight of a sample is computed as an increasing
# function of its `n` field.

Also, regarding samples weights, you can read more here: https://jonathan-laurent.github.io/AlphaZero.jl/dev/reference/params/#AlphaZero.SamplesWeighingPolicy.

deveshjawla

comment created time in 5 hours

more