rawbin.tcl

#

Copyright 2017, Erik N. Johnson

FILENAME: rawbin.tcl

AUTHOR: erik.johnson@jogle.us

DESCRIPTION: rawbin.tcl is part of the binconvert package. binconvert is a package that reads & writes EEPROM memory files in multiple formats. It converts the data to & from a Tcl representation as a list of data segments, which is available for processing.

rawbin.tcl contains all the support procs to manage input from binary files of no particular format. It assumes a starting address of 0 and packs all data read into one initial segment. When writing out data, it will start at 0 or such other address as the user sets, and will fill in undefined data with bytes of 0xFF or as the user sets.

This package documentation is auto-generated with Pycco: https://pycco-docs.github.io/pycco/

Use "pycco filename" to re-generate HTML documentation in ./docs .

#

Procedures for Raw Binary Format

This format is not really a format. This driver is intended to be used to input flat binary dumps, e.g. memory dumps, to be saved in another format, or to write binary data to output channels that expect raw binary images.


ProcessRawbinInput

#

ProcessRawbinInput is the parser for the readline proc. Since the input file did not have lines, we don't expect more than one lump of data. Use binary scan to convert the whole thing to a list of byte values.

N.B. that there are no checksums or CRCs, and thus no way of detecting a corrupted file unless the corruption makes a line not interpretable.

proc ::binconvert::ProcessRawbinInput {dataIn} {
    set addr 0
    binary scan $dataIn cu* dataL
    return [list DATA $addr $dataL]
}
#

WriteRawbinFile

#

WriteRawbinFile will iterate over the segments of the segment list.

proc ::binconvert::WriteRawbinFile {segmentList outchan {startAddr 0} {fillValue 0x255}} {
#

Scan the list for the end address. Use that to create a list of byte values covering all segments, filled with a value (nominally 0xFF). The list starts at the input startAddr, and segments are expected to be placed within it.

    set maxAddr 0
    foreach {addr dataL} $segmentList {
        if {$addr < $startAddr} {
            set errMsg "Invalid start address: segment starts at $addr,\
                        output file defined to start at $startAddr"
            log::error $errMsg
            error $errMsg
        }
        if {$maxAddr < ($addr + [llength $dataL])} {
            set maxAddr [expr {$addr + [llength $dataL]}]
        }
    }
    set outL [lrepeat [expr {$maxAddr - $startAddr}] $fillValue]
#

We have our filled output list. For each segment, replace the data in the appropriate range with the segment data.

    foreach {addr dataL} $segmentList {
        set offset [expr {$addr - $startAddr}]
        set outL [lreplace $outL $offset [expr {$offset + [llength $dataL] - 1}] {*}$dataL]]
    }
#

After the output list is completely filled, convert it to a binary string and write it to disk. Don't forget to set the output channel to binary too, to keep line feeds from being corrupted.

    set outS [binary format c* $outL]
    chan configure $outchan -translation {binary binary} -encoding binary
    puts $outchan $outS
}