40-bit values on a 32-bit microcontroller - Page 1
Forum section: electronics / general

author: rill17
author_rank: Contributor
timestamp: April 21, 2017, 06:17:23 pm
content: Hi there, I am using a 32-bit microcontroller (PIC32MZ) and a device i am interfacing with will send me a 40-bit value over spi in a series of 5 bytes. How can i use this 40 bit value to, for instance, perform arithmetic operations with it such as multiply or divide it with another 40-bit value? thanks in advance

author: mariush
author_rank: Super Contributor
timestamp: April 21, 2017, 06:32:37 pm
content: Use 64 bit variables? Shift the bits into 64bit variables and then do the math with them.Seexc32 documentation, Chapter 8. Supported Data Types and Variables (page 145)Use unsigned long long ... make an alias for it, name it uint64 or something like that.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: April 22, 2017, 12:44:25 am
content: What type of 40 bit value is it (integer, fixed point, floating point?) and how is it stored in the 5 bytes?

author: rill17
author_rank: Contributor
timestamp: April 25, 2017, 12:34:13 am
content: basically what is happening is im interfacing with an ic which is transmitting 40-bit and 32-bit values via spi. i managed the 40-bit data but have run into another issue if you guys can help. the 32 bit data is being received 1 byte at a time and i am storing the data into 32-bit integers on the microcontroller by shifting the data using the following bit of code:for(i=0; i<64; i++){received= (uint32_t)(((myReadBuffer_SPI)<<24) | ((myReadBuffer_SPI[j+1])<<16) | ((myReadBuffer_SPI[j+2])<<|(myReadBuffer_SPI[j+3]));j += 4;}i need to transmit this 32 bit number using uart to a pc, i am using a uart to usb device and basically need to end up with a text file containing the integers in decimal format so i could copy in excel and graph the data. the conversion can be done on the pc and not necessarily on the microcontroller. any ideas??

author: TNorthover
author_rank: Contributor
timestamp: April 25, 2017, 01:46:40 am
content: Quote from: rill17 on April 25, 2017, 12:34:13 amI assume you can write bytes through the UART already, so you just reverse the unpacking shifts in your post and write those 4 bytes out sequentially. Then the PC end reassembles them exactly as you did with the SPI. Or is there something else we're missing?

author: mariush
author_rank: Super Contributor
timestamp: April 25, 2017, 02:09:34 am
content: To keep things simple you could use hexadecimal notation ( 0..9 A..F) to send the numbers over. Split the number in 4 bit chunks and convert each 0..15 value to the proper ascii character.You could just shift take the last 4 bits and put the result in an 10 element array, shift 4 bits to the right, repeat n times, then do the 0..15 conversion to 0..f 10 times for your 40 bit value.Have a look at STRUCT and UNION .. you can make your own data types with them to make it easier to work with individual bytes if you don't want to use divisions and shifts a lot.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: April 25, 2017, 02:19:53 am
content: Quote from: rill17 on April 25, 2017, 12:34:13 amIt's often better to convert the numbers into text (in eg. comma delimited CSV format) before sending via UART, because binary values can be tricky to get through some serial protocols (NULLs get absorbed, control characters do weird stuff) and synchronization is harder (how do you tell when one number ends and another starts whenanyByte can be 0-255?). Downsides are having to do more processing in the MCU (shouldn't be a problem for PIC32MZ), and having to transmit more Bytes per number.QuoteCan you tell us what the ic is, or is it a big secret?

author: rill17
author_rank: Contributor
timestamp: April 25, 2017, 12:21:43 pm
content: No no secret, i just kept it vague on purpose as its not that relevant. The IC is the Xethru X2, i am actually transmitting through UART and receiving using Termite as seen in the screenshot (delimited by a carriage return). what i need to end up with is a list of decimal values in a text file as attached.

author: brucehoult
author_rank: Super Contributor
timestamp: April 25, 2017, 01:51:28 pm
content: Quote from: rill17 on April 25, 2017, 12:34:13 amUnless you absolutely need every bit of speed you can get (inconceivable if a UART is fast enough to absorb the data) it would be much easier to use an array of bytes to store the data!Code:unsigned char received;for (i=0; i<256; i++){received = myReadBuffer_SPI;}// ... time passeschar *hex = "0123456789ABCDEF";for (i=0; i<256; i++){unsigned char ch = received;UART_out(hex[ch/16]);UART_out(hex[ch%16]);}Or maybe you can just do it from the SPI buffer in one hit, if you're not sorting out multiple interleaved message types or something.

