|
Forum Index : Microcontroller and PC projects : Convert small 64bit signed integer into a high and low byte ?
| Author | Message | ||||
| DigitalDreams Regular Member Joined: 03/05/2025 Location: United KingdomPosts: 62 |
My next challenge is to save signed integers to an I2c memory chip. They will only range from say -300 to +900 so will be saving as two bytes (high and low) as if a 16bit integer, not the incoming MMBasic 64bit. For example - Dim as integer Xmin,Dhi,Dlo Xmin=-298 ... ... I2c write &h50,0,4,1,0,Dhi,Dlo I'm already writing small positive MMBasic 64bit integers as single bytes as MMBasic converts/truncates to 8bit in the i2c command itself. Wondering what the fastest and most efficient way would be to do this ? |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11194 |
bin2str$ was designed for specifically this Edited 2026-04-15 03:23 by matherp |
||||
| DigitalDreams Regular Member Joined: 03/05/2025 Location: United KingdomPosts: 62 |
I'll have a play sir.... |
||||
| bfwolf Senior Member Joined: 03/01/2025 Location: GermanyPosts: 233 |
A kind of "hack" according to C, which relies on the Pico using an ARM with a little-endian format:Dim XminAddr As integer XminAddr = PEEK(VARADDR Xmin) Dlo = PEEK(BYTE XminAddr) Dhi = PEEK(BYTE (XminAddr+1)) |
||||
| DigitalDreams Regular Member Joined: 03/05/2025 Location: United KingdomPosts: 62 |
First attempt results in "Error : Argument Count" a$=Bin2Str$(INT16,xmin,BIG) I2C2 write &h50,0,4,1,0,a$ Hence writing 4 bytes... '1','0','2byte string' ?? |
||||
| DigitalDreams Regular Member Joined: 03/05/2025 Location: United KingdomPosts: 62 |
Interesting 😎 |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 3141 |
When writing a string to a 24Cxx EEPROM the 2 address bytes need to be added to the start of the data. So perhaps try:- a$ = Chr$(Mem.addr>>8) + Chr$(Mem.addr And 255) + a$ 'prepend 2 byte memory address to the data I2C2 WRITE I2C.addr, 0, Len(a$), a$ 'write 2 memory address bytes + up to 32 data bytes Pause 6 'allow time to write Currently you are trying to write a mix of integer bytes and a string which I2C WRITE doesn't accept. Edited 2026-04-15 11:04 by phil99 |
||||
| DigitalDreams Regular Member Joined: 03/05/2025 Location: United KingdomPosts: 62 |
Done, created a 4byte string by concatenation of the 2 individual FRAM address bytes (INT8) and the 16bit signed integer data (INT16) into one string for a single I2C2 string write (adding three Bin2Str$ together). Reading back was much simpler as the I2C read is preceeded by an I2C write that simply sets the FRAM address of the two data bytes that are then I2C read into a string in Str2Bin format. Don't think there's a more efficient/faster way at the moment unless Peter adds the ability into I2C2write 😎... Edited 2026-04-16 05:58 by DigitalDreams |
||||
| PhenixRising Guru Joined: 07/11/2023 Location: United KingdomPosts: 1840 |
I find the To be a bit offensive Is it required? Furthermore, I believe that in the manual, there's a paragraph that suggests the maximum speed is still 400KHz whereas elsewhere, it has been updated to 1000KHz. |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 3141 |
Not if you are doing a single write. If writing to more than 1 32 byte page you get a garbled mess if you don't space the writes out. It doesn't have to be a pause, you could do the writes triggered by a timer or in a tick sub. |
||||
| bfwolf Senior Member Joined: 03/01/2025 Location: GermanyPosts: 233 |
I just looked at the datasheet for the Microchip 24LC512 and it says the following: I assume this behavior is common to many I2C EEPROMs? This would mean that as long as the write cycle is still ongoing, a read command (to any address, or more precisely, to the LastWriteAddress + 1) will not be acknowledged, and this behavior can be interpreted as "busy"! This way, a fixed (and unnecessarily long) delay could be avoided. Regards, bfwolf. |
||||
| Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 5856 |
Hi bfwolf, That is the correct way to do it, but in MMbasic that means you will need to poll in a loop until you do not an I2C error anymore. So MMBasic is busy. So it is not better than a simple "PAUSE 6" (unless a particular fast I2C chip is ready in 4ms). Regards, Volhout PicomiteVGA PETSCII ROBOTS |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 3141 |
It appears you can trim some time off, depending on the chip. > d$ = "ABCDEFGHIJKLMNOPQRSTUVWXYZ012345" '32 bytes > d$= bin2str$(uint16,48,big)+d$ > i2c2 write &H57,0,len(d$),d$ :t=timer :do :i2c2 read &H57,0,26,d$ :loop until MM.I2C=0 :t= timer-t :?t 2.379 > i2c2 write &H57,0,len(d$),d$ :t=timer :do :i2c2 read &H57,0,26,d$ :loop until MM.I2C=0 :t= timer-t :?t 2.372 > |
||||
| bfwolf Senior Member Joined: 03/01/2025 Location: GermanyPosts: 233 |
I just took a quick look at some I2C EEPROM datasheets from various manufacturers (which we have archived on a server at work) and noticed the following: Many have "WriteCycleTime = max. 5ms", but the AT24C1024, for example, has 10ms — so 6ms might even be too short! Sure, "PAUSE 6" is the easy way, which probably works 90% of the cases — but it can also sometimes be too short — or usually too long. By the way, I initially thought "PAUSE 6" would pause for 6 seconds... @phil99: Good example code shown! Regards, bfwolf |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 3141 |
A better speed tester. This one doesn't waste time reading back a lot of bytes, 1 is all that is needed. Print "Page write speed test for 24C32 EEPROM on I2C2" Dim Wr$, Re$, tmp$, n%, t, I2C.addr = &H57 Print "Make future failure to write visible." tmp$ = "Fail" For n%= 0 To 95 Step 4 Wr$ = Chr$(0)+Chr$(n%)+tmp$ I2C2 write I2C.addr, 0, Len(Wr$), Wr$ Pause 9 Next Print "Verify data was written" I2C2 write I2C.addr, 0, 2, 0, 0 : I2C2 read I2C.addr, 0, 96, Re$ Print Re$ : Print Wr$ = "" : tmp$ = "" : Re$ = "" For n% = 32 To 127 'make 3 pages of data Inc Wr$, Chr$(n%) Next Print "Test Data" Print Wr$ : Print For n% = 0 To 64 Step 32 tmp$ = Mid$(Wr$,n%+1,32) Print tmp$ tmp$ = Chr$(0) + Chr$(n%) + tmp$ I2C2 write I2C.addr, 0, Len(tmp$), tmp$ t=Timer:Do :I2C2 read I2C.addr,0,1,Re$:Loop Until MM.I2C<>1:t=Timer-t Print "Time to Write a Page = ";t;"mS" : Print Next Re$ = "" Print " Check saved data for errors." I2C2 write I2C.addr, 0, 2, 0, 0 : I2C2 read I2C.addr, 0, 96, Re$ Print Re$ If Re$ = Wr$ then Print " Data validated" else Print " Validation failed!" End A:> RUN Page write speed test for 24C32 EEPROM on I2C2 Make future failure to write visible. Verify data was written FailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFailFail Test Data !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ !"#$%&'()*+,-./0123456789:;<=>? Time to Write a Page = 1.806000002mS @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ Time to Write a Page = 1.787999999mS `abcdefghijklmnopqrstuvwxyz{|}~ Time to Write a Page = 1.789999999mS Check saved data for errors. !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ Data validated A:> So for this chip a 2mS pause is enough. Edited 2026-04-17 13:56 by phil99 |
||||
| Mixtel90 Guru Joined: 05/10/2019 Location: United KingdomPosts: 8763 |
You can't go shorter than what it says on the spec sheet for the chip. That's the timing that the manufacturers know will work. Some chips might be faster on test but one from the next batch might be only just within the spec figure. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 3141 |
This line, instead of a Pause... Do :I2C2 read I2C.addr,0,1,Re$:Loop Until MM.I2C<>1 will let the chip take as much time as it needs but no more.Footnote added 2026-04-17 18:44 by phil99 In view of Peters comment below perhaps this could be used instead. t=timer :Do :I2C2 read I2C.addr,0,1,Re$:Loop Until MM.I2C<>1 Or timer-t >6 |
||||
| matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 11194 |
This is a bad idea. This could wait for the default I2C timer to expire (1 second) before returning depending on what the device does with the early request. If you have a device that needs a 5mSec wait then you need to wait 5mSec. The way to do this without blocking would be a settick callback timer Edited 2026-04-17 18:32 by matherp |
||||
| phil99 Guru Joined: 11/02/2018 Location: AustraliaPosts: 3141 |
Good point, added a 5mS timeout to the loop and a counter to record the number of times the timeout is reached. Then made it loop continuously to see how often this happens. Print "Page write speed test for 24C32 EEPROM on I2C2" Dim Wr$, Re$, tmp$, n%, t, LC%, LT, TOut%, I2C.addr = &H57 For n% = 32 To 127 'make 3 pages of data Inc Wr$, Chr$(n%) Next Print "Test Data" Print Wr$ : Print Do For n% = 0 To 64 Step 32 tmp$ = Mid$(Wr$,n%+1,32) Print tmp$ tmp$ = Chr$(0) + Chr$(n%) + tmp$ I2C2 write I2C.addr, 0, Len(tmp$), tmp$ t=Timer:Do :I2C2 read I2C.addr,0,1,Re$:Loop Until MM.I2C<>1 Or Timer-t>5:t=Timer-t Print "Time to Write a Page = ";t;"mS" If t>5 Then Print "*********** 5mS Timout Exceeded ************" Inc TOut% EndIf Next Re$ = "" Print " Check saved data for errors." I2C2 write I2C.addr, 0, 2, 0, 0 : I2C2 read I2C.addr, 0, 96, Re$ Print Re$ ': Print If Re$ = Wr$ Then Print " Data validated" Else Print " Validation failed!" If t > LT Then LT = t Inc LC% Print "Loop Count =";LC%, "Max. Write Time =";LT, "Number of Timeouts =";TOut% Print "Start again" : Print : Print Loop End !"#$%&'()*+,-./0123456789:;<=>? Time to Write a Page = 1.767999999mS @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ Time to Write a Page = 1.83mS `abcdefghijklmnopqrstuvwxyz{|}~ Time to Write a Page = 1.825999999mS Check saved data for errors. !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ Data validated Loop count = 7574 Max. Write Time = 1.833000001 Number of Timeouts = 0 Start again !"#$%&'()*+,-./0123456789:;<=>? Time to Write a Page = 1.824999999mS @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ Time to Write a Page = 1.821mS `abcdefghijklmnopqrstuvwxyz{|}~ Time to Write a Page = 1.823000001mS Check saved data for errors. !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ Data validated Loop count = 7575 Max. Write Time = 1.833000001 Number of Timeouts = 0 Start again Edit. A longer run. Check saved data for errors. !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ Data validated Loop count = 84732 Max. Write Time = 1.833000001 Number of Timeouts = 0 Start again Edited 2026-04-17 22:07 by phil99 |
||||
| The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2026 |