Android Question Convert HEX in ASCII

StarinschiAndrei

Active Member
Licensed User
Longtime User
Hi,
Is there any function that can convert hex 15e in 30 31 35 3E ?
I tried to use:
B4X:
dim val as string     '15e
Log(bc.HexFromBytes (bc.StringToBytes(val,"UTF8")))
but the result is : 313565
 

StarinschiAndrei

Active Member
Licensed User
Longtime User
No worries, it was kinda fun to do that stuff again. I probably spent a couple of days massaging my first packet send/receive routines into shape the first time I did it, so if I've saved you a bit of that same time and heartache, then we're good.

I was mulling over that you might be about to enter the packet-receive swamp (if you're not already knee-deep with those alligators ;-) and the first thing I'd do is pull out the checksum calculation into its own sub so that you can use it for both generating outgoing checksums and checking incoming checksums, eg:

B4X:
Sub CalculateChecksum(PacketBytes() As Byte, I1 As Int, I2 As Int) As Byte()
 
    Dim ControlSum As Int = 0
    For I = I1 To I2
        ControlSum = ControlSum + SignedByteToUnsigned(PacketBytes(I))
    Next
 
    Dim ChecksumBytes(4) As Byte
    'zero shift right left in because computer time is cheap and programmer time is not
    ChecksumBytes(0) = 0x30 + Bit.And(Bit.ShiftRight(ControlSum, 12), 0x000F)
    ChecksumBytes(1) = 0x30 + Bit.And(Bit.ShiftRight(ControlSum,  8), 0x000F)
    ChecksumBytes(2) = 0x30 + Bit.And(Bit.ShiftRight(ControlSum,  4), 0x000F)
    ChecksumBytes(3) = 0x30 + Bit.And(Bit.ShiftRight(ControlSum,  0), 0x000F)

    Return ChecksumBytes
 
End Sub

and then the packet assembly bit collapses down to:

B4X:
'Position 7 = BCC
Dim ChecksumBytes() As Byte = CalculateChecksum(PacketBytes, 1, PutPtr - 1)    'Position 2 to Position 6
For I = 0 To 3
    PacketBytes(PutPtr) = ChecksumBytes(I)
    PutPtr = PutPtr + 1
Next

and on the disassembly side you'd have something like:

B4X:
'Position 7 = BCC
Dim ChecksumBytes() As Byte = CalculateChecksum(PacketBytes, 1, ChecksumPosition - 1)    'Position 2 to Position 6
Dim ChecksumOkFlag As Boolean = True    'optimism reigns supreme
For I = 0 To 3
    If PacketBytes(ChecksumPosition + I) <> ChecksumBytes(I) Then
        ChecksumOkFlag = False
        Exit
    End If
Next

BTW I did see you were using strings originally, which I can understand as a sin committed in the heat of the coding battle ;-) but the performance hit is like 100-fold or more. If you want to make it out of this low-level swamp alive, best avoid strings like the plague. Use bytes instead, or if the signed-vs-unsigned stuff gets too annoying, use shorts instead (still signed, but able to handle full "proper" 8-bit range 0..255) and convert them at handover to/from the serial stream. The maximum packet size was under 255 bytes, so worst-case is you waste maybe 500 bytes to have your packet assembly/disassembly buffers as easy-to-use shorts instead of pita bytes. Cheap insurance if you ask me, and you probably even reclaim some of that space through smaller/simpler code in that area.

What could possibly go wrong?!?!
Thank you emexes .... you saved me a lot of time. Before you sent me the code I spent 2 days in front of computer with no results. Your code is amazing.
Now i don't know what goes wrong. I'm digging the rest of the protocol communication ... i hope the rest of think will go smooth.
 
Upvote 0

emexes

Expert
Licensed User
"What could possibly go wrong?!?!" is my usual positive refrain when we're getting close to a solution and everything seems to be working like it should... usually it's closely followed by being bitten from behind by an alligator I didn't see coming....

So: you're not alone.

;-)
 
Upvote 0

emexes

Expert
Licensed User
The way that I received incoming packets was with a buffer (ideally large enough to hold the longest packet possible, and at least large enough to hold the longest packet that I need to receive) and putptr of where the next received byte goes in that buffer, and a state, where:

