CRC16 calculation in Tcl - tcl

Im trying to compute the CRC16 of a binary file.
I started by reading 2 Bytes from the Binary file and compute a CRC16 with a Polynome= 1021 and 0xFFFF Initial Value. I used a C code and tried to translate it to TCL. I couldnt use the bytes format because i get by the computation an error about using non numeric string. So i converted the bytes to strings.
proc main {}{
# open binary file
set file_read [open "$input_file" rb]
while {1} {
if {! [eof $fr]} {
append binary_data [read $file_read 2]
}
binary scan [string range $binary_data 0 1] H4 str_bin_data
set CRC_data [CRC_calculation $str_bin_data]
puts " CRC_data := $CRC_data"
}
}
proc CRC_calculation {str_bin_data} {
set Polynome 0x1021
set Highbit 0x8000
set CRC_data 0xFFFF
set byte 0
set bit 0
set data_ln [string length $str_bin_data]
# puts " data_ln := $data_ln"
for {set byte 0} {$byte < $data_ln} {incr byte} {
set CRC_data [ expr {$CRC_data ^ ([lindex $str_bin_data $byte] << 8)} ]
for {set bit 8} {$bit > 0} {incr bit -1} {
if {($CRC_data && $Highbit)} {
set CRC_data [expr {($CRC_data << 1) ^ $Polynome}]
} else {
set CRC_data [expr {$CRC_data << 1}]
}
}
puts " byte_index := $byte"
puts " CRC_data := $CRC_data"
}
return $CRC_data
}
In C when i define a byte array example( first 8 Bytes in the binary file):
unsigned char bytes[3]= {0x55,0x55,0x55,0x55};
then CRC = 0x82b8
In Tcl I dont get the correct value not even a 32 bit CRC value.
Here the C code that i m using:
#include<stdio.h>
#define Polynom 0x1021
#define Highbit 0x8000
unsigned short getCRC(const unsigned char data[])
{
unsigned short rem = 0xFFFF;
unsigned long byte = 0;
int bit = 0;
for (byte = 0; byte < 3; ++byte)
{
rem ^= (data[byte]<< 8);
for (bit = 8; bit > 0; --bit)
{
if (rem & Highbit)
rem = (rem << 1) ^ Polynom;
else
rem = (rem << 1);
}
}
return (rem);
}
int main() {
int rem ;
unsigned char data[]= {0x55,0x55,0x55,0x55};
rem = getCRC (data);
printf("%x", rem);
}

There's a few problems. Firstly, and most importantly, the scanning of the binary data isn't right as we want to end up with unsigned bytes (for parallel operation with that C) and not hex characters. You'd be better with:
# I'm assuming you've got Tcl 8.6, this is how you read 2 bytes as unsigned chars
binary scan [read $file_read 2] "cu*" str_bin_data
# Process the list of parsed byte data here; I'm not sure if you want this in the loop or not
The other big problem is that your CRC calculation isn't correct.
proc CRC_calculation {str_bin_data} {
set Polynom 0x1021
set Highbit 0x8000
set MASK 0xFFFF; # 16 bit mask; for clamping to C unsigned short range
set rem 0xFFFF
# Assume str_bin_data holds a list of unsigned char values
foreach byte $str_bin_data {
set rem [expr {$rem ^ ($byte << 8)}]
foreach _ {7 6 5 4 3 2 1 0} {
set rem [expr {
(($rem << 1) ^ ($rem & $Highbit ? $Polynom : 0)) & $MASK
}]
}
}
return $rem
}
Key observation here? Tcl's numbers are arbitrary precision integers (and IEEE doubles, though not relevant here). This means that you need to clamp the range. Minimally, that would be an AND with 0xFFFF (16-bit mask) after any operation that can increase the number of bits in use, which is just << in this algorithm. That, plus the problems with converting the binary data in the first place, are why things weren't working for you. I've also switched to using foreach as that's fast and clearer for operations where “do every one of them” is the fundamental idea, and merged the inner bits into a single expr (yes, expr expressions can be multiline if you want).
The biggest single problem was that you were passing entirely the wrong thing to the CRC_calculation code. Changing the binary scan is vital.

Related

Does TCL containg built in functions of type get_bits and set_bits?

