|
Hey, this is not exactly embedded programming, but do any of you guys have any experience doing stuff in Windows with USB? I'm interested in trying to make a Guncon3 driver for Windows as a personal project and I'd like to know if you have resources to recommend. Like I'd guess the first thing I want to do is just be able to get the raw output of the thing so I can try to work out what signals it actually sends? I just have this idea and not much sense of how to go about it. I make ASP.NET applications for a living so this is a bit of a departure from stuff I normally work on.
|
![]() |
|
![]()
|
# ? May 13, 2024 14:11 |
|
A long time ago I made a post in here about getting up and running doing AVR programming on windows. I said I would follow up at some point with a linux walkthrough. Is there interest in that still? I could write up something that goes through the various free linux command line tools, including debugging.
|
![]() |
|
RICHUNCLEPENNYBAGS posted:Hey, this is not exactly embedded programming, but do any of you guys have any experience doing stuff in Windows with USB? I'm interested in trying to make a Guncon3 driver for Windows as a personal project and I'd like to know if you have resources to recommend. Like I'd guess the first thing I want to do is just be able to get the raw output of the thing so I can try to work out what signals it actually sends? I just have this idea and not much sense of how to go about it. Wireshark on linux might support USB capture, so give that a try? There might be capture software for Windows too. There are also inline USB protocol analyzers and data loggers, but those can be expensive.
|
![]() |
|
I used USBTrace when I was working on from-scratch USB firmware for a PIC and it did a pretty good job. It's commercial though, but it looks like there are free things too.
|
![]() |
|
For the Windows development side there's this MSDN. Without any kind of documentation or existing driver to sniff it's going to be pretty difficult though.
|
![]() |
|
JawnV6 posted:For the Windows development side there's this MSDN. Without any kind of documentation or existing driver to sniff it's going to be pretty difficult though. At the very least, setting up a sniffer on a PC would let you see the device's descriptors which will tell you the endpoints and their types, which is the first step towards making a driver so that the device will enumerate properly. Once you have a stub of a driver that makes it through the enumeration process you can sniff it further to see what it tries to send to the host. I would wager that even if it doesn't enumerate as an HID, that it will work similarly with transfers over the control endpoint or a second interrupt endpoint. Edit: Not gonna say it's the easiest thing in the world especially if you've never touched USB before, but Windows handles the descriptor fetching so even without a driver you should be able to sniff everything without having to write any code. Also an input device is the easiest case to work with, it's not like we're talking mass storage here Edit 2: Actually since the Guncon3 is based on IR tracking it's possible that it sends image data over a bulk endpoint in addition to an HID-like interrupt endpoint, but that's not so bad either BattleMaster fucked around with this message at 18:36 on May 6, 2015 |
![]() |
|
armorer posted:A long time ago I made a post in here about getting up and running doing AVR programming on windows. I said I would follow up at some point with a linux walkthrough. Is there interest in that still? I could write up something that goes through the various free linux command line tools, including debugging. I think it would be great if you did. Debugging is of particular interest to me.
|
![]() |
|
Slanderer posted:Wireshark on linux might support USB capture, so give that a try? There might be capture software for Windows too. There are also inline USB protocol analyzers and data loggers, but those can be expensive. Microsoft Message Analyzer is quite good (and free) for windows USB capture. There are a few libusb ports for windows (eg libusbK) that will let you send / recieve to USB endpoints without writing a driver, which might be a good way to get started. The first step should be connecting the device and getting the descriptors to see if it's going to be a standard usb class or a completely custom thing. USBView (either the microsoft version or the improved USBTreeView - http://www.uwe-sieber.de/usbtreeview_e.html#download) is good for this.
|
![]() |
|
Aurium posted:I think it would be great if you did. Debugging is of particular interest to me. Okay, I got debugging working using avarice and gdb. You could front-end gdb with something if you want, but I won't go into that. In my write-up I'll be using an AVR Dragon, Mint 16 (out of date, should probably work on any more recent Ubuntu/Debian-based distro), and an atmega328p. The atmega328p doesn't support JTAG, so I'm using debugWire, but it should be even easier to do on an AVR chip that supports JTAG.
|
![]() |
|
Thanks for the various advice on USB, folks.
|
![]() |
|
RICHUNCLEPENNYBAGS posted:Thanks for the various advice on USB, folks. If you need a hand, post a USB capture log from plugging it in and I can take a look at the descriptors for you. I've never written drivers, just device firmware (from scratch, so even though it was hideous I learned a lot) for generic USB classes, but at the very least I know enough from that to interpret the descriptors. BattleMaster fucked around with this message at 10:15 on May 7, 2015 |
![]() |
|
BattleMaster posted:If you need a hand, post a USB capture log from plugging it in and I can take a look at the descriptors for you. I've never written drivers, just device firmware (from scratch, so even though it was hideous I learned a lot) for generic USB classes, but at the very least I know enough from that to interpret the descriptors. Thanks! This is what you're talking about, right? code:
|
![]() |
|
That's what I was hoping for, thanks. It looks pretty simple. These code:
code:
The device has one configuration, which is the typical and most simple case; when you plug in a device, the computer has to tell it which configuration it wants to use and they're mutually exclusive, but luckily we won't have to deal with this. The configuration descriptor defines one interface. An interface is a set of endpoints that perform one function. Devices with multiple interfaces are composite devices that perform multiple different functions, and again we're lucky to not have to deal with this. code:
The interface defines two endpoints. code:
Endpoint 0 is the control endpoint that already exists (it's how all of these descriptors are sent to begin with). Endpoints don't have to be sequentially-numbered, and in this device there's no Endpoint 1; it skips right to 2. Endpoints are pretty much just logical dropboxes for data that the host wants to send to the device or that the device wants to send to the host. The host initiates all communications and will say things like "hey, here's data for endpoint 2" or "send me the data in endpoint 2". Packets can be smaller than the size the descriptor says (but not bigger, obviously) and it's also valid for the endpoint to not be ready to be polled when the host asks about it, or for the device to not be ready to receive one. Endpoint 2 is set up as a bidirectional interrupt endpoint (bidirection endpoints count as two separate endpoints.) Interrupt endpoints are designed to be polled at set intervals and are prioritized. Because of this, interrupt endpoints are generally used for human interface devices like game controllers (and mice, and keyboards, etc.) because of their predictability and guaranteed data rate. Interestingly, the IN endpoint (directions are relative to the host, so IN means from the gun to the computer) has not only a much faster polling rate (4 milliseconds or 250 Hz) and a larger packet size than the OUT endpoint, at 15 bytes versus 8 bytes. I wouldn't expect to see much traffic on the OUT endpoint, so hopefully you don't need to send anything. Therefore, Endpoint 2 IN is where most of your attention will be focused, and will hopefully be all that you need to deal with in writing a driver. It's likely that one 15 byte packet contains absolutely all controller state, given the weird size of it. That should be all you need to know. I would imagine that it would be easy to set up a stub driver that opens up the endpoints and just tosses the input to /dev/null, and that the hard part is actually just properly acting on the data from the gun. If you can do that, you can use a packet sniffer on the endpoint to see what happens when you press buttons and such. Edit: I was expecting it to send image data from a camera to the host so that the host itself can do the image processing and positioning like the Wii Remote does; it may still do that, but given the lack of a bulk endpoint I think it is very unlikely as the interrupt endpoints lack the throughput for that. The control endpoint (endpoint 0) has a packet size of 8 (which is standard, but can be much higher) so I don't think it's using that for image data either (it isn't intuitive but control endpoints can be used for data, old USB 1.1 HID keyboards sent keycodes via an interrupt IN and used control OUT for toggling the keyboard's status lights). If it does do the image processing itself and only spits out the screen co-ordinate, then there might be a signal that the host needs to send to tell it to enter calibration mode. I don't have one to look at myself so I can't say for sure, but keep that in mind as you poke at it. If there is a signal to initiate calibration, then it's almost certainly going to be sent via Endpoint 2 OUT. BattleMaster fucked around with this message at 07:31 on May 8, 2015 |
![]() |
|
RICHUNCLEPENNYBAGS posted:I set up Microsoft Message Analyzer but I feel like kind of a dummy in that I can't figure out which USB traffic actually belongs to this device. But maybe that's not the right tack anyway. The best way I've found is to set a filter for the vendor / product id. In your case this would be: code:
|
![]() |
|
You guys are really helpful. Thanks again.
|
![]() |
|
I'm also working on a USB related project and had not heard of Microsoft message analyzer before, so I thought I would give it a shot. I'm trying to follow the first video on this page: https://msdn.microsoft.com/en-us/library/windows/hardware/dn741264%28v=vs.85%29.aspx I'm on windows 7, and the interface looks a little different from the video. There is no "Capture / Trace" "tab" as mentioned in the video so that's where I'm currently stuck. Am I losing my mind or is this the most incomprehensible UI produced by microsoft to date? e: Well I eventually was able to start a USB trace, but none of the devices I try plugging in show up in the log ![]() Is there something special I need to do to capture enumeration events? I only see these two devices VID/PID (I'm grouping by UsbDevice in the Analysis grid view to try to see them) VID:8087 PID:8008 VID:8087 PID:8000 Which I think are intel hubs that are built into the motherboard. ![]() peepsalot fucked around with this message at 21:45 on May 8, 2015 |
![]() |
armorer posted:A long time ago I made a post in here about getting up and running doing AVR programming on windows. I said I would follow up at some point with a linux walkthrough. Is there interest in that still? I could write up something that goes through the various free linux command line tools, including debugging. If you could writeup something on using an AVR emulator on Linux that would be cool. A guide to setting up and using simavr for instance.
|
|
![]() |
|
Popete posted:If you could writeup something on using an AVR emulator on Linux that would be cool. A guide to setting up and using simavr for instance. I will see about adding that in. I haven't had time to do the writeup yet, but I have everything prepared for it other than running an emulator. It is a pretty solid thing to add though so I'll see what I can do.
|
![]() |
|
Hey, I'll bet this is the place to talk this out: I'm working with a Cortex M3-based synth module (Patchblocks) and I'm trying to wrap my head around why my FM sounds like poo poo. The implementation uses Q10 fixed-point arithmetic on 32-bit with the following sin(): code:
code:
I have no background in math so I'm kind of over my head. I rolled my own FM block but it sounds pretty bad. I've done FM on floating point before to good result, but something is going awry here in fixed-point land: code:
Edit: fixed a bug that caused the modulation phase to be incorrect, but it doesn't solve the problem. Tan Dumplord fucked around with this message at 16:43 on May 14, 2015 |
![]() |
|
Well, implementing CORDIC sine at Q16 didn't completely eliminate the problem, but it did reduce it. Guess I'll try a LUT next, as I don't think I have any headroom to go to a higher bit depth CORDIC. Also, CORDIC uses 7 times more CPU than the built-in sin. Tan Dumplord fucked around with this message at 13:54 on May 15, 2015 |
![]() |
|
The CMSIS library provides a LUT based sin function, which you may already have in your environment. I'm on my phone, so not sure on the supported datatypes.
|
![]() |
|
Pretty basic but I thought it was still a fun project, so cross-posting:Star War Sex Parrot posted:Managed to reproduce the functionality of a TC-80N3! Sure maybe it's not as pretty....
|
![]() |
|
sund posted:The CMSIS library provides a LUT based sin function, which you may already have in your environment. I'm on my phone, so not sure on the supported datatypes. Well this saves me from debugging my 1/4 wave LUT with linear interpolation. CMSIS has Q15 and Q31 LUT sin with cubic interpolation. I didn't have CMSIS, so I got it and hacked the Q15 sin file into a header. Unfortunately, I'm still getting crackling when modulating the depth, so either there's something wrong with my math or fixed-point FM is a lost cause. I'd try the Q31, but I don't know if I'd really gain anything as I'd probably end up shifting away any of the extra resolution.
|
![]() |
|
sliderule posted:Well this saves me from debugging my 1/4 wave LUT with linear interpolation. Can you make a test that runs through a bunch of inputs and saves the output of the sin function, then plot it and see if it looks like what you would expect?
|
![]() |
|
taqueso posted:Can you make a test that runs through a bunch of inputs and saves the output of the sin function, then plot it and see if it looks like what you would expect? Yeah I'll set up a test rig with parallel fixed and floating-point implementations and see what I find.
|
![]() |
|
Well, visualizing the waveforms helped me find a few errors with one sine implementation and helped me optimize the headroom of my multiplications and eliminate precision loss, but it hasn't pointed to where the clicking is coming from. Errors between the fixed and floating point implementations don't exceed 1% at modulation depth 40, and when I modulate the depth over time, errors are proportional to the depth. Also, the error delta from sample to sample does not exceed the maximum error. Carrier phase and modulator phase accrue no error. Raw sine error < 0.025% at Q15 and < 0.11% at Q10. I've checked for clipping. Now I guess I need to generate a WAV file to check if it's just happening within the Patchblocks emulator. edit: Oh wonderful. The WAV sounds fine, so it must be a problem trying to run this algorithm live. Time to profile. Tan Dumplord fucked around with this message at 22:28 on May 17, 2015 |
![]() |
|
Well, I ported Patchblocks' sine function to the testbench, and the awful crackling appears. This gives me hope that the new implementation will work with some optimization. The crackling is coming from a bug in the sine function that returns -1 for some values near 1/2 pi. I guess it shows up with FM because there are a greater range of phases that can occur at sample time. edit: *sigh*, PB sine ranges from -1.0 to 1.0 Q12, which means that I can't << 3 to make a valid Q1.15. arm_sin_q15 clips to 0x7FFF. Tan Dumplord fucked around with this message at 00:10 on May 19, 2015 |
![]() |
|
I figured if I am going to keep building stuff with fixed-point math, I would need some tools.code:
|
![]() |
I'm over here struggling to get this CRC32 function to work properly and you're making me feel real dumb. ![]()
|
|
![]() |
|
Worry not, I'm pretty dumb myself. At this very instant I am struggling to get a simple multiplication to work in Arm ASM inline in GCC. I'm sure I'll come here and ask a really dumb question very shortly. e: or not... shaved 5 instructions off of gcc -O1, but I think I replaced thumb instructions with Arm ones. So better CPU usage, worse code size. Tan Dumplord fucked around with this message at 16:36 on May 20, 2015 |
![]() |
Popete posted:I'm over here struggling to get this CRC32 function to work properly and you're making me feel real dumb. CRCs are voodoo. Last week I learned how to back calculate the value to run through to get an expected output because ST's older CRC32 peripheral resets to 0xFFFFFFFF always.
|
|
![]() |
Mr. Powers posted:CRCs are voodoo. Last week I learned how to back calculate the value to run through to get an expected output because ST's older CRC32 peripheral resets to 0xFFFFFFFF always. So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work...
|
|
![]() |
|
Popete posted:So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work... Could it be caused by a difference in endianness between x86 and ARM?
|
![]() |
BattleMaster posted:Could it be caused by a difference in endianness between x86 and ARM? That was my thought too but I can execute the crc32 function from UBoot before booting to Android and it comes out correct. I then ported that Uboot crc32 function to user land and have it running continuously once Android boots and its incorrect. Perhaps I missed some endian check though when I brought the code over.
|
|
![]() |
|
When I did my CS degree, we had to do our CRC in hardware, with 74 series gates *shakes fist*
|
![]() |
SybilVimes posted:When I did my CS degree, we had to do our CRC in hardware, with 74 series gates *shakes fist* Well when I did my computer engineering degree we had to do our 16 bit shift multiplier in VLSI transistor layout and we had to make our own gate libraries! *shakes fist harder*
|
|
![]() |
Popete posted:So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work... This is because there isn't just one CRC32 and its dumb. Is the initial value 0xFFFFFFFF or 0? Is it byte or word oriented, and if byte, what order? Is it the same polynomial (it probably is)? The STM32 does little endian word-oriented with an initial value of 0xFFFFFFFF. It took us a while to get this figured out, then we had to get IAR to generate a CRC the same way. Pain in the rear end.
|
|
![]() |
|
Hi guys. I've just found this thread today and figured it would be good to read what other people are doing since I've recently gotten involved in embedded programming. I joined a lab at my university where we primary work with Teensy 3.1s and some flavors of MSP430s for ultra low power sensors. So far I've explored and created a testbed for a low power computational RFID backscatter analysis (which was mostly finding existing code and adapting it for my own use) and I helped with writing a basic accelerometer driver and getting some radios to talk to each other!
|
![]() |
Mr. Powers posted:This is because there isn't just one CRC32 and its dumb. Is the initial value 0xFFFFFFFF or 0? Is it byte or word oriented, and if byte, what order? Is it the same polynomial (it probably is)? The STM32 does little endian word-oriented with an initial value of 0xFFFFFFFF. It took us a while to get this figured out, then we had to get IAR to generate a CRC the same way. Pain in the rear end. Yeah I actually initially tried out a CRC32 that my buddy had written and it uses the same polynomial as the UBoot and Linux lib/crc32c.c code. The polynomial starts as 0xFFFFFFFF and has a set polynomial. Like I said I ended up just porting over the UBoot CRC32 function into my userland program and tried running it there but ended up with differing results. This could be a byte order issue still though as I'm reading out this blob from eMMC and dumping it into RAM where I then run CRC32 across it.
|
|
![]() |
|
![]()
|
# ? May 13, 2024 14:11 |
|
Popete posted:So I have a binary blob cross compiled on my Ubuntu build machine and I run crc32 on it to get the original value. Then I boot my system (Android with 2.6.35 kernel) and attempt to recalculate the CRC across the same binary blob. I ported over U-Boots crc32 command line function into Linux user land for my board and it never gives me the same crc32. If I use the same crc32 at the U-Boot command line it comes out correct but for whatever reason my port doesn't work... I'm assuming this code is C? Does the CRC algorithm make any assumption about the actual sizes of data types (int, short, etc...)? Does the code comply with strict aliasing rules? Have you tried running the various CRC on a single word or other small datum to get a better idea how its output diverges?
|
![]() |