#%TITLE% ICE_VDATA.MAC
#
#%NAME%
# Macros to handle IcePAP data vectors, used for instance for
# defining embedded trajectories.
#
#%DESCRIPTION%
# These macros allow to create a data vector from one to several
# data arrays of parameter, position or slope values.
#
#%EXAMPLE%
# short array myparam[4]
# short array mypos[4]
# array_op("fill", myparam)
# array_op("fill", mypos, 10)
# icepap_vdata_build vdata1 POSITION mypos 6
# icepap_vdata_build vdata1 PARAMETER myparam 6
# icepap_vdata_info vdata1
#
#%END%
#
# Mandatory standard IcePAP macros
need ice
# Constant definitions
unglobal ICEPAP_VDATA_DTYPECODE
ICEPAP_VDATA_DTYPECODE["BYTE" ] = 0x00
ICEPAP_VDATA_DTYPECODE["WORD" ] = 0x01
ICEPAP_VDATA_DTYPECODE["DWORD" ] = 0x02
ICEPAP_VDATA_DTYPECODE["LWORD" ] = 0x03
ICEPAP_VDATA_DTYPECODE["FLOAT" ] = 0x04
ICEPAP_VDATA_DTYPECODE["DFLOAT"] = 0x05
ICEPAP_VDATA_DTYPECODE["UBYTE" ] = 0x10
ICEPAP_VDATA_DTYPECODE["UWORD" ] = 0x11
ICEPAP_VDATA_DTYPECODE["UDWORD"] = 0x12
ICEPAP_VDATA_DTYPECODE["ULWORD"] = 0x13
unglobal ICEPAP_VDATA_VTYPECODE
ICEPAP_VDATA_VTYPECODE["PARAMETER"] = 0x1000
ICEPAP_VDATA_VTYPECODE["POSITION" ] = 0x2000
ICEPAP_VDATA_VTYPECODE["SLOPE" ] = 0x4000
ICEPAP_VDATA_SIGNATURE = 0xCAFE
#%UU% vector type array addr
#%MDESC%
# Update an IcePAP data vector with the content of the given
# data array. If the vector does not exist, it will be created,
# otherwise it will be enlarged with the new data.
#
# The type describe the kind of vector data which could be
# "PARAMETER", "POSITION", "SLOPE"
#
# The address given is the destination DRIVER address.
#
# Example:
# icepap_vdata_build vdata1 POSITION mypos 6
#
def icepap_vdata_build '{
local silent
if($# != 4) {
p "Usage: $0 vector type array addr"
p " Ex: $0 vdata1 POSITION posarray 7"
exit
}
silent = 1
if(_icepap_vdata_build("$1", "$2", $3, $4, silent)) {
exit
}
}'
#%IU%(vector_name, type, array, addr, silent)
#%MDESC%
# Update an IcePAP data vector, given by its name.
#
# Returns non null if an error occured.
#
# TODO:
# -check if the given vector type is not already present in the vector
#
# Example:
# short array myparam[4]
# short array mypos[4]
# array_op("fill", myparam)
# array_op("fill", mypos, 10)
# _icepap_vdata_build("vdata1", "PARAMETER", myparam, 7)
# _icepap_vdata_build("vdata1", "POSITION", mypos, 7)
#
# _icepap_send_array("eutmp1", 7, "*PARDAT", vdata1)
# p _icepap_query("eutmp1","7","?pardat 0")
#
def _icepap_vdata_build(vdata_name, vdatat_str, data, addr, silent) '{
local vdata
local data_sz data_ln data_n
local full_sz
local i j k
local header_sz header_ver header_zip
local datat_str datat_cod vdatat_cod
local vdata_append full_old_sz
# From DSP source code:
# typedef struct {
# uint16_t signature; // Signature must be VDAT_SIGNATURE (0xCAFE)
# uint8_t version; // Version of the data vector format. Currently=0
# uint8_t data_offset;// Data offset in dwords = 6 (0x006)
# uint32_t vdat_size; // Full vector size in dwords (4 bytes)
# uint32_t n_values; // number of values in the vector
# uint8_t data_type; // Data type
# uint8_t compression;// Compression algorithm: 0=uncompressed, 1=lzapp
# uint16_t flags; // coding flags and board address
# extdfloat_t firstvalue; // first vector value if incremental
# } vdatheader_t;
# some hardcoded information to be adapted if vector header signature changes
header_sz = 12 # header size in words
header_ver = 0 # version of data vector
header_zip = 0 # compression algo (0==uncompressed)
# check argins validity
if(whatis("data") & 0x0001ffff != 0x00010004) {
_icepap_err
print "Bad data array type"
return(-1)
}
# guess the data size in words
if((data_sz = _icepap_array_size(data)) == -1) {
return(-1)
}
data_n = array_op("rows", data) * array_op("cols", data)
data_ln = data_n * data_sz
# encode data type
datat_str = _icepap_array_type(data)
if(!(datat_str in ICEPAP_VDATA_DTYPECODE)) {
_icepap_err
print "Data array type not supported"
return(-1)
}
datat_cod = ICEPAP_VDATA_DTYPECODE[datat_str]
# encode the vector type
if(!(vdatat_str in ICEPAP_VDATA_VTYPECODE)) {
_icepap_err
printf("Wrong vector type, must be: ")
for(i in ICEPAP_VDATA_VTYPECODE) {
printf("\"%s\" ",i)
}
print ""
return(-1)
}
vdatat_cod = ICEPAP_VDATA_VTYPECODE[vdatat_str]
# calculate the full vector size in words
full_sz = data_ln + header_sz
# check if destination vector is not empty and must be appended
# NOTE MP Jan/2015: the whatis() function does not work
#if(whatis("@vdata") & 0x0001ffff == 0x00010004) {
# if(!index(whatis("dataw", "info"), "ushort")) {
# _icepap_err
# printf("invalid data type for array \"%s\", must be ushort\n", @vdata)
# return(-1)
# }
# vdata_append = 1
#}
vdata_append = (@vdata_name[0] == ICEPAP_VDATA_SIGNATURE)
# allocate vector
ushort array vdata[full_sz]
i = 0
# debug information
if(!silent) {
printf("\tVector name : %s (%s)\n", \
vdata_name, vdata_append?"APPENDING":"CREATED")
printf("\tVector type : %s\n", vdatat_str)
printf("\tData type : %s\n", datat_str)
printf("\tData size : %4d words\n", data_sz)
printf("\tNumber of data : %4d\n", data_n)
printf("\tData length : %4d words\n", data_ln)
printf("\tVector length : %4d words\n", full_sz)
}
# prepare vector header
# signature
vdata[i++] = ICEPAP_VDATA_SIGNATURE
# version + data_offset in dwords
vdata[i++] = header_ver + ((header_sz / 2) << 8)
# full vector size in dwords
vdata[i++] = ((full_sz/2) & 0xffff)
vdata[i++] = ((full_sz/2) >> 16)
# number of values in the vector
vdata[i++] = (data_n & 0xffff)
vdata[i++] = (data_n >> 16)
# data_type + compression
vdata[i++] = datat_cod + (header_zip << 8)
# format + address
vdata[i++] = addr + vdatat_cod
# first double value if incremental
vdata[i++] = 0
vdata[i++] = 0
vdata[i++] = 0
vdata[i++] = 0
# minium check
if(i != header_sz) {
_icepap_err
print "Internal error: wrong header size"
return(-1)
}
# finally add the data
# NOTE MP 2015Sep: bug of array_copy(subarray, ...) on release < 6.02
#array_copy(vdata[i:], data)
ushort array vdata_one[data_sz]
for(j=0;j<data_n;j++) {
array_copy(vdata_one, data[j])
for(k=0;k<data_sz;k++) {
vdata[i++] = vdata_one[k]
}
}
# update vector to return
if(!vdata_append) {
# creating a new vector
ushort array @vdata_name[full_sz]
array_copy(@vdata_name, vdata)
} else {
# appending an existing one
# calculate the full vector size in words
full_old_sz = array_op("rows", @vdata_name) * array_op("cols", @vdata_name)
ushort array vdata_tmp[full_old_sz]
array_copy(vdata_tmp, @vdata_name)
# create a new vector
ushort array @vdata_name[full_sz + full_old_sz]
array_copy(@vdata_name, vdata_tmp, vdata)
}
# normal end
if(0) {
if(!silent) {
_icepap_vdata_dump(@vdata_name)
}
}
return(0)
}'
#%IU%(vector_data)
#%MDESC%
# Print given data vector as a byte array.
# For debug purpose only
#
def _icepap_vdata_dump(vdata) '{
local data_sz data_ln data_n
# vector data type length in words (should be always words array)
data_sz = _icepap_array_size(vdata)
# calculate vector length in bytes
data_n = array_op("rows", vdata) * array_op("cols", vdata)
data_ln = data_n * data_sz * 2
# dump vector data array as a byte array
local ubyte array tmp[data_ln]
array_copy(tmp, vdata)
printf("\tVector as bytes: ")
for(i=0;i<data_ln;i++) {
printf("\\x%02x", tmp[i])
}
print ""
}'
#%UU% vector_name
#%MDESC%
# Print information on given data vector
#
def icepap_vdata_info '{
local vdata_name
local i n idx
vdata_name = "$1"
# update information first
if(_icepap_vdata_info(vdata_name)) {
exit
}
n = ICEPAP_VDATA_INFO[vdata_name]["vectors"]
printf("\tVector name : %s\n", vdata_name)
printf("\tContained vectors : %d\n", n)
for(i=1;i<=n;i++) {
idx = sprintf("%s_%d", vdata_name, i)
printf("\n")
printf("\tVector number : #%d\n", i)
printf("\tDriver address : %d\n", ICEPAP_VDATA_INFO[idx]["address"])
printf("\tType : %s\n", ICEPAP_VDATA_INFO[idx]["type"])
printf("\tNumber of values : %d\n", ICEPAP_VDATA_INFO[idx]["values"])
printf("\tValues type : %s\n", ICEPAP_VDATA_INFO[idx]["dtype"])
}
}'
#%IU%(vector_name, silent)
#%MDESC%
# Update stored information on given data vector.
#
# Returns non null if an error occured.
#
def _icepap_vdata_info(vdata_name, silent) '{
global ICEPAP_VDATA_INFO[]
local flags flags_offset vdatat_cod vdatat_str
local offset
local array_sz full_sz full_sz_offset
local data_n data_n_offset
local datat_cod datat_offset datat_str
local i n idx
# check that the given array is a data vector
# NOTE MP Jan/2015: the whatis() function does not work
if(@vdata_name[0] != ICEPAP_VDATA_SIGNATURE) {
_icepap_err
print "Not an IcePAP data vector"
return(-1)
}
# remove any previous information
_icepap_vdata_cleanup(vdata_name)
# some hardcoded information to be adapted if vector header signature changes
full_sz_offset = 2
data_n_offset = 4
datat_offset = 6
flags_offset = 7
# at least one data vector present
array_sz = array_op("rows", @vdata_name) * array_op("cols", @vdata_name)
for(n=1, offset=0;;n++) {
# new entry
ICEPAP_VDATA_INFO[vdata_name]["vectors"] = n
idx = sprintf("%s_%d", vdata_name, n)
# get vector type
flags = @vdata_name[flags_offset + offset]
vdatat_cod = flags & 0xff00
vdatat_str = ""
for(i in ICEPAP_VDATA_VTYPECODE) {
if(ICEPAP_VDATA_VTYPECODE[i] == vdatat_cod) {
vdatat_str = i
break
}
}
if(vdatat_str == "") {
_icepap_vdata_cleanup(vdata_name)
_icepap_err
print "Invalid data vector data type"
return(-1)
}
ICEPAP_VDATA_INFO[idx]["type"] = vdatat_str
# get DRIVER address
ICEPAP_VDATA_INFO[idx]["address"] = flags & 0xff
# get number of values
data_n = @vdata_name[data_n_offset + offset]
data_n += (@vdata_name[data_n_offset + offset + 1] << 16)
ICEPAP_VDATA_INFO[idx]["values"] = data_n
# get values type
datat_cod= @vdata_name[datat_offset + offset] & 0xff
datat_str= ""
for(i in ICEPAP_VDATA_DTYPECODE) {
if(ICEPAP_VDATA_DTYPECODE[i] == datat_cod) {
datat_str = i
break
}
}
if(datat_str == "") {
datat_str = "UNKNOWN"
}
ICEPAP_VDATA_INFO[idx]["dtype"] = datat_str
# get full vector size in words
full_sz = @vdata_name[full_sz_offset + offset]
full_sz += (@vdata_name[full_sz_offset + offset + 1] << 16)
full_sz *= 2
ICEPAP_VDATA_INFO[idx]["full_sz_words"] = full_sz
# check if there is another data vector to process
offset += full_sz
if(offset >= array_sz) {
break
}
if(@vdata_name[offset] != ICEPAP_VDATA_SIGNATURE) {
break
}
}
# normal end
return(0)
}'
#%IU%(vector_name)
#%MDESC%
# Remove any stored information on given data vector
#
def _icepap_vdata_cleanup(vdata_name) '{
global ICEPAP_VDATA_INFO[]
local i j idx
j = ICEPAP_VDATA_INFO[vdata_name]["vectors"]
for(;j>0;j--) {
idx = sprintf("%s_%d", vdata_name, j)
for(i in ICEPAP_VDATA_INFO[idx]) {
delete ICEPAP_VDATA_INFO[idx][i]
}
}
for(i in ICEPAP_VDATA_INFO[vdata_name]) {
delete ICEPAP_VDATA_INFO[vdata_name][i]
}
}'
#%MACROS%
#%IMACROS%
#%AUTHOR% MP BLISS (Original 02/2015).
# %BR%$Revision: 1.1 $ / $Date: 2017/02/24 11:58:32 $
#%TOC%
|