The get_bits will return specific bits of a value and set_bits will set specific bits of a value to a specified value. Does TCL contain such functions built in or should they be written by the user?
The binary scan command does come close to the get_bits function but is not the same thing.
There's no specific function for getting or setting a particular bit. We can make them.
proc get_bit {value bit} {
expr {($value & (1 << $bit)) != 0}
}
proc set_bit {varName bit {value 1}} {
upvar 1 $varName var
if {$value} {
set var [expr {$var | (1 << $bit)}]
} else {
set var [expr {$var & ~(1 << $bit)}]
}
}
Those will work with integer values of any width; you're not restricted to 32 bits or 64 bits.
# Lots of bits!
set x 123456789012345678901234567890
# Fetch a particular bit
puts [get_bit $x 17]
# Set a bit to 1
set_bit x 78
puts "x = $x"
# Set a bit to 0
set_bit x 75 0
puts "x = $x"

conversion of and operation having a function from c# to tcl

how to do the and operation given as one line statement in tcl in tcl where pcieDeviceControlRegister is a function given as in the code:
code:
pcieDeviceControlRegister = cfgSpace.pcieDeviceControlRegister & (~((uint)0xF));
Reference for pcieDeviceControlRegister function is :
public uint pcieDeviceControlRegister
{
get
{
if (pcieCapabilityOffset != 0)
return (ReadDW((int)(pcieCapabilityOffset + 8) / 4, 0xF)) & 0xFFFF;
else
return 0;
}
set
{
if (pcieCapabilityOffset != 0)
{
uint val = ReadDW((int)(pcieCapabilityOffset + 8) / 4, 0xF)& 0xFFFF0000;
val |= value;
// write should be done with byte enables !!!
WriteDW((int)(pcieCapabilityOffset + 8) / 4, val, 0xF);
}
}
}
You'll have to arrange for the mapping of ReadDW and WriteDW into Tcl, probably by writing a little C or C++ code that makes commands (with the same names) that do those operations. I'm assuming that you've already done that. (SWIG can generate the glue code if you need it.)
Then, we define a command like this:
proc pcieDeviceControlRegister {{newValue ""}} {
global pcieCapabilityOffset
# Filter the bogus setup case early; if this is really an error case though,
# it is better to actually throw an error instead of struggling on badly.
if {$pcieCapabilityOffset == 0} {
return 0
# error "PCIE capability offset is zero"
}
set offset [expr {($pcieCapabilityOffset + 8) / 4}]
if {$newValue eq ""} {
# This is a read operation
return [expr {[ReadDW $offset 0xF] & 0xFFFF}]
} else {
# This is a write operation
set val [expr {[ReadDW $offset 0xF] & 0xFFFF0000}]
# Note that we do the bit filtering HERE
set val [expr {$val | ($newValue & 0xFFFF)}]
WriteDW $offset $val 0xF
return
}
}
With that, which you should be able to see is a pretty simple translation of the C# property code (with a bit of minor refactoring), you can then write your calling code like this:
pcieDeviceControlRegister [expr {[pcieDeviceControlRegister] & ~0xF}]
With Tcl, you don't write casts to different types of integers: Tcl just has numbers (which are theoretically of infinite width) so instead you need to do a few more bit masks in key places.
The conversion of the above code to a method on an object is left as an exercise. It doesn't change very much…

Converting this algorithm in TCL

I need help in converting this algorithm into tcl for my work, I am not so good in tcl language.
Inputs: STA−1, STA−2, STA−3, ..., STA−n
//requests from various stations for channel access
Shared Variables:
for every i, 1 ≤ i ≤ n
counter[i] ∈ { / 0, 1, 2,..., N}, initially 0, updated by stations
Sequence Number, K ∈ { / 0, 1, 2,..., N}, initially 0, will be set to a positive integer
Procedure:
//Initialization
Set sequence number K = m; //based on the action selected
for (i = 1 to n)
counter[i] = 0;
for (i = 1 to n)
{
while (channel access[i])
if (counter[i]! = K)
{
if (channel == idle)
{
if (counter[i]<min(counter[i+1], counter[i+2], ..., counter[i + n]))
access channel;
else
defer access;
}
counter[i]+ +;
}
else
defer access;
}
This is for CPS devices to access internet using a WSN in between..basic network is done but need help with adding this algo to it..
Can someone help me code that algo in tcl?
Your question isn't clear enough.
For syntax, I'd recommend referring TCL online help.
Some quick snippets:
# Inputs: STA−1, STA−2, STA−3, ..., STA−n
set stations [list "STA−1" "STA−2" "STA−3"]
# Shared Variables:
# for every i, 1 ≤ i ≤ n
# counter[i] ∈ { / 0, 1, 2,..., N}, initially 0, updated by stations
array set counter {}
set n 10
set i 0
while {$i < $n} {
set counter($i) 0
incr i
}
The core of your method is converted to this, assuming that counter is converted to an (associative) array, and that channel identifiers are stored in the channel array:
variable K 0
for {set i 1} {$i <= $n} {incr i} {
set counter($i) 0
}
for {set i 1} {$i <= $n} {incr i} {
while {[channelAccess $channel($i)]} {
if {$counter($i) != $K} {
if {[channelIdle $channel($i)]} {
set minimum [getMinimum [expr {$i + 1}] [expr {$i + $n}]]
if {$counter($i) < $minimum} {
accessChannel $channel($i)
} else {
deferAccess $channel($i)
}
}
incr counter($i)
} else {
deferAccess $channel($i)
}
}
}
You'll also need this procedure:
proc getMinimum {from to} {
upvar 1 counter counter
set minVal $counter($from)
for {set i $from} {$i <= $to} {incr i} {
set minVal [expr {min($minVal, $counter($i))}]
}
return $minVal
}
And you'll need to define channelAccess, channelIdle, accessChannel and deferAccess; they're things that your algorithm doesn't specify. There's also nothing to say what various variable are actually updated by. But that's the algorithm converted.
Note the patterns for using for; those are idiomatic Tcl for this sort of thing. Also note the brace positioning; your life will be easiest in Tcl if you use that style.