author: macboy
author_rank: Super Contributor
timestamp: April 25, 2017, 04:08:16 pm
content: Why not pass along the 5 bytes directly, or even better IMHO, translate them into two-character ASCII encoded hex values (like "FF" for 0xFF). The benefit of the latter is that you only send printable ASCII characters, never control codes which might get eaten by the UART (like XON/XOFF chars) or by the receiving end software (like Null, EOF, CR/LF, Bell, etc.). It also allows you to insert end-of-line characters or spaces at will, to demarcate the 5-byte values. This also greatly simplifies the processing as plain text is scripting language friendly and human readable. Binary is neither.The conversion on the PC side would be simple. I'm sure a perl guru could come up with a one-liner that would eat the hex-encoded ASCII text file and spit out another text file with decimal values. In fact, you could do it real time by using the serial port as the input file to such a script.With that said, I have worked with data as large as 40 bits on a lowly 8-bit PIC (reallylowly... a PIC16F55). Writing an efficient algorithm, in assembly, to convert a 40-bit integer into a 13-digit decimal on a chip without hardware multiply or divide, is interesting to say the least.

author: brucehoult
author_rank: Super Contributor
timestamp: April 26, 2017, 01:40:28 pm
content: Quote from: macboy on April 25, 2017, 04:08:16 pmI'm not too familiar with PIC model numbers. I found that PIC16C55 has 24 *bytes* of RAM. Is that the same? Anyway, there's plenty of ROM.Store a table of powers of 10 in ROM. 13 entries, 65 bytes. For each power of ten, count how many times you can subtract it from the number (can be zero). Output that digit. Maximum 13*9 = 117 loops. Should be plenty fast enough.You could generate the powers of 10 at runtime (a loop with n = ((n<<2)+n)<<1), but it might use abuot as much code space as the table.Storing [1..9] times each power of ten would be a waste as you'd still have to fetch and compare them. At most you could do a binary search, but that would gain very little.

author: macboy
author_rank: Super Contributor
timestamp: April 26, 2017, 02:56:11 pm
content: Quote from: brucehoult on April 26, 2017, 01:40:28 pmSorry, it was the PIC16F57 (I was replacing a PIC16C55). The 'F57 has 72 bytes of RAM and 2 kword of ROM.QuoteYou might find each loop iteration to be at least few dozen cycles, so you are into the many thousands of cycles to do the conversion. It would be more efficient to have 12 separate subroutines, one for each power of ten (the highest counting up to 10 instead of 9) using immediate values, rather than gathering values from a table. When I have ROM to spare, I tend toward inline code with as few loops and branches as possible.I implemented a version of the "double dabble" algorithm. If you are not familiar, look it up. It's fascinating. I got it down to a fixed 2570 cycles for any 40-bit input. I was trying to do this within a single 2 ms timeslice of a main loop running at 1 MIPS, but couldn't fit it so I modified the algorithm to pause itself partway through and resume later.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: April 26, 2017, 08:42:50 pm
content: Quote from: rill17 on April 25, 2017, 12:21:43 pmIf I understand the X2 datasheet correctly, it stores 32 bit ADC samples in a frame buffer. When reading the buffer you choose MSB and LSB between 0 and 31. Presumably the values are unsigned, so depending on what bit range you choose the SPI output could be equivalent to 8, 16, 24 or 32 bit unsigned integers. Some control registers store 40 bit integers.Your data appears to be 32 bit integers, which you want to convert to the equivalent ASCII decimal number (character string). This can be done using printf().

author: brucehoult
author_rank: Super Contributor
timestamp: April 26, 2017, 08:49:20 pm
content: Quote from: Bruce Abbott on April 26, 2017, 08:42:50 pmShirley you joke, sir?printf() can drag in tens of KB of code. You want to print a simple integer, why drag in tons of code you don't need to to justify, pad, print in different bases, not to mention format floating point numbers in a all manner of ways?

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: April 27, 2017, 05:22:31 pm
content: Quote from: brucehoult on April 26, 2017, 08:49:20 pmThesmallestPICMZ has 512k of Flash. XC32's printf uses less than 7k. If program memory is so tight that you can't afford another 1.4% to get nicely formatted printing then you are probably already in trouble.

author: senso
author_rank: Frequent Contributor
timestamp: April 27, 2017, 06:53:48 pm
content: Printf with floats in an atmega are around 3-4k of flash, its so handy to be able to print nicelly formated strings, yes I could make it with a ton of buffers, xtoa's and gluing that all together, or just sprintf and be done with it.

author: brucehoult
author_rank: Super Contributor
timestamp: April 27, 2017, 08:22:27 pm
content: Quote from: Bruce Abbott on April 27, 2017, 05:22:31 pmWe were just talking about, for example, PIC16F57 with 2 K words of ROM, and printing 40 bit integers on that. printf() ain't gunna fit.

author: VEGETA
author_rank: Super Contributor
timestamp: May 01, 2017, 05:39:27 am
content: I guess you can use 2 of 32 variables for storing data then use shifting bits technique to store them in one 64 variable. I guess the tool here is >> and <<.