Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] .mem file reading byte by byte in tcl

Status
Not open for further replies.

telangamey_ei

Junior Member level 1
Joined
Nov 11, 2014
Messages
19
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
163
Hi,

I have a .mem file with for ex. below hex data in it
----------------------
ABCDEF11
22334455
----------------------

Now, I want to read only 1 byte at a time (i.e. First time AB, second time CD
& so on) till my data end.

I want this to be done in TCL. Can some one please provide me an script for
the same.

Thanks
 

Can some one please provide me an script for the same.

I guess there is no spoon feeding in this forum.

Have you tried out anything yourself? If yes, then show us that.
 

Hi Paul,

I understand there is no spoon feeding on this forum,
but being a new bee to TCL I want to try this out.

I searched a lot but not able to find out proper replies.

I tried with "Split" command & creating different "for loops"
but nothing work out.

Even some kind of flow diagram would be helpful for me as
a start point.

Again not looking for spoon feeding but a flow. :p

Thanks
 

Hi,

I write something like this

Code:
set f [open "F:/test_tcl/mem.ini" r]
set out [open "F:/test_tcl/mem_wr.ini" w]
seek $f 0
set s [read $f 2]
puts $out "$s"
seek $f 2
set s [read $f 2]
puts $out "$s"
seek $f 4
set s [read $f 2]
puts $out "$s"
seek $f 6
set s [read $f 2]
puts $out "$s"
seek $f 9
set s [read $f 2]
puts $out "$s"
seek $f 11
set s [read $f 2]
puts $out "$s"
close $out

and it is working. I want this "seek" to go in
a loop. But whenever I am trying to do this,
it fails.

What could be the best way to make it in a loop.
 
Last edited by a moderator:

Use gets to read the entire line, without the linefeed:
Code:
gets $fh line
then use a regexp to extract the 4 bytes:
Code:
regexp {(..)(..)(..)(..)} $line matched byte1 byte2 byte3 byte4
Stick those two statements inside a loop, with whatever else you want done to the bytes.

I'm sure some Tcl guru could do this in a more efficient manner, but this is the first way that comes to mind.
 

I'm pretty sure read is impure and modifies $f's read pointer.

you should be able to just read while [eof $f] == 0. if not, you should be able to use "tell" and math in order to get the next argument for seek.
 

I'm pretty sure read is impure and modifies $f's read pointer.
Not sure what you are trying to say here.
This is what Tcl's read command does:
https://wiki.tcl.tk/1182
If that is considered "impure" then so be it, it's just the way it's supposed to work.

you should be able to just read while [eof $f] == 0. if not, you should be able to use "tell" and math in order to get the next argument for seek.
I'm not sure why you would suggest something like this? Using seek and tell and math doesn't help the OP read this well formatted data. The OPs problem seemed to stem from an issue with the LF being in the character channel stream. This would also require a different script depending on the file format, unix/dos, which would make the loop even more complicated.

Just read the line like I suggested in #5 and then parse the resulting string into the individual 2 character hex bytes. No reason to make anything a "number" (e.g. everything is a string) and use math to extract the bytes. Hell the OP could just read the line and shift the characters one by one building each byte...(but my suggestion is way easier)

Of course my original suggestion using regex is probably somewhat slower than some other implementations (Regex being a somewhat slow process and Tcl having had a poor implementation of it), but considering they are unlikely concerned about ms of time difference in the script...why care?.

- - - Updated - - -

Here is code that reads the following file in:
Code:
12345678
9abcdef0
AAAA5555
F0F0F0F0
and spits out this:
Code:
12
34
56
78
9a
bc
de
f0
AA
AA
55
55
F0
F0
F0
F0
F0
F0
F0
F0

Note this code does not write the data to another file, that is left to the reader. :)
Code:
proc byte_me {file {eolchar "\n"}} {
  set f [open $file r]
  while {![eof $f]} {
    gets $f line
    regexp {(..)(..)(..)(..)} $line matched byte1 byte2 byte3 byte4
    puts "$byte1\n$byte2\n$byte3\n$byte4"
  }
  close $f
}

Took all of 3 mins to write and test, probably against my better judgement I should have just supplied the entire code in post #5.

On a Tcl prompt %
source byte_me.tcl
byte_me <filename_to_byte>

- - - Updated - - -

Oops, I just noticed you wanted to deal with each byte separately...
Code:
proc byte_me {file {eolchar "\n"}} {
  set f [open $file r]
  while {![eof $f]} {
    gets $f line
    regexp {(..)(..)(..)(..)} $line matched byte1 byte2 byte3 byte4
    foreach byte [list $byte1 $byte2 $byte3 $byte4] {
      puts "$byte, i.e. the stuff you want to do to each byte separately"
    }
  }
  close $f
}
 

Hi ads-ee ,

Thanks for your such a nice & detailed explanation.

This helps me to cross one ladder & I am able to read from
my file byte by byte.

The another challenge here is rather than reading from every
line I want it to be read from specific sets of line.

For Ex:- I have a text file with around 30,000 lines in it. Each line
contains 16 byte. Out of which as per your code I have read initial
4 bytes from every line.

Now, I want to read same 4 byte but from line 1, 64, 127, 190......
i.e. every 64th line till "eof".

I tried multiple things looking here and there but not able to do it.

Any idea would be helpful.

Thanks
 

OK.... here is the peace of code which does this job.

It reads line # 64, 128, 192 ...... & so on till EOF &
reads initial 1 byte out of those lines.

Pasting it below if someone needs in future.

Code:
set fp [open "F:/test_tcl/mem.ini" r]
set out [open "F:/test_tcl/mem_wr.ini" w]
set count 0
set rem 0
while {[gets $fp line]!=-1} {
    incr count
    set rem [expr {$count%64}]
    if {$rem==0} {
       set result [string range $line 0 1]
       puts "Required word(s) : $result"
       puts $out "$result"
    }
}
close $fp
close $out

Thanks
 
Last edited by a moderator:

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top