Reversing every character in a file

I'm in a little trouble here.
Can anyone help me implement a solution that reverses every byte so 0xAB becomes 0xBA but not so "abcd" becomes "dcba". I need it so AB CD EF becomes BA DC FE.
Preferably in C or C++ but it doesn't really matter provided it can run.
So far, I've implemented a UBER CRAPPY solution that doesn't even work (and yes, I know that converting to string and back to binary is a crappy solution) in PureBasic.
OpenConsole()
filename$ = OpenFileRequester("Open File","","All types | *.*",0)
If filename$ = ""
End
EndIf
OpenFile(0,filename$)
*Byte = AllocateMemory(1)
ProcessedBytes = 0
Loc=Loc(0)
Repeat
FileSeek(0,Loc(0)+1)
PokeB(*Byte,ReadByte(0))
BitStr$ = RSet(Bin(Asc(PeekS(*Byte))),16,"0")
FirstStr$ = Left(BitStr$,8)
SecondStr$ = Right(BitStr$,8)
BitStr$ = SecondStr$ + FirstStr$
Bit.b = Val(BitStr$)
WriteByte(0,Bit)
ProcessedBytes = ProcessedBytes + 1
ClearConsole()
Print("Processed Bytes: ")
Print(Str(ProcessedBytes))
Loc=Loc(0)
Until Loc = Lof(0)
Delay(10000)
Thanks for reading.
Reading your PureBasic code (I skipped it at first), it does seem you want to swap endian, even though it's not what your text is asking—0xAB practically always means a byte with decimal value 171, not two bytes, and it's extremely common to display a byte as two hex digits, where you use A-F in your example.
#include <iostream>
int main() {
using namespace std;
for (char a; cin.get(a);) {
char b;
if (!cin.get(b)) {
cout.put(a); // better to write it than lose it
cerr << "Damn it, input ends with an odd byte, is it in "
"the right format?\n";
return 1;
}
cout.put(b);
cout.put(a);
}
return 0;
}
// C version is a similar easy translation from the original code
import numpy
import sys
numpy.fromfile(sys.stdin, numpy.int16).byteswap(True).tofile(sys.stdout)
Original answer:
I'm not sure why you want this (it doesn't convert endian, for example, if you want that), but here you go:
#include <stdio.h>
int main() {
for (char c; (c == getchar()) != EOF;) {
putchar((c & 0xF << 4) | ((int)c & 0xF0 >> 4));
}
return 0;
}
#include <iostream>
int main() {
for (char c; std::cin.get(c);) {
std::cout.put((c & 0xF << 4) | ((int)c & 0xF0 >> 4));
}
return 0;
}
import sys
for line in sys.stdin:
sys.stdout.write("".join(
chr((ord(c) & 0xF << 4) | (ord(c) & 0xF0 >> 4))
for c in line
))
All assume that text translations don't occur (such as \n to \r\n and vice versa); you'll have to change them to opening files in binary mode if that's the case. They read from stdin and write to stdout, if you're unfamiliar with that, so just use programname < inputfile > outputfile to run them.
Reversing the high and low half-byte is possible through a simple arithmetic formula (assuming you operate on unsigned bytes):
reversed = (original % 16) * 16 + (original / 16);
A Haskell solution:
module ReverseBytes where
import qualified Data.ByteString as B
import Data.Bits
import Data.Word
-----------------------------------------------------------
main :: IO ()
main = B.getContents >>= B.putStr . B.map reverseByte
reverseByte :: Word8 -> Word8
reverseByte = flip rotate 4
runghc ReverseBytes.hs < inputfile > outputfile

