Passing and Returning Arrays
reppig
Posts: 35
I am trying to follow the examples in the education kit manual but I still most not be doing it right.
In the code below I call geoLlh2Efg(@GS_Llh, @efg_gs) where the first pointer is an array of data coming in and the second is an array to return the answers. The answers coming back are not correct.
Am I passing arrays back and forth correctly??
In the code below I call geoLlh2Efg(@GS_Llh, @efg_gs) where the first pointer is an array of data coming in and the second is an array to return the answers. The answers coming back are not correct.
Am I passing arrays back and forth correctly??
CON _clkmode = xtal1 + pll16x 'Standard clock mode * crystal freq. = 80 MHz _xinfreq = 5_000_000 'Extenal Crystall Freq. {{********* WGS-84 Constants **********}} earth_rad = 6378137.0 'Radius of a spherical model of the Earth flattening = 298.2572236 'Flattening - spherical model of the earth VAR long efg[3], efg_gs[3], efg_tgt[3] 'efg coords of ground station and target(balloon long xyz[3], rae[3], GS_Llh[3] 'xyz or range,az,el or ground station lat, long, height OBJ f : "Float32Full" DBG : "FullDuplexSerialPlus" FS : "FloatString" 'EX. - DBG.Str(FS.FloatToString(temp)) PUB Main | ok1, ok2 WAITCNT(CLKFREQ * 6 + CNT) 'Start FullDuplexSerialPlus Driver for debug. The Driver will launch a 'COG for serial communication with Parallax Serial Terminal oK1 := DBG.Start(31, 30, 0, 57600) DBG.Str(STRING(16, 1, 10, 13)) DBG.Str(STRING(" GPS Float Lite Demo v1.0 started...", 10, 13)) WAITCNT(CLKFREQ * 2 + CNT) 'Start Float32Full oK2 := f.Start 'Connection pins are defined in the driver IF NOT (oK1 AND oK2) 'Some error occured IF oK1 'We have at least the debug terminal DBG.Str(STRING(10, 13)) DBG.Str(STRING("Some error occurred. Check System!", 10, 13)) DBG.Stop IF oK2 f.Stop REPEAT 'Until Power Off or Reset GS_Llh[0] := 28.52467 GS_Llh[1] := -80.68395 GS_Llh[2] := 14.0 geoLlh2Efg(@GS_Llh, @efg_gs) DBG.Str(FS.FloatToString(efg_gs[0])) DBG.Str(STRING(10, 13)) DBG.Dec(FS.FloatToString(efg_gs[1])) DBG.Str(STRING(10, 13)) DBG.Dec(FS.FloatToString(efg_gs[2])) repeat {********** Geo_B & Geo_E2 are Functions to do a Geodetic solution **********} PUB Geo_B | temp 'Geo_B = (earth_rad * (1.0 - (1.0 / flattening))) temp := f.FDiv(1.0, flattening) 'Geo_B = (earth_rad * (1.0 - temp)) temp := f.FSub(1.0, temp) 'Geo_B = (earth_rad * temp) temp := f.FMul(earth_rad, temp) DBG.Str(FS.FloatToString(temp)) DBG.Str(STRING(10, 13)) result := temp 'Return Geo_B PUB Geo_E2 | temp, temp1, temp2 'Geo_E2 = (((earth_rad * earth_rad) - (GEO_B * GEO_B)) / (earth_rad * earth_rad)) temp2 := f.FMul(earth_rad, earth_rad) 'Geo_E2 = ((temp2 - (GEO_B * GEO_B)) / temp2) temp1 := f.FMul(GEO_B, GEO_B) 'Geo_E2 = ((temp2 - temp1) / temp2) temp := f.FSub(temp2, temp1) 'Geo_E2 = (temp / temp2) temp := f.FDiv(temp, temp2) DBG.Str(FS.FloatToString(temp)) DBG.Str(STRING(10, 13)) result := temp PUB geoLlh2Efg(LLHaddr, efg_ret) | temp, temp1, sin_lat, cos_lat, N 'Inputs Latitude, longitude, height & return array sin_lat := f.Sin(f.Radians(long[LLHaddr][0])) cos_lat := f.Cos(f.Radians(long[LLHaddr][0])) { Compute the radius of curvature -- N = a / Sqrt(1.0 - Geo_E2 * sin_lat * sin_lat) } temp := f.FMul(sin_lat, sin_lat) 'N = a / Sqrt(1.0 - (Geo_E2 * temp)) temp := f.FMul(Geo_E2, temp) 'N = a / Sqrt(1.0 - temp) temp := f.FSub(1.0, temp) 'N = a / Sqrt(temp) temp := f.FSqr(temp) 'N = a / temp N := f.FDiv(earth_rad, temp) { Compute the EFG(XYZ) coordinates (earth centered)} temp1 := f.FAdd(N, long[LLHaddr][2]) 'efg[0] := ((N + height) * cos_lat * Cos(Degree2Radian(lon))) temp := f.Cos(f.Radians(long[LLHaddr][1])) 'efg[0] := (temp1 * cos_lat * temp) temp := f.FMul(cos_lat, temp) 'efg[0] := (temp1 * temp) efg_ret[0] := f.FMul(temp1, temp) 'efg[1] := ((N + height) * cos_lat * Sin(Degree2Radian(lon))) temp := f.Sin(f.Radians(long[LLHaddr][1])) 'efg[1] := temp1 * cos_lat * temp temp := f.FMul(cos_lat, temp) 'efg[1] := temp1 * temp efg_ret[1] := f.FMul(temp1, temp) 'efg[2] := (N * (1.0 - Geo_E2) + height) * sin_lat temp := f.FSub(1.0, Geo_E2) 'efg[2] := (N * temp + height) * sin_lat temp := f.FMul(N, temp) 'efg[2] := (temp + height) * sin_lat temp := f.FAdd(temp, long[LLHaddr][2]) 'efg[2] := temp * sin_lat efg_ret[2] := f.FMul(temp, sin_lat)
Comments
Edit: plus in geoLlh2Efg
Should be efg_gs[0] := Fix the other two as well...
Use the Parallax Serial Terminal to view values/memory. Use meaningful variable names... I found your code hard to follow. I had to use find to track your variables. But that's just me others might not have the same issue.
But to explain what's wrong with your code:
In fact SPIN is not type-safe. This means that even if efg_ret is a single long containing the address of the array, it can be used as an array itself without a problem. But without problem only means that the compiler does not complain.
But the function is different than expected!
long efg_gs[3]
creates 3 longs in memory and efg_gs in the program is replaced by the address of the first long in all the code.
The array-notation will simply add the index to this address wherever used.
efg_gs := 0 and efg_gs[0] := 0 are the same! (0 will be stored at the memory location that's given by efg_gs respectively efg_gs + 0.
efg_gs[1] := 0 stores the 0 at the memory location efg_gs + 4 (it's +4 because we talk about a long variable)
efg_gs[2] := 0 -> efg_gs + 8 .....
Instructions like efg_gs[1] := will always put a long into the location, whereas an instruction like ret := efg_gs[1] + xxxxx will always read the content and use that.
A function call like calc(efg_gs) will first read the content and pass this as parameter.
A function call like calc(@efg_gs) will not read the content, but pass the address insted.
On the other side of the function, the address is stored IN the parameter-variable.
PUB calc( efg_ret )
So, what does it mean?
efg_ret contains the address
efg_ret[0] also contains the address. Overwriting efg_ret[0] := 0 will simply put the 0 into efg_ret. Now it no longer contains the address!
efg_ret[1] := 0 will store the 0 in memory location efg_ret + 4, which is located in the stack-space - if the stack is big enough. If not you overwrite something else!
To write into the memory that efg_ret points to, you have to write
long[ efg_ret ][ 0 ] := 0
long[ efg_ret ][ 1 ] := 0 ....
The debug numbers that come out are:
Params: 28.52467 <-- correct
5712 <-- not correct
5712 <-- not correct
Main 907832.2 <-- correct
Why are the second and third parameters not being passed??