state 0 = waiting for the sync byte (first byte of the packet), and then when we get that:
state 1 = receiving the fixed-size packet header
state 2 = receiving the variable-size payload/data
state 3 = receiving the fixed-size packet "tailer" (or whatever the opposite of header is)

and a count of how many bytes are still to be received when in state 1, 2 or 3. When that count reaches zero, then we move on to the next state. If we receive invalid bytes (eg, if we're in state 2 receiving data, and we get a byte less than 0x20) then clearly the packet is invalid and we just move back to state 0 and wait for the next packet.

so the code looks something like (I'm just banging this out, so there is *no* way it will work first go)

B4X:
initialize:
    dim rxbuffer(bigenough)
    rxstate = 0

sub handlerx( rxchar )

    if rxstate = 0 then
        if rxchar = syncbyte then
            rxbuffer(0) = rxchar
            rxputptr = 1    'sync at 0, next byte goes here
            rxmoretocome = 5    'remainder of header (already got sync byte)
            rxstate = 1    'let's get this show on the road...
        else
            'noise on line, or idle sync or keep-alive, or remainder of previous invalid packet
        end if
    else
        buffer(rxputptr) = rxchar
        rxputptr = rxputptr + 1
        rxmoretocome = rxmoretocome - 1

        select case rxstate
            case 1:    'receiving header
                if rxmoretocome = 0 then
                    if header-looks-good then
                        datastartsat = rxputptr    'save this rather than recalculate it later
                        rxmoretocome = (buffer(3) - 0x20) - 2    'LEN but 2 already received as part of header
                        rxstate = 2
                    else  
                        rxstate = 0    'packet bad - log it?
                    end if
                end if

            case 2:    'receiving payload
                if rxchar < 0x20 then  
                    rxstate = 0    'packet bad - log it?
                else if rxmoretocome = 0 then
                     dataendsat = rxputptr - 1
                     tailerstartsat = rxputptr
                     rxmoretocome = 6    'size of tailer
                     rsstate = 3
                end if

            case 3:    'receiving tailer
                if rxmoretocome = 0 then
                    if tailer-looks-good then
                        checksum = checksum(rxbuffer(), 1, tailerstartsat) then    'checksum excludes first byte, includes first byte of tailer
                        checksumstartsat = tailerstartsat + 1    'iirc, tailer had an extra byte between data and checksum
                        okflag = true
                        for i = 0 to 3
                            if rxbuffer(checksumstartsat + i) <> checksum(i) then
                                okflag = false
                                exit
                            end if
                        next i

                        if okflag then
                            'we have a valid packet, payload/data is in rxbuffer at datastartsat..dataendsat
                        end if
                    end if

                    rxstate = 0    'regardless of whether tailer/checksum are good or bad
                end if

            case else:
                'wtf, who's clobbering my variables?!?!

         end select
    end if

end sub
 
Upvote 0

emexes

Expert
Licensed User
If the protocol is half-duplex, then it can be simpler to have a state 4 = valid packet received and in buffer, which the main program checks regularly and, if it finds a packet waiting, processes it and then sets state = 0 to reenable the receiving process

B4X:
...
    end if
else if rxstate = 4 then
    'not expecting to receive anything until main program has handled previous packet and requested more
else
    buffer(rxputptr) = rxchar
...

and

B4X:
...
                if okflag then
                    rxstate = 4    'we have a valid packet, payload/data is in rxbuffer at datastartsat..dataendsat
                end if
            end if

            if rxstate <> 4 then    'if we didn't mark packet as good
                rxstate = 0    'then it must have been bad
            end if
        end if

    case else:
        'wtf, who's clobbering my variables?!?!

end select
 
Upvote 0

StarinschiAndrei

Active Member
Licensed User
Longtime User
"What could possibly go wrong?!?!" is my usual positive refrain when we're getting close to a solution and everything seems to be working like it should... usually it's closely followed by being bitten from behind by an alligator I didn't see coming....

So: you're not alone.

;-)
Very nice.
 
Upvote 0

Similar Threads

Top