How can I reverse the ON bits in a byte?

I was reading Joel's book where he was suggesting as interview question:
Write a program to reverse the "ON" bits in a given byte.
I only can think of a solution using C.
Asking here so you can show me how to do in a Non C way (if possible)
I claim trick question. :) Reversing all bits means a flip-flop, but only the bits that are on clearly means:
return 0;
What specifically does that question mean?
Good question. If reversing the "ON" bits means reversing only the bits that are "ON", then you will always get 0, no matter what the input is. If it means reversing all the bits, i.e. changing all 1s to 0s and all 0s to 1s, which is how I initially read it, then that's just a bitwise NOT, or complement. C-based languages have a complement operator, ~, that does this. For example:
unsigned char b = 102; /* 0x66, 01100110 */
unsigned char reverse = ~b; /* 0x99, 10011001 */
What specifically does that question mean?
Does reverse mean setting 1's to 0's and vice versa?
Or does it mean 00001100 --> 00110000 where you reverse their order in the byte? Or perhaps just reversing the part that is from the first 1 to the last 1? ie. 00110101 --> 00101011?
Assuming it means reversing the bit order in the whole byte, here's an x86 assembler version:
; al is input register
; bl is output register
xor bl, bl ; clear output
; first bit
rcl al, 1 ; rotate al through carry
rcr bl, 1 ; rotate carry into bl
; duplicate above 2-line statements 7 more times for the other bits
not the most optimal solution, a table lookup is faster.
Reversing the order of bits in C#:
byte ReverseByte(byte b)
{
byte r = 0;
for(int i=0; i<8; i++)
{
int mask = 1 << i;
int bit = (b & mask) >> i;
int reversedMask = bit << (7 - i);
r |= (byte)reversedMask;
}
return r;
}
I'm sure there are more clever ways of doing it but in that precise case, the interview question is meant to determine if you know bitwise operations so I guess this solution would work.
In an interview, the interviewer usually wants to know how you find a solution, what are you problem solving skills, if it's clean or if it's a hack. So don't come up with too much of a clever solution because that will probably mean you found it somewhere on the Internet beforehand. Don't try to fake that you don't know it neither and that you just come up with the answer because you are a genius, this is will be even worst if she figures out since you are basically lying.
If you're talking about switching 1's to 0's and 0's to 1's, using Ruby:
n = 0b11001100
~n
If you mean reverse the order:
n = 0b11001100
eval("0b" + n.to_s(2).reverse)
If you mean counting the on bits, as mentioned by another user:
n = 123
count = 0
0.upto(8) { |i| count = count + n[i] }
♥ Ruby
I'm probably misremembering, but I
thought that Joel's question was about
counting the "on" bits rather than
reversing them.
Here you go:
#include <stdio.h>
int countBits(unsigned char byte);
int main(){
FILE* out = fopen( "bitcount.c" ,"w");
int i;
fprintf(out, "#include <stdio.h>\n#include <stdlib.h>\n#include <time.h>\n\n");
fprintf(out, "int bitcount[256] = {");
for(i=0;i<256;i++){
fprintf(out, "%i", countBits((unsigned char)i));
if( i < 255 ) fprintf(out, ", ");
}
fprintf(out, "};\n\n");
fprintf(out, "int main(){\n");
fprintf(out, "srand ( time(NULL) );\n");
fprintf(out, "\tint num = rand() %% 256;\n");
fprintf(out, "\tprintf(\"The byte %%i has %%i bits set to ON.\\n\", num, bitcount[num]);\n");
fprintf(out, "\treturn 0;\n");
fprintf(out, "}\n");
fclose(out);
return 0;
}
int countBits(unsigned char byte){
unsigned char mask = 1;
int count = 0;
while(mask){
if( mask&byte ) count++;
mask <<= 1;
}
return count;
}
The classic Bit Hacks page has several (really very clever) ways to do this, but it's all in C. Any language derived from C syntax (notably Java) will likely have similar methods. I'm sure we'll get some Haskell versions in this thread ;)
byte ReverseByte(byte b)
{
return b ^ 0xff;
}
That works if ^ is XOR in your language, but not if it's AND, which it often is.
And here's a version directly cut and pasted from OpenJDK, which is interesting because it involves no loop. On the other hand, unlike the Scheme version I posted, this version only works for 32-bit and 64-bit numbers. :-)
32-bit version:
public static int reverse(int i) {
// HD, Figure 7-1
i = (i & 0x55555555) << 1 | (i >>> 1) & 0x55555555;
i = (i & 0x33333333) << 2 | (i >>> 2) & 0x33333333;
i = (i & 0x0f0f0f0f) << 4 | (i >>> 4) & 0x0f0f0f0f;
i = (i << 24) | ((i & 0xff00) << 8) |
((i >>> 8) & 0xff00) | (i >>> 24);
return i;
}
64-bit version:
public static long reverse(long i) {
// HD, Figure 7-1
i = (i & 0x5555555555555555L) << 1 | (i >>> 1) & 0x5555555555555555L;
i = (i & 0x3333333333333333L) << 2 | (i >>> 2) & 0x3333333333333333L;
i = (i & 0x0f0f0f0f0f0f0f0fL) << 4 | (i >>> 4) & 0x0f0f0f0f0f0f0f0fL;
i = (i & 0x00ff00ff00ff00ffL) << 8 | (i >>> 8) & 0x00ff00ff00ff00ffL;
i = (i << 48) | ((i & 0xffff0000L) << 16) |
((i >>> 16) & 0xffff0000L) | (i >>> 48);
return i;
}
pseudo code..
while (Read())
Write(0);
I'm probably misremembering, but I thought that Joel's question was about counting the "on" bits rather than reversing them.
Here's the obligatory Haskell soln for complementing the bits, it uses the library function, complement:
import Data.Bits
import Data.Int
i = 123::Int
i32 = 123::Int32
i64 = 123::Int64
var2 = 123::Integer
test1 = sho i
test2 = sho i32
test3 = sho i64
test4 = sho var2 -- Exception
sho i = putStrLn $ showBits i ++ "\n" ++ (showBits $complement i)
showBits v = concatMap f (showBits2 v) where
f False = "0"
f True = "1"
showBits2 v = map (testBit v) [0..(bitSize v - 1)]
If the question means to flip all the bits, and you aren't allowed to use C-like operators such as XOR and NOT, then this will work:
bFlipped = -1 - bInput;
I'd modify palmsey's second example, eliminating a bug and eliminating the eval:
n = 0b11001100
n.to_s(2).rjust(8, '0').reverse.to_i(2)
The rjust is important if the number to be bitwise-reversed is a fixed-length bit field -- without it, the reverse of 0b00101010 would be 0b10101 rather than the correct 0b01010100. (Obviously, the 8 should be replaced with the length in question.) I just got tripped up by this one.
Asking here so you can show me how to do in a Non C way (if possible)
Say you have the number 10101010. To change 1s to 0s (and vice versa) you just use XOR:
10101010
^11111111
--------
01010101
Doing it by hand is about as "Non C" as you'll get.
However from the wording of the question it really sounds like it's only turning off "ON" bits... In which case the answer is zero (as has already been mentioned) (unless of course the question is actually asking to swap the order of the bits).
Since the question asked for a non-C way, here's a Scheme implementation, cheerfully plagiarised from SLIB:
(define (bit-reverse k n)
(do ((m (if (negative? n) (lognot n) n) (arithmetic-shift m -1))
(k (+ -1 k) (+ -1 k))
(rvs 0 (logior (arithmetic-shift rvs 1) (logand 1 m))))
((negative? k) (if (negative? n) (lognot rvs) rvs))))
(define (reverse-bit-field n start end)
(define width (- end start))
(let ((mask (lognot (ash -1 width))))
(define zn (logand mask (arithmetic-shift n (- start))))
(logior (arithmetic-shift (bit-reverse width zn) start)
(logand (lognot (ash mask start)) n))))
Rewritten as C (for people unfamiliar with Scheme), it'd look something like this (with the understanding that in Scheme, numbers can be arbitrarily big):
int
bit_reverse(int k, int n)
{
int m = n < 0 ? ~n : n;
int rvs = 0;
while (--k >= 0) {
rvs = (rvs << 1) | (m & 1);
m >>= 1;
}
return n < 0 ? ~rvs : rvs;
}
int
reverse_bit_field(int n, int start, int end)
{
int width = end - start;
int mask = ~(-1 << width);
int zn = mask & (n >> start);
return (bit_reverse(width, zn) << start) | (~(mask << start) & n);
}
Reversing the bits.
For example we have a number represented by 01101011 . Now if we reverse the bits then this number will become 11010110. Now to achieve this you should first know how to do swap two bits in a number.
Swapping two bits in a number:-
XOR both the bits with one and see if results are different. If they are not then both the bits are same otherwise XOR both the bits with XOR and save it in its original number;
Now for reversing the number
FOR I less than Numberofbits/2
swap(Number,I,NumberOfBits-1-I);