Forum Index
HomeZBasic Home   Forum RulesForum Rules   Forum FAQForum FAQ   MemberlistMemberlist   UsergroupsUsergroups   RSS FeedRSS Feed
Site SearchSite Search   LinksLinks   DownloadDownload   Digests and SubscriptionsDigests and Subscriptions
ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in   RegisterRegister
How is a UnsignedInteger stored?

 
Post new topic   Reply to topic    Forum Index -> ZBasic Language
Author Message
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 08 February 2006, 20:23 PM    Post subject: How is a UnsignedInteger stored? Reply with quote

I need to store some UnsignedIntegers(UI) in EEPROM and would like to know how ZBasic normally stores this two byte data type. My EEPROM is a serial FRAM device. I need to know if I should store the data with the lobyte at the lowest memory location followed by the hibyte or the other way around because I want to use something like:
Code:

   Call BlockMove(2, MemAddress(data(7), MemAddress(UserFldEl))

to retrieve the UI and place it in UserFldEl. The data for UserFldEl is retrieved from the FRAM into data(7) and data(8). Should data(7) contain the low byte or the high byte?
Back to top
mikep



Joined: 24 Sep 2005
Posts: 765
Location: Austin, TX

Posted: 08 February 2006, 21:18 PM    Post subject: Reply with quote

Vic,

You are on the wrong track here. EEPROM memory is treated differently to RAM memory. Read sections 2.9 and 2.10 of the language reference manual. It is your decision whether to use Persistent memory (on chip EEPROM) or program memory (off chip EEPROM).

BlockMove only moves bytes from RAM to RAM as stated in the documentation: http://www.zbasic.net/doc/ZBasicSysLib/ZBasicSysLib26.html.
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR

Posted: 08 February 2006, 22:30 PM    Post subject: Reply with quote

The ZX is a "little endian" device. For those unfamiliar with the term, "little endian" implies that the less significant bytes are stored at lower numbered addresses, i.e. "little end" first. In contrast, "big endian" form has the more significant bytes stored at lower numbered addresses.

You'll have to write your own routines for writing data to and reading data from the external FRAM device. Consequently, you can adopt any byte order that you would like as long as you are consistent. From a practical perspective, it may be simpler to adopt the "little endian" form used by the ZX.

As Mike pointed out, BlockMove() copies from RAM to RAM. You can use GetPersistent() to copy from Persistent Memory to RAM and PutPersistent() to copy from RAM to Persistent Memory. GetEEPROM() and PutEEPROM() perform the same function between RAM and Program Memory.
Back to top
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 09 February 2006, 2:44 AM    Post subject: Reply with quote

First, let me thank you both for your response to my question. Smile

I believe I misled you both about this code
Code:

Call BlockMove(2, MemAddress(data(7), MemAddress(UserFldEl))


This was extracted from my FRAMRead subroutine. The information read from the FRAM in the routine is stored in the array data() and, in particular, the two bytes of data representing UserFldEl has been stored into data(7) and data( 8 ) and i wish to move those two bytes from data() to UserFldEl. I have a subroutine FRAMWrite that puts the bytes of UserFldEl sequentially into FRAM and I want to be sure that I am putting them in the proper order so that when I call FRAMRead and extract the bytes from the FRAM I can get them back into USerFLdEl in the proper order using the above BlockMove call. The array data() is defined as an array of bytes. So I guess I would put the high byte of UserFldEl into the FRAM at address x and the low byte into FRAM at address x+1. Question Then, later I can extract UserFldEl using my block move and have the stored value replaced properly in UserFldEl Smile

Does this make any sense? Confused

Vic
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR

Posted: 09 February 2006, 3:13 AM    Post subject: Reply with quote

Quote:
So I guess I would put the high byte of UserFldEl into the FRAM at address x and the low byte into FRAM at address x+1.

That would be "big endian" byte order, backwards from the ZX's "little endian" byte order. However, as I pointed out earlier, the difference is moot provided your "get" and "put" routines operate in a consistent manner.

As usual, it is best to document details such as byte order in your code's comments just so you won't forget what's going on and why.
Back to top
mikep



Joined: 24 Sep 2005
Posts: 765
Location: Austin, TX

Posted: 09 February 2006, 3:15 AM    Post subject: Reply with quote

So your problem is that you have a data structure that you want to manipulate in memory and it should contain an unsigned integer at offset 7 in the array. The fact that the memory is written or read from FRAM, EEPROM, Floppy disk etc is actually not relevant to this problem.

And in fact you shouldn't have to care about byte ordering either providing you do it the same for writing and reading. The simplest solution in ZBasic is to use Aliases (http://www.zbasic.net/doc/ZBasicRef/ZBasicRef69.html):
Code:
Dim data(1 to 20) as Byte
Dim UserFldEl as UnsignedInteger alias data(7)

BasicX does not have Aliases so you have to use the BlockMove idea. Aren't you glad you are using Zbasic now Smile
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR

Posted: 09 February 2006, 3:26 AM    Post subject: Reply with quote

Quote:
The simplest solution in ZBasic is to use Aliases...


In order to use an Alias (or BlockMove() for that matter) the byte order must match the native byte order, i.e., little endian.

If you assemble the values byte-by-byte using the shift/add approach, the byte order of the data source is immaterial. This method (or something similar) must be used to attain code portability among platforms with different byte orders. For example, in network-oriented code written in C/C++ and similar languages macros are often employed that convert values from network byte order (big endian) to host byte order and back. On systems where the host byte order is the same as network byte order the macros do nothing.
Back to top
victorf



Joined: 01 Jan 2006
Posts: 342
Location: Schenectady, New York

Posted: 09 February 2006, 12:11 PM    Post subject: Reply with quote

OK here's the that I am using. I have tried to figure out how to do the alias thing. The variables being written to FRAM are global:

Code:

Public Function WriteSystemData() as byte

'System data is maintained in at the top of the FRAM starting at the address 32700. This
'System data is:
'
'UserToFromFlag    as Boolean               (1)   32700
'UserHgtUnits       as Boolean               (1)   32701
'UserFldElUnits    as Boolean               (1)   32702
'UserAscRtUnits    as Boolean               (1)   32703
'UserSpdUnits       as Byte                     (1)   32704
'UserSampleTime    as Byte                     (1)   32705
'UserFldEl             as UnsignedInteger   (2)   32706 32707
'UserAscRate          as UnsignedInteger   (2)   32708   32709
'
'this Function returns 0 if successful else:
'-1 if invalid fram channel
'-2 if invalid sda pin number
'-3 if invalid scl pin number
'-4 if invalid bit rate
'-5 if fram device addressing problem
'-6 if write address problem
'-7 if error writing data
'
   dim data(1 to 10) of byte
   dim rvalue as integer
   dim
   data(1) = CByte(UserToFromFlag)
   data(2) = CByte(UserHgtUnits)
   data(3) = CByte(UserFldElUnits)
   data(4) = CByte(UserAscRtUnits)
   data(5) = UserSpdUnits
   data(6) = UserSampleTime
   data(7) = HiByte(UserFldEl)
   data(8) = LoByte(UserFldEl)
   data(9)= HiByte(UserAscRate)
   data(10) = LoByte(UserAscRate)
   
   rvalue = FRAMInit(HRDWARE, SDA, SCL, 0)   'use hardware I2C channel w/defaults

   if rvalue < 0 then                     'error initializing FRAM occured
      WriteSystemData = rvalue         
      exit Function
   End if

   rvalue = FRAMWrite(HRDWARE, FRAMDEV, FRAMUSRADR, data(), SizeOf(data))
   
   if rvalue < 0 then                     'error initializing FRAM occured
      select Case rvalue
         case -1
            rvalue = -5
         case -2, -3
            rvalue = -6
         case -4
            rvalue = -7
      End select
      WriteSystemData = rvalue         
      exit Function
   End if
   
   WriteSystemData = rvalue
End Function   'WriteSystemData

Code:

Public Function ReadSystemData() as integer

'System data is maintained in at the top of the FRAM starting at the address 32000. This
'System data is:
'
'UserToFromFlag    as Boolean               (1)   32700
'UserHgtUnits       as Boolean               (1)   32701
'UserFldElUnits    as Boolean               (1)   32702
'UserAscRtUnits    as Boolean               (1)   32703
'UserSpdUnits       as Byte                     (1)   32704
'UserSampleTime    as Byte                     (1)   32705
'UserFldEl             as UnsignedInteger   (2)   32706 32707
'UserAscRate          as UnsignedInteger   (2)   32708   32709
'
'Function returns number of bytes read from FRAM if successful
'else it returns a negative number

   dim data(1 to 10) of byte
   dim rvalue as integer
   
   rvalue = FRAMRead(HRDWARE, FRAMDEV, FRAMUSRADR, data(), SizeOf(data))
   
   if rvalue < 0 then
      ReadSystemData = rvalue
      exit Function
   End if
   
   UserToFromFlag = CBool(data(1))
   UserToFromFlag = CBool(data(2))
   UserFldElUnits = CBool(data(3))
   UserAscRtUnits = CBool(data(4))
   UserSpdUnits = data(5)
   UserSampleTime = data(6)
   Call BlockMove(2, MemAddress(data(7), MemAddress(UserFldEl))
   Call BlockMove(2, MemAddress(data(9), MemAddress(UserAscRate))
   
   ReadSystemData = rvalue
   
End Function   'ReadSystemData



By the way, here are the declarations of the system variables being discussed:
Code:

'User Parameters
Public UserToFromFlag as Boolean   'True = To or False = From
Public UserHgtUnits as Boolean      'True = Feet or False = Meters
Public UserSpdUnits as byte      '0 = Knots, 1 = Km/Hr, 2 = M/Sec
Public UserFldElUnits as Boolean   'True = Feet or False = Meters
Public UserFldEl as UnsignedInteger   '0 to 65535 units
Public UserAscRtUnits as Boolean   'True = Ft/Min or False = M/Min
Public UserAscRate as UnsignedInteger 'pibal ascent rate in user units
Public UserSampleTime as byte       'sample period 0 = 15 sec, 1 = 30 sec, 2 = 60 sec


Without declaring a whole bunch of new variables for use in these routines, I just want to move the already existing values into my scratchpad FRAM and later retrieve them, usually in another running of the program. Notice that I am putting these valuse in the high end of the FRAM. This is because I am using the low addresses to store variables computed during the running of the program. I have my reasons for doing this. The variables under discussion are not LIKELY to be changed by the user in any case as they define the system, but they could be!

I like the "alias" thing but I am not sure how to apply it here.

BTW:this forum editor does not seem to handle tabs very gracefully Nor the insertion of Emoticons Confused

Any enlightenment will be appreciated.

Vic
Back to top
mikep



Joined: 24 Sep 2005
Posts: 765
Location: Austin, TX

Posted: 09 February 2006, 14:29 PM    Post subject: Reply with quote

Here is the set of global declarations you need for your system variables and data array:
Code:
Private data(1 to 10) as Byte
Private UserToFromFlag as Boolean Alias data(1)
Private UserHgtUnits as Boolean Alias data(2)
Private UserFldElUnits as Boolean Alias data(3)
Private UserAscRtUnits as Boolean Alias data(4)
Private UserSpdUnits as Byte Alias data(5)
Private UserSampleTime as Byte Alias data(6)
Private UserFldEl as UnsignedInteger Alias data(7)
Private UserAscRate as UnsignedInteger Alias data(9)

and here is the rest of the (untested) code to make the system work
Code:
Private Const HRDWARE as Byte = 0
Private Const FRAMDEV as Byte = 6
Private Const FRAMUSRADR as Byte = 32700
Private Const SDA as Byte = 11
private Const SCL as Byte = 12

'System data is maintained in at the top of the FRAM starting at the address 32700.
Public Function WriteSystemData() as Integer
   Dim rvalue as Integer
   rvalue = FRAMInit(HRDWARE, SDA, SCL, 0)   'use hardware I2C channel w/defaults
   rvalue = FRAMWrite(HRDWARE, FRAMDEV, FRAMUSRADR, data, SizeOf(data))
   WriteSystemData = rvalue
End Function   'WriteSystemData

Public Function FRAMInit(ByVal channel as Byte, ByVal SDAPin as Byte, ByVal SCLPin as Byte, ByVal BitRate as Byte) as Integer
   Call OpenI2C(channel, SDAPin, SCLPin, BitRate)
   FRAMInit = 0
End Function

Public Function FRAMWrite(ByVal channel as Byte, ByVal slaveId as Byte, ByVal address as Byte,  _
                     ByRef dataToWrite() as Byte, ByVal length as Integer) as Integer               
   FRAMWrite = I2CCmd(channel, slaveId, address, length, 0, 0)
   FRAMWrite = I2CCmd(channel, slaveId, dataToWrite(1), length, 0, 0)
End Function

Public Sub Main()
   Debug.Print "Saving system data returns ";CStr(WriteSystemData())
End Sub
Back to top
mikep



Joined: 24 Sep 2005
Posts: 765
Location: Austin, TX

Posted: 10 February 2006, 3:47 AM    Post subject: Reply with quote

For those of you who are awake there is a bug in the routine below.
Code:
Public Function FRAMWrite(ByVal channel as Byte, ByVal slaveId as Byte, ByVal address as Byte,  _
                     ByRef dataToWrite() as Byte, ByVal length as Integer) as Integer               
   FRAMWrite = I2CCmd(channel, slaveId, address, length, 0, 0)
   FRAMWrite = I2CCmd(channel, slaveId, dataToWrite(1), length, 0, 0)
End Function
I wasn't able to test this code but it should look something like this:
Code:
Public Function FRAMWrite(ByVal channel as Byte, ByVal slaveId as Byte, ByVal address as Byte,  _
                     ByRef dataToWrite() as Byte, ByVal length as Integer) as Integer
   Dim L as Byte
   L = 1           
   FRAMWrite = I2CCmd(channel, slaveId, address, L, 0, 0)
   FRAMWrite = I2CCmd(channel, slaveId, dataToWrite(1), length, 0, 0)
End Function
Back to top
dkinzer
Site Admin


Joined: 03 Sep 2005
Posts: 2499
Location: Portland, OR

Posted: 10 February 2006, 5:07 AM    Post subject: Reply with quote

The "number of bytes to write" parameter comes before the "data to write" so the code below would be closer to being correct.

Code:
Public Function FRAMWrite(ByVal channel as Byte, ByVal slaveId as Byte, ByVal address as Byte,  _
                     ByRef dataToWrite() as Byte, ByVal length as Integer) as Integer
   FRAMWrite = I2CCmd(channel, slaveId, 1, address, 0, 0)
   FRAMWrite = I2CCmd(channel, slaveId, CByte(length), dataToWrite, 0, 0)
End Function


Upon further reflection, however, it would seem that the 'address' parameter probably should be wider than a Byte. However, if the address will always be less than 256 it doesn't matter.

Note that the I2CCmd() procedure is capable of writing at most 255 bytes at a time. If this function needs to be able to write more than that, it will have to do it iteratively.
Back to top
Display posts from previous:   
Post new topic   Reply to topic    Forum Index -> ZBasic Language Time synchro. with the server - Timezone/DST with your computer
Page 1 of 1

 


All content Copyright © 2005-2012 Elba Corp. All Rights Reserved.
Opinions expressed in posts are those of the author and not necessarily those of Elba Corp.
Powered by phpBB © 2001, 2005 phpBB Group