<euphemism[m]>
<waveguide[m]> "> <@euphemism:matrix.org> More..." <- Some clarifications: I'm hoping to use an RP2040 as my host, as I will be attempting to take advantage of https://github.com/Wren6991/PicoDVI to simplify my BOM. I don't know if the full 1.5 MB/s would be saturated or not. There's a 16bit, 44.1kHz stereo audio stream which I guess would be something like `0.1764` MB/s, and then a currently unknown amount of serial data which
<euphemism[m]>
contains information for drawing a screen.
<euphemism[m]>
> <@waveguide:matrix.org> Maybe an nrf7002 over QSPI to an m7 core? Bridging 12Mbps will be time consuming without significant care
<euphemism[m]>
* Some clarifications: I'm hoping to use an RP2040 as my host, as I will be attempting to take advantage of https://github.com/Wren6991/PicoDVI to simplify my BOM. I don't know if the full `1.5 MB/s` would be saturated or not. There's a `16bit`, `44.1kHz` stereo audio stream which I guess would be something like `0.1764 MB/s`, and then a currently unknown amount of serial data which contains information for drawing a screen.
<euphemism[m]>
Could you clarify what you mean by
<euphemism[m]>
> Bridging 12Mbps will be time consuming without significant care
<euphemism[m]>
* Some clarifications: I'm hoping to use an RP2040 as my host, as I will be attempting to take advantage of https://github.com/Wren6991/PicoDVI to simplify my BOM. I don't know if the full 1.5 MB/s would be saturated or not. There's a 16bit, 44.1kHz stereo audio stream which I guess would be something like 0.1764 MB/s, and then a currently unknown amount of serial data which contains information for drawing a screen (at
<euphemism[m]>
60 FPS).
<M9names[m]>
sounds ambitious, to say the least. what sort of serial data are you thinking of for your video data?
notgull has quit [Ping timeout: 240 seconds]
notgull has joined #rust-embedded
<euphemism[m]>
<M9names[m]> "sounds ambitious, to say the..." <- Not My Data™. It's a series of commands to draw characters and rectangles at a number of positions. Will try to do some testing with the device to see what the actual bounds are on the serial bitrate.
<euphemism[m]>
Might just accept that an ever-shrinking part of this project will involve Rust. Found a new devkit for the NRF7002 @ $36.00 so I'll just pick that up and see where I end up.
<euphemism[m]>
Oh. Someone just bought it. Okay.
<GrantM11235[m]>
Are you building a wireless KVM or something?
<euphemism[m]>
🤔 Kinda, I guess. The dream is a little, battery-powered hat on the device, and a streaming-stick-esque dongle poking out of a TV.
<euphemism[m]>
But with a focus on low latency as that is important for peak enjoyment.
<korken89[m]>
<dirbaio[m]> "try passing linker args from..." <- Neat trick, I'll give it a try!
<korken89[m]>
korken89[m]: Do you know how to make a `"-C", "linker=flip-link",` work in this kind of setup as well?
<korken89[m]>
korken89[m]: `println!("cargo:rustc-linker-bins=flip-link");` follows the pattern, but not sure 😅
zupink0re has joined #rust-embedded
baiko0x has joined #rust-embedded
zupink0re has quit [Ping timeout: 252 seconds]
baiko0x has quit [Ping timeout: 246 seconds]
zupink0re has joined #rust-embedded
<MathiasKoch[m]>
<JamesMunns[m]> "(that's why its marked ..." <- Hmm, couldn't quite shake this, so i'd just bring some more possibly relevant info to the table.
<MathiasKoch[m]>
It seems to work for serde_cbor, which i would expect to have the same underlying identifier issue from a binary format, of only storing the variant identifier?
<JamesMunns[m]>
cbor is self describing, iirc
<JamesMunns[m]>
Postcard doesn't send field name/identifiers, while cbor is closer to "binary json"
<MathiasKoch[m]>
ahh.. Fair enough point
<JamesMunns[m]>
The issue is self describing vs non self describing formats, not binary vs text/human readable
<MathiasKoch[m]>
gotcha 👍️
<JamesMunns[m]>
Part of the reason postcard is so efficient (and fragile in some ways) is it just spits out "value value value value" on the wire, assuming both sides agree 100% on the ordering and meaning, while self describing formats spit out "key:value key:value key:value"
<JamesMunns[m]>
Which is wasteful if you do 100% agree, but is very useful if you potentially or definitely dont
<JamesMunns[m]>
Or in some cases even "key:type:value...", which json and I think cbor do
<JamesMunns[m]>
`{ "key": 1234 }` has a lot of implicit type information! We know it's a dict, with a string key and a numerical value!
<JamesMunns[m]>
Whereas postcard would just send essentially just send `0x03 b"key" 0xd2 0x04" on the wire
<JamesMunns[m]>
s/"/`/
<JamesMunns[m]>
So only 6 bytes, very efficient!, but if you don't know how to decode it you're in trouble
lulf[m] has joined #rust-embedded
<lulf[m]>
A general rule I tend to use is: If you need to change the schema at different points in time for endpoint 'A' and 'B', or you need to store the data, use self-describing formats and/or at least version + a registry to lookup schema
<JamesMunns[m]>
Or if it was a struct, e.g. struct { key: 0x04d2 } it would only send two bytes, just the integer value!
<JamesMunns[m]>
Tbh I've considered making a more flexible, self describing version of postcard, and I don't think it would be very far from cbor, honestly.
<JamesMunns[m]>
Hashmaps in postcard are encoded as basically an array of tuples, but structs are just a tuple of values
<JamesMunns[m]>
* array of tlkey/val tuples, but
<JamesMunns[m]>
* array of key/val tuples, but
<JamesMunns[m]>
* Hashmaps in postcard are encoded as basically a slice of key/val tuples, but structs are just a tuple of values
<JamesMunns[m]>
And we can see, that the serialize behavior didn't change, which means there's no identifiers on the wire to decode, so that's actually a good thing!
<JamesMunns[m]>
this is feasible in json, because serde nominally transforms structs into `HashMap<String, Any>`.
<JamesMunns[m]>
but postcard doesn't do that same transform
Darius has quit [Server closed connection]
Darius has joined #rust-embedded
<MathiasKoch[m]>
Yeah, that fits with my observations from digging through.
<MathiasKoch[m]>
Question then becomes, is there anything i can do in either serialize or deserialize to support this without breaking the json ser/de?
<MathiasKoch[m]>
I don't mind hand-rolled impls for this, but the struct itself is going through some abstractions, which means the copy-paste version without tag & content, combined with `From/Into` is rather unfeasible for me :/
<JamesMunns[m]>
I don't really have any ideas, unfortunately. You essentially need two ser/de impls: one for "json mode" and one for "postcard mode", since the `tag/content` transform is invalid for "postcard mode"
<JamesMunns[m]>
And the only way to achieve that I'm aware of is by using separate types, either wrapper types SideTagged(MyType) vs Normal(MyType); or MyType1 vs. MyType2
<MathiasKoch[m]>
Yeah.. Guess ill change my binary format, which is essentially for persisting state to flash, to something with a slightly bigger overhead, but without it being json. Something like cbor :/
<MathiasKoch[m]>
Ohh.. Nevermind, i think i can do the into call in my storage layer (read/write)
Guest7221 has left #rust-embedded [Error from remote client]
Guest7221 has joined #rust-embedded
zupink0re has joined #rust-embedded
fu5ha[m] has joined #rust-embedded
<fu5ha[m]>
<euphemism[m]> "Not My Data™. It's a series of..." <- Fwiw, *just* doing this in a way that can feed a 60hz output video on an rp2040 would be a hell of a challenge, not counting anything else..
starblue has quit [Ping timeout: 240 seconds]
starblue has joined #rust-embedded
zupink0re has quit [Quit: Leaving]
IlPalazzo-ojiisa has joined #rust-embedded
<euphemism[m]>
<fu5ha[m]> "Fwiw, *just* doing this in a way..." <- Which part of this would be the bottleneck in your view?
<fu5ha[m]>
Mostly the 'drawing graphics fast enough' part, if you have a highly compressed instruction set input over serial. It depends how much of the screen you want to change per frame. But even if you're only drawing a total of 1/8th of the screen per frame, that's still 160x120 pixels to draw.... you have a max 16ms time to do it, if you double buffer. At 252Mhz internal clock which you need for picodvi I believe, that's only (252000000
<fu5ha[m]>
/ 60) / (160 * 120) = ~200 clock cycles per pixel! In those 200 clock cycles per pixel you need to not only read serial data, but also compute what to draw and then actually write it into the next framebuffer so the other core can grab it and bang it out over dvi. Do keep in mind though that when you overclock the rp2040, you get degraded max peripheral clocks (i believe down to 12Mhz) so that would limit you even more as well. And
<fu5ha[m]>
that's not even taking into account the other stuff you want it to be doing, like passthrough input!
thejpster[m] has quit [Quit: Idle timeout reached: 172800s]
therealprof[m] has quit [Quit: Idle timeout reached: 172800s]
Noah[m] has quit [Quit: Idle timeout reached: 172800s]
vollbrecht[m] has quit [Quit: Idle timeout reached: 172800s]
<ryan-summers[m]>
Is it possible to have cortex-m-rt use two different RAM sections for data vs stack? The H7 has, like, 5 discontinuous sections, and I'm going to need a pretty large stack. I figured it would make the most sense to link .data and stack into separate sections, since that helps with memory safety anyways
sourcebox[m] has quit [Quit: Idle timeout reached: 172800s]
<ryan-summers[m]>
It looks like the answer is probably no without a custom linker script since cortex-m-rt defines the stack symbol etc. using the RAM memory section
mabez[m] has joined #rust-embedded
<mabez[m]>
ryan-summers[m]: I think you'd need to copy and modify link.x from cortex-m-rt crate, the default one puts all those section in the same `RAM` memory segment
<ryan-summers[m]>
Can you just keep a local copy in your repo and it'll pick that up?
<mabez[m]>
s/section/sections/
<mabez[m]>
ryan-summers[m]: Yeah, call it something different and move it to the out dir, then in `.cargo/config.toml` you can tell the linker to use your linker script instead of `link.x`
<ryan-summers[m]>
Well maybe I should read the docs before asking
<mabez[m]>
ryan-summers[m]: Ah yeah for the stack start, you can override that, if you don't mind the other sections all going into RAM
<ryan-summers[m]>
Yeah that would be fine here, I just have a random unused 512KB I want to move the stack into
<ryan-summers[m]>
Which feels like such a weird thing to say for an embedded guy
<waveguide[m]>
Do any other hals have something like a clock tree solver of sorts built in?
<waveguide[m]>
I have 3 peripherals I may want to clock well, so I have what amounts of a system of equitions that I need to do a best fit on it feels like
<euphemism[m]>
<fu5ha[m]> "Mostly the 'drawing graphics..." <- Thank you for taking the time to investigate this. A couple of things:
<euphemism[m]>
There is no input pass through; this is a one-way remote display. The resolution of the described frame being drawn is 320x240, and it’s not full frame video or anything. Mostly only small areas update at any given time, barring changes to other views. I didn’t know about the degraded peripheral performance. That’s interesting.
<dirbaio[m]>
spinfast: which chip? some stm32 hals have sort of that, where you specify target freqs and it tries to calculate best dividers, pll factors, etc
<waveguide[m]>
e.g. "audio_clock_solver(sai1_freq, sai2_freq, sai3_freq)" is a function I think I need to concoct here, and its kind of wild... as actually there's different PLLs each can mux on, followed by a whole slew of various dividers... all to in the end generate a serial audio bit clock of a particular frequency
<waveguide[m]>
imxrt10xx in this case, with 3 SAI (serial audio) peripherals
<dirbaio[m]>
with time i've come to the opinion that doing it on-firmware is a mistake though. it's complex, the compiler is bad at optimizing it out
<waveguide[m]>
yeah I wish I could write a const fn for this
<waveguide[m]>
like, here's the output frequencies I want in rust, generate the clock tree settings
<dirbaio[m]>
and on firmware you can only approximate. to get the actual best clock config you essentially need a full-blown SMT solver :P
<waveguide[m]>
though maybe this is beyond the capabilities of a const fn... we already have some build.rs stuff
<waveguide[m]>
yeaaaaaah
<waveguide[m]>
maybe I'll provide the mutators for this stuff, then set it up by hand in the board clock tree config for now... most of the imxrt evks seem to use the same codec and little speaker hooked up to the medium quality sound peripheral
<dirbaio[m]>
so it's best to calculate the config beforehand and hardcode it in the firmware
<waveguide[m]>
like this thing can do sai3 -> mqs -> micro speaker
<waveguide[m]>
which is neat I guess, no codec required
<dirbaio[m]>
perhaps with some tool. ST has stm32cubemx which is quite good for it, not sure if imxrt has something similar
<waveguide[m]>
can probably blast out some 90's quality midi vibes
<waveguide[m]>
yeah I recall cubemx's clock tree config, mcux has something similar
<waveguide[m]>
the tools are kind of dreadful in other ways though
<dirbaio[m]>
yeah 🥲
<waveguide[m]>
they really want to dump out C code
<waveguide[m]>
like, in the gui you work out the clock tree and the output is just a big blob of C for the vendor hal...
<dirbaio[m]>
user specifies a config, the hal just validates and applies it.
<dirbaio[m]>
i'm actually refactoring embassy-stm32 rcc lately to remove all on-firmware clock solving :P
<waveguide[m]>
that really does prevent clock scaling if you want that though
<waveguide[m]>
like if you wanted to drop power modes by doing a bunch of clock/power gating and down clocking
<dirbaio[m]>
not necessarily, you could have multiple configs and switch between them
<waveguide[m]>
I guess you could pre-defined the states...
<waveguide[m]>
that's kind of what mcux does, there's a predefined run and low power state I believe
<waveguide[m]>
but again those feel pretty limiting
<JamesMunns[m]>
(this is what I've always done, use the GUI tools to pick a couple of values, get the PLL config values, dump the solved P/N/M/Q/whatever values into the firmware itself)
<waveguide[m]>
for audio this is particularly annoying I'd say
<waveguide[m]>
the audio sample clock may be useful to change at runtime
<JamesMunns[m]>
but yeah, depends on how autonomous/automatic/magical you want to be. But I've always been lucky enough where one or two const configs were acceptable
<JamesMunns[m]>
but then again I don't do a lot of audio :D
<waveguide[m]>
as would the number of channels being TDMed into the audio serial stream
<waveguide[m]>
e.g. someone plugs in a microphone
<waveguide[m]>
or line out
<waveguide[m]>
or line out and speaker
<dirbaio[m]>
you can always do a "tiny" clock solver in user code for just that application
<waveguide[m]>
right
<dirbaio[m]>
the problem with doing clock solving in the HAL is there's pressure to make it handle EVERYTHING for ALL use cases, which is not feasible
<waveguide[m]>
yeah so then the HAL only provides ways to mutate and access clock tree settings and rates
<dirbaio[m]>
yep
<waveguide[m]>
up to application to maybe have a table around for various configs, makes sense
<waveguide[m]>
I like it
<waveguide[m]>
always make it an app problem not a hal problem, seems like a good mantra to repeat
<waveguide[m]>
✌️
<dirbaio[m]>
lol
<dirbaio[m]>
imo it's good to solve as much stuff in the HAL, but only as long as it's actually solveable
<dirbaio[m]>
* the HAL as possible, but
<waveguide[m]>
even providing the clock manipulation, config, and providing the current frequency is an interesting thing for this part... do the ST H7/F7 parts also have insane clock trees?
<waveguide[m]>
imxrt has like 6 plls
<dirbaio[m]>
yep, ST has up to 3 plls and tons of muxes 🙃
<JamesMunns[m]>
IMO the imxrt is definitely more complex, but the H7s get pretty close from memory
<dirbaio[m]>
H5 adds more muxes, U5 is quite insane too
<waveguide[m]>
yeah... imxrt is wildly configurable
<waveguide[m]>
want mmio accessible hyperflash/hyperram with video, audio, enet, and usb all going?
<waveguide[m]>
sure thing bos
<waveguide[m]>
* sure thing boss
<waveguide[m]>
almost feels like the only real seperation here between imxrt and imx is a ddr controller and mmu...
<JamesMunns[m]>
The datasheet isn't 4k+ pages for no reason
<waveguide[m]>
* and mmu... I mean I know its more than that... but my goodness
<JamesMunns[m]>
there's... a lot of flexibility and options in there
<waveguide[m]>
ya, the rt500/rt600 are I don't even know... those are also completely different
<waveguide[m]>
m33 + xtensa hifi + a half dozen flexcomms
<waveguide[m]>
the audio evk has like 8 trs plugs and I think fistful of dmics
<JamesMunns[m]>
(nordic, to Arm): don't worry! That new core means nothing to me! it's just for low power stuff, no threat!
<JamesMunns[m]>
waveguide[m]: yep!
<waveguide[m]>
It's gotta be tough to compete with espressif at this point
<waveguide[m]>
yeah, they don't want to lose whatever pricing deal they have
<waveguide[m]>
* they have, though maybe that's a new way to negotiate "give us a discount on arm designs or we're going all in on riscv"
<waveguide[m]>
aren't the espressif modules all fcc certified too? like for $2.50 to get wifi/ble/etc, more sram and flash, and fcc certified... what is nordic going to give me for that
<waveguide[m]>
* fcc certified, and a rust sdk... what