Decrypt Hidden Message with bitwise operator - c

I encountered this exercise where it asks you to Decrypt a hidden message in the encrypted code in the picture below.
This exercise is related to bitwise operators , so that I assume we need to use " XOR " operator to decrypt the code with 2-digit keys ranging from 00 to 99.
Here's my code.
char input[9] = "dEsxDI^I" , decrypt[9]; // Variable Declarations and Initializations.
int key;
printf("\n\n\nDecrpytion for the Encrypted code \"dEsxDI^I\" :\n\n\n");
for(key = 0 ; key <= 99 ; key++) // 00 to 99 Key Testing.
{
for (int i = 0; i < 8; i++) // Decryption Process.
{
decrypt[i] = input[i] ^ key;
printf("%c", decrypt[i]);
}
printf(" = Key No (%d)\n\n\n", key); // Displays Key No for each decryption.
}
printf("\n\n");
return 0;
The message I decrypted is " Hi_There " with the encryption key of " 44 ".
Just wondering is it the correct message or not? Since that's the most logical message of all the messages I decrypted.
There's no solution provided for this exercise , so I'm curious.
So , what are your output guys?

The message I decrypted is " Hi_There " with the encryption key of "
44 ". Just wondering is it the correct message or not?
There are no firm directions about whether your solution to the 8-character cipher must be an 8-character solution, but that is the general case. Absent clear instruction ("Your solution may, or may not, contain all characters in the cipher."), I would look for a solution that included 8-chars.
Though you have not provided specifics of your code, a simple brute-force loop over all possible keys is about as good as anything else. Since you are not provided with the solution, you cannot do any comparisons along the way. The best you can do is loop over all keys, applying it to each character in your cipher and outputting the result -- and then using you "good ole eyeballs" to pick out a solution. (If you knew the solution would be all upper/lower case characters -- you could impose that check before outputting each result for manual inspection).
It's not clear if you were told to XOR the key with each char, or whether you were just supposed to try all reasonable bitwise operations, but a general OR or XOR is a good place to start.
Putting that together for XOR, you could do something similar to:
#include <stdio.h>
int main (void) {
char *buf = "dEsxDI^I";
for (int key = 0; key < 100; key++) { /* loop over all keys */
char *p = buf; /* output key (and char) */
printf ("key: %2d ('%c') ", key, key >= ' ' ? key : 0);
while (*p) /* loop over all chars */
putchar (*p++ ^ key); /* output decrypted char */
putchar ('\n'); /* tidy up with '\n' */
}
return 0;
}
Example Use/Output
$ ./bin/keyfind2
key: 0 ('') dEsxDI^I
key: 1 ('') eDryEH_H
key: 2 ('') fGqzFK\K
key: 3 ('') gFp{GJ]J
key: 4 ('') `Aw|#MZM
key: 5 ('') a#v}AL[L
<snip>
key: 12 ('') hItHERE
<snip>
key: 43 ('+') OnXSobub
key: 44 (',') Hi_There
key: 45 ('-') Ih^Uidsd
<snip>
Using XOR to appy to the key and using the manual eyeballs to scan for solutions, key: 12 ('') hItHERE looks promising, but then it is only a 7-char solution, continuing key: 44 (',') Hi_There provides an 8-char solution and would be the better of the two answers.
So, "Yes", I think you found the correct solution.
Without Pointers using String Indexes
Since the use of the pointer p to iterate over your cipher string in buf seems to have left you scratching your head (don't worry, it will all soak in over time), you can easily do exactly the same thing with string indexes. A for loop is just as easily used with indexes. Eliminating pointers and using string indexes, you could do the following:
#include <stdio.h>
int main (void) {
char *buf = "dEsxDI^I";
for (int key = 0; key < 100; key++) { /* loop over all keys */
printf ("key: %2d ('%c') ", key, key >= ' ' ? key : 0);
for (int i = 0; buf[i]; i++) /* loop over all chars */
putchar (buf[i] ^ key); /* output decrypted char */
putchar ('\n'); /* tidy up with '\n' */
}
return 0;
}
(output is exactly the same)
Your question regarding the use of the ternary operator in the printf statement is a good question for someone not familiar with it. The ternary operator is a shorthand for an if/else statement where the result of the expression is based on a given test condition. Essentially the ternary operator is:
condition ? if_true_value : if_false_value
In my printf statement I simply do:
printf ("key: %2d ('%c') ", key, key >= ' ' ? key : 0);
Obviously the integer value of key is used with the %2d conversion specifier to insure all key values are printed two characters wide (that's the purpose of the 2 field-width specifier. Now let's just look at what character I want to print through %c.
key >= ' ' ? key : 0 // huh?
It's easy. The first printable ASCII value is 0x20 (hex) or 32 decimal which corresponds to the ' ' (space) character. See ASCII table below. So what is my test condition? If (key >= ' ') greater or equal to space. If it is, just print the character represented by key. If it isn't, then print the nul-character (which is decimal 0 or the equivalent character '\0' -- which just takes more typing). You could do the same thing with:
if (key >= ' ')
printf ("key: %2d ('%c') ", key, key);
else
printf ("key: %2d ('') ", key);
(it's just more typing :)
ASCII Table
Char Dec Oct Hex | Char Dec Oct Hex | Char Dec Oct Hex | Char Dec Oct Hex
-------------------------------------------------------------------------------------
(nul) 0 0000 0x00 | (sp) 32 0040 0x20 | # 64 0100 0x40 | ` 96 0140 0x60
(soh) 1 0001 0x01 | ! 33 0041 0x21 | A 65 0101 0x41 | a 97 0141 0x61
(stx) 2 0002 0x02 | " 34 0042 0x22 | B 66 0102 0x42 | b 98 0142 0x62
(etx) 3 0003 0x03 | # 35 0043 0x23 | C 67 0103 0x43 | c 99 0143 0x63
(eot) 4 0004 0x04 | $ 36 0044 0x24 | D 68 0104 0x44 | d 100 0144 0x64
(enq) 5 0005 0x05 | % 37 0045 0x25 | E 69 0105 0x45 | e 101 0145 0x65
(ack) 6 0006 0x06 | & 38 0046 0x26 | F 70 0106 0x46 | f 102 0146 0x66
(bel) 7 0007 0x07 | ' 39 0047 0x27 | G 71 0107 0x47 | g 103 0147 0x67
(bs) 8 0010 0x08 | ( 40 0050 0x28 | H 72 0110 0x48 | h 104 0150 0x68
(ht) 9 0011 0x09 | ) 41 0051 0x29 | I 73 0111 0x49 | i 105 0151 0x69
(nl) 10 0012 0x0a | * 42 0052 0x2a | J 74 0112 0x4a | j 106 0152 0x6a
(vt) 11 0013 0x0b | + 43 0053 0x2b | K 75 0113 0x4b | k 107 0153 0x6b
(np) 12 0014 0x0c | , 44 0054 0x2c | L 76 0114 0x4c | l 108 0154 0x6c
(cr) 13 0015 0x0d | - 45 0055 0x2d | M 77 0115 0x4d | m 109 0155 0x6d
(so) 14 0016 0x0e | . 46 0056 0x2e | N 78 0116 0x4e | n 110 0156 0x6e
(si) 15 0017 0x0f | / 47 0057 0x2f | O 79 0117 0x4f | o 111 0157 0x6f
(dle) 16 0020 0x10 | 0 48 0060 0x30 | P 80 0120 0x50 | p 112 0160 0x70
(dc1) 17 0021 0x11 | 1 49 0061 0x31 | Q 81 0121 0x51 | q 113 0161 0x71
(dc2) 18 0022 0x12 | 2 50 0062 0x32 | R 82 0122 0x52 | r 114 0162 0x72
(dc3) 19 0023 0x13 | 3 51 0063 0x33 | S 83 0123 0x53 | s 115 0163 0x73
(dc4) 20 0024 0x14 | 4 52 0064 0x34 | T 84 0124 0x54 | t 116 0164 0x74
(nak) 21 0025 0x15 | 5 53 0065 0x35 | U 85 0125 0x55 | u 117 0165 0x75
(syn) 22 0026 0x16 | 6 54 0066 0x36 | V 86 0126 0x56 | v 118 0166 0x76
(etb) 23 0027 0x17 | 7 55 0067 0x37 | W 87 0127 0x57 | w 119 0167 0x77
(can) 24 0030 0x18 | 8 56 0070 0x38 | X 88 0130 0x58 | x 120 0170 0x78
(em) 25 0031 0x19 | 9 57 0071 0x39 | Y 89 0131 0x59 | y 121 0171 0x79
(sub) 26 0032 0x1a | : 58 0072 0x3a | Z 90 0132 0x5a | z 122 0172 0x7a
(esc) 27 0033 0x1b | ; 59 0073 0x3b | [ 91 0133 0x5b | { 123 0173 0x7b
(fs) 28 0034 0x1c | < 60 0074 0x3c | \ 92 0134 0x5c | | 124 0174 0x7c
(gs) 29 0035 0x1d | = 61 0075 0x3d | ] 93 0135 0x5d | } 125 0175 0x7d
(rs) 30 0036 0x1e | > 62 0076 0x3e | ^ 94 0136 0x5e | ~ 126 0176 0x7e
(us) 31 0037 0x1f | ? 63 0077 0x3f | _ 95 0137 0x5f | (del) 127 0177 0x7f

I did XOR, ~XOR, AND, NAND, OR, NOR, left-shift, right-shift operations on your decrypted message.
naturally as any of us would have thought the answer key is 44.
I did not get any other readable message from that String.
although If you consider all possibilities :
XOR:
key 12 : hItHERE
key 44 : Hi_There
key 112 : 49.9____
replace underscores with spaces(not unprintable chars, just empty space)
OR:
key 14 : no~no~o
key 46 : no~no~o
yes they both are same, in fact OR produces a lot of Strings with repeating chars like '{{{{{{{{'
~XOR:
key 243: hItHERE
key 211: Hi_There
Now the definition of readable message depends on every individual.
hItHERE might be some marker for aerial strike.
no~no~o might be a call for help or denial of something.
49.9 might be the quantity of some secret ingredient in a bio-weapons lab.
0~99 is quite a limited range.

A goal should be to to automate the detection mechanism. Rather than find the decrypted phrase from an exhaustive list, form code than does it.
With some minor modifications to OP's code, the below calls various valid() to assess the decryption validity.
Recommend that OP further adjust valid() until it provides 1 "best" decryption. Then the "formula" for decryption is found.
For fun: Try finding the phone number of this spy and Google to determine the name. Her encrypted data is "0>?%=;81". Adjust valid() accordingly.
#include <stdio.h>
#if 1
int valid(const char *decrypt) {
size_t end = strspn(decrypt, " ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
return end == 8;
}
#else
int valid(const char *decrypt) {
size_t end = strspn(decrypt, " ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz");
if (end != 8) return 0;
for (int i=1; i<8; i++) {
if (isupper(decrypt[i-1]) && isupper(decrypt[i])) { //reject paired capital letters
return 0;
}
}
return 1;
}
#endif
int main(void) {
const char input[9] = "dEsxDI^I";
printf("Decryption for the Encrypted code \"dEsxDI^I\" :\n\n");
for (int key = 0; key <= 99; key++) {
char decrypt[9] = ""; // Variable Declarations and Initializations.
for (int i = 0; i < 8; i++) {
decrypt[i] = (char) (input[i] ^ key);
}
if (valid(decrypt)) {
printf("Key No %2d Decrypt:<%s>\n", key, decrypt);
}
}
return 0;
}
Output - 1st valid()
Decryption for the Encrypted code "dEsxDI^I" :
Key No 1 Decrypt:<eDryEH_H>
Key No 10 Decrypt:<nOyrNCTC>
Key No 11 Decrypt:<oNxsOBUB>
Key No 16 Decrypt:<tUchTYNY>
Key No 17 Decrypt:<uTbiUXOX>
Key No 22 Decrypt:<rSenR_H_>
Key No 28 Decrypt:<xYodXUBU>
Key No 29 Decrypt:<yXneYTCT>
Key No 39 Decrypt:<CbT_cnyn>
Key No 42 Decrypt:<NoYRnctc>
Key No 43 Decrypt:<OnXSobub>
Key No 44 Decrypt:<Hi_There>
Key No 48 Decrypt:<TuCHtyny>
Key No 49 Decrypt:<UtBIuxox>
Key No 60 Decrypt:<XyODxubu>
Key No 61 Decrypt:<YxNEytct>
Output - 2nd valid()
Decryption for the Encrypted code "dEsxDI^I" :
Key No 22 Decrypt:<rSenR_H_>
Key No 39 Decrypt:<CbT_cnyn>
Key No 44 Decrypt:<Hi_There>

Related

Synchronous baud rate (RFC2217) encode/decode

I'm trying to implement RFC2217 in my code but I can't understand how the last parity bit (46H and 28H) is generated.
I'm using RS485 to Ethernet device.
What will be the code, if I'm using 2400,E,8,1?
Is it: 55 AA 55 09 60 1B XX?
Is 1B right?
What will be XX?
User manual: page 42 in https://www.sarcitalia.it/file_upload/prodotti//USR-N520-Manual-EN-V1.0.4.pdf
In the field for the baud rate you missed the MSByte. This field shall be 00 09 60.
Yes, 1B for "E,8,1" is correct. BTW, the table lists 2 bits for the 1-bit fields of "stop bit" and "parity enable", which is quite irritating.
The field "parity" is actually just a sum, without the header and the MSBit cleared. (I don't grasp the text of the explanation, but the document seems to be low quality anyway.)
01 C2 00 03: 0x01 + 0xC2 + 0x00 + 0x03 = 0xC6; without bit 7 = 0x46.
00 25 80 03: 0x00 + 0x25 + 0x80 + 0x03 = 0xA8; without bit 7 = 0x28.
Your telegram 00 09 60 1B: 0x00 + 0x09 + 0x60 + 0x1B = 0x84; without bit 7 = 0x04. So XX is 04.

I am Using PSoC 5. I want to know about how to convert 8-Byte hexadecimal into decimal after reading from EEPROM

EEPROM Data:
0000: 88 77 66 55 44 33 22 11 00 00 00 00 00 00 00 00
0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
I am saving the result after reading 0th row of EEPROM in array
Ex - Uint8 EEPROM_res[8];
EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};
I want to convert HexaDecimal(0x8877665544332211) into decimal (9833440827789222417) and save the decimal value into integer data type for further comparison. What is the easiest way of conversion of 8-Byte Hexadecimal?
Can you share the algorithm? – Shivangi Kishore
Converting base 10 (seconds) to base 60 (hours:minutes:seconds)
4321 seconds (in base 10) to base 60.
60^0 = 1
60^1 = 60
60^2 = 3600
60^3 = 216000
(just like 10^0 = 1, 10^1 = 10 and 10^2 = 100 ... base 10, 2^0 = 1, 2^1 = 2, 2^2 = 4 and so on base 2)
So 4321 is less than 216000 but greater than 3600 so we can shortcut and start there
4321 / 3600 = 1 remainder 721
721 / 60 = 12 remainder 1
So 4321 base 10 converted to base 60 (using base 10 to do the math) is 01:12:01
base 2 to base 10 using a base 2 computer is no different.
10 factors into 2 and 5, 2 factors into 2, so you cannot do base 8 (octal) to base 2 shortcuts nor can you do base 16 (hex) to base 2 shortcuts. Have to do it the long way.
EDIT
Another approach that may be more useful to you is to work from the other end. Same math just done using remainders instead of results. Makes for an easier algorithm to program.
4321 / 60 = 72 remainder 1
72 / 60 = 1 remainder 12
1 / 60 = 0 remainder 1
conversion to base 60: 01:12:01
1234 / 10 = 123 remainder 4
123 / 10 = 12 remainder 3
12 / 10 = 1 remainder 2
1 / 10 = 0 remainder 1
conversion to base 10: 1234
Long division in binary is the same but simpler than in a base greater than 2 because the divisor on each step through the denominator can either go into the test value 0 times or 1 time. binary...base 2...
Also if you think through long division (254 / 5 or 0xFE / 0x5)
------------
101 ) 11111110
this is the first test cases that is non-zero
001
------------
101 ) 11111110
101
and you keep going
001
------------
101 ) 11111110
101
---
10
and
0011
------------
101 ) 11111110
101
---
101
101
---
0
and
00110010
------------
101 ) 11111110
101
---
101
101
---
0111
101
---
100
and so 0xFE / 5 = 0x32 remainder 4, but the key here is that I could
do that in hardware with a hardware divide instruction if I have say an 8 bit divide instruction and want to divide an infinitely long number.
If my next (let's say) four digits were 1010:
0001110
101 1001010
101
===
1000
101
===
111
101
===
100
0xFEA / 5 = 0x32E remainder 4
So now I have divided a 12 bit number using an 8 bit divider instruction and I can do this all day long until I run out of ram. 8 bits, 88 bits, 888 bits, 8888 bits, a million bits divided by a small number like 5 or 10.
Or if you keep working on this you find that compilers often use multiply we also know from grade school (since all of this problem is solved with grade school math).
x / 10 = x * (1/10)
More likely to find a hardware multiply than a divide and the multiply is often fewer clocks, etc.
unsigned int fun ( unsigned int x )
{
return(x/10);
}
00000000 <fun>:
0: e59f3008 ldr r3, [pc, #8] ; 10 <fun+0x10>
4: e0802093 umull r2, r0, r3, r0
8: e1a001a0 lsr r0, r0, #3
c: e12fff1e bx lr
10: cccccccd stclgt 12, cr12, [r12], {205} ; 0xcd
0000000000000000 <fun>:
0: 89 f8 mov %edi,%eax
2: ba cd cc cc cc mov $0xcccccccd,%edx
7: f7 e2 mul %edx
9: 89 d0 mov %edx,%eax
b: c1 e8 03 shr $0x3,%eax
e: c3 retq
and other instruction sets, the compiler multiplies by 1/5 then compensates (base 10, 10 factors to 2 and 5, base 2, 2 factors to 2 a common factor).
But if your hardware doesn't have a multiply or divide the compiler should still handle the basic C language variable types, long, int, short, char. And you can cascade those all day long.
unsigned int fun ( unsigned int x )
{
unsigned int ra;
unsigned int rb;
unsigned int rc;
ra=((x>>4)&0xFF)/5;
rb=((x>>4)&0xFF)%5;
rb=(rb<<4)|(x&0xF);
rc=rb/5;
ra=(ra<<4)|rc;
return(ra);
}
test it on the development machine
#include <stdio.h>
extern unsigned int fun ( unsigned int );
int main ( void )
{
printf("%X\n",fun(0xFEA));
return(0);
}
and the output is 0x32E.
And that really completes it everything you need to know (well you already knew from grade school) to do the conversion with the tools you have available.
If instead you are looking for some big math library for some compiler for some target, having us google things for you is not a Stack Overflow question and should be closed as seeking external or third party libraries.
Now as pointed out
save the decimal value into integer data type for further comparison
makes no sense whatsoever, if you want to take some number and then save it for further comparison on a computer, that function looks like this
void fun ( void )
{
}
It is already in that form you want it to be a integer that means some variable (larger than C supports so that is yet another problem with the wording of the question) so that means binary not decimal, so it is already in a future comparable integer form.
If you want to represent that number visually (as in a human viewable printout) in some base then you need to convert that into something that can be viewed be it base 2 (binary), base 8 (octal), base 16 (hex), base 10 (decimal) and so on.
The bits 11111111 in the computer if I want to see those in binary then
"11111111" in octal "377" in hex "FF" in decimal "255" all of which require an algorithm to convert. Octal and hex of course being the simplest, don't need to use a division routine to convert to octal, base 8, factors are 222 base 2 factors are 2 so 2^3 vs 2^1
11111111 / 8 = 11111111 >> 3 = 11111 r 111
11111 / 8 = 11111 >> 3 = 11 r 111
11 / 8 = 11 >> 3 = 0 r 11
377
Base 10 though you have to go the long way and actually do the division and find the remainder until the result of the division in the loop is 0.
10 has factors 2 and 5, 2 has factors 2 you can't shift your way through it. Base 100, 10*10, and base 10 you can shift your way through (just like base 2 to base 4) but base 10 from base 2, can't.
11111111 / 10 = 11001 r 101
11001 / 10 = 10 r 101
10 / 10 = 0 r 10
255
Which of course is why we greatly prefer to view stuff on the computer in hex rather than decimal.
Once in decimal though
"for further comparison"
once you get it to base 10 then the only reasonable comparison you can do with other base 10 numbers is a string compare or an array compare, from the above example the two more common ways you would store that conversion is 0x32, 0x35, 0x35, 0x00 or 0x02, 0x05, 0x05 with some length knowledge.
You can't do greater than less than without a whole lot of work. Equal vs not equal you could do in base 10 bit it is not in integer form.
So your question doesn't make any sense.
Also assume this is a multi part typo:
EEPROM_res = {88, 77, 66, 55, 44, 33, 22, 11};
which is the same as
EEPROM_res = {0x58,0x4D,0x42,0x37,0x2C,0x21,0x16,0x0B};
Neither of which are
EEPROM_res = {0x88,0x77,0x66,0x55,0x44,0x33,0x22,0x11};
Which is what your first 8 bytes of eeprom dump showed in hexadecimal as you mentioned and is somewhat obvious.
Nor are they
EEPROM_res[19] = {0x39,0x38,0x33,0x33....and so on
or
EEPROM_res[19] = {0x09,0x08,0x03,0x03....and so on
the decimal value you computed somehow: 9833440827789222417

Unpack Dec from Hex - via bit offsets

I have a block of hex data which inicludes settings of a sensor, I will include the beginning snippet of the hex (LSB first):
F501517C 8150D4DE 04010200 70010101
05F32A04 F4467000 00000AFF 0502D402
This comes straight from the documentation to decode this hex to dec:
3.1. Full identifier and settings record (0x7C)
Offset Length (bytes) Field description
0x00 6 Full identifier
0x06 40 Settings
3.1.1 Full identifier
Offset Field description
0x00 Product Type
0x01 Device Type
0x02 Software Major Version
0x03 Software Minor Version
0x04 Hardware Major Version
0x05 Hardware Minor Version
3.1.2 Settings
Offset Length(bit) Offset(bit) Default value Min Max Field Description
0x00 8 0 0 0 255 Country number
0x01 8 0 0 0 255 District number
0x02 16 0 0 0 9999 Sensor number
...
0x27
This being the only information I have to decode this. The offset column must be the trick to understanding this.
What are the hex values offset from?
I see 7C in the first hex string.
The Settings section goes to 0x27 = 39 in decimal which is stated in the 3.1 section as the length being 40.
The given hex bytes are byte offset from the beginning of the data.
Assuming that your given dump is little endian 32-bit, let's have a look:
Value in dump - separated in bytes - bytes in memory
F501517C - F5 01 51 7C - 7C 51 01 F5
8150D4DE - 81 50 D4 DE - DE D4 50 81
04010200 - 04 01 02 00 - 00 02 01 04
Now let's assign them to the fields. The next list has both records concatenated.
Byte Offset Field description
7C 0x00 Product Type
51 0x01 Device Type
01 0x02 Software Major Version
F5 0x03 Software Minor Version
DE 0x04 Hardware Major Version
D4 0x05 Hardware Minor Version
Byte Offset Length(bit) Offset(bit) Default value Min Max Field Description
50 0x00 8 0 0 0 255 Country number
81 0x01 8 0 0 0 255 District number
00,02 0x02 16 0 0 0 9999 Sensor number
Whether the result makes sense, is your decision:
Product Type = 0x7C
Device Type = 0x51 = 81 decimal (could also be ASCII 'Q')
Software Major.Minor Version = 0x01.0xF5 = 1.245 decimal
Hardware Major.Minor Version = 0xDE.0xD4 = 222.212
Country number = 0x50 = 80 decimal (could also be ASCII 'P')
District number = 0x81 = 129 decimal (perhaps 0x01 = 1 with bit 7 set?)
Sensor number = 0x0002 = 2 decimal (big endian assumed)

RxAndroidBle, value should be in Hexadecimal

Values from the notification should be hexadecimal but I got decimal and negative values (with another app I got the good format) :
123 0 0 72 98 0
124 0 0 39 97 0
125 0 0 -2 95 0
126 0 0 -50 94 0
127 0 0 -105 93 0
-128 0 0 88 92 0
-127 0 0 18 91 0
-126 0 0 -59 89 0
-125 0 0 113 88 0
-124 0 0 22 87 0
-123 0 0 -76 85 0
-122 0 0 76 84 0
-121 0 0 -35 82 0
-120 0 0 103 81 0
Do you know how can I get this in Hexadecimal form?
Best regards
The RxAndroidBle library emits a byte[] when a notification is received. A single byte value can be represented in a different ways.
The log you have presented is just printing the raw values according to Java specification. Java does not have a concept of unsigned values and every value that starts with a 1 bit is treated as a negative number. i.e. 0xA2 is equivalent to -94. (0xA2 == -94) == true
A simple way to display a value as a hex is to use String.format() i.e. String.format("0x%2xh", byteValue)
Most probably you wanted to ask a question: How to convert a byte array to a hex String in Java
I wrote a little method to convert a byte[] into a String that looks like [02 FC 41 5A] etc.:
static String byteArrayToHexDigits(final byte[] bytes) {
int i;
StringBuilder result = new StringBuilder( "[" );
for( i = 0; i < (bytes.length-1); i++ ) {
result.append(String.format( "%02X ", bytes[i] ));
}
result.append(String.format( "%02X]", bytes[i] ));
return result.toString();
}

USART wrong data incoming

I am writing a communication between Atmega162 and PC.
On my PCB I have interface RS485 (converted from RS422 by MAX485) and it goes through ADAM-4520 transceiver into COM port.
I've been testing my program in terminal and it seems strange to me, that sending characters from MCU works fine, but these received from PC are changed (I cannot figure out any scheme of this conversion).
For example these ASCII characters are interpreted this way:
0 => 0
1 => 64
2 => 32
3 => 32
4 => 16
5 => 65
6 => 16
7 => 16
8 => 8
'1' => 204
'2' => 102
'3' => 70
'4' => 51
'5' => 141
'6' => 35
'7' => 51
'8' => 6
'9' => 142
I've been testing it for several transmission parameters, but it doesn't seem to help. The source code is here:
void USART_init()
{
UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
UCSR0C |= (1<<UCSZ10)|(1<<UCSZ00)|(1<<USBS0)|(1<<UPM10);
UBRR0H = 0;
UBRR0L = 12;
DDRD |= 1<<PD1;
_delay_ms(1);
}
void USART_Transmit( unsigned char data )
{
PORTD |= 1<<PD4;
while ( !( UCSR0A & (1<<UDRE0)) );
UDR0 = data;
while (!(UCSR0A & (1 << TXC0)))
PORTD &= ~(1<<PD4);
}
ISR(USART0_RXC_vect)
{
unsigned char a;
while ( !(UCSR0A & (1<<RXC0)) );
a = UDR0;
speed_1 = a;
}
PD4 switches between transmitting and receiving.
Looks like idle line is treated wrongly in your setup.
Lets see what a transmission over RS-485/RS-422 is looks like.
By default, when no device is transmitted, lines are in idle state. Normally they are pulled together by the terminal resistors and there is no differential voltage across the lines. Or there are bias resistors which pull the line to make 200mV (logical 1) difference between A and B.
When transmitter driver is enabled and 0 or 1 is being transmitted, the transmitter pulls the lines apart, making differential voltage across them more than 200mV with one sign or another.
And transmission of a byte would be look like this
............ 0 1000 1100 1 1 ............
(idle line) | | (data) | | | (idle again)
driver enabled | | | driver disabled
start bit parity |
stop bit
In this example digit 1 (0x31 hex, or 00110001 bin) is being transmitted, assuming even parity is enabled.
On UART, each transmitted byte is started by a start-bit (which is logical 0) then the data is being transmitted in little-endian form (i.e. starting from the least significant bit), and it finished by transmitting one or more stop bits, which is logical 1.
Normally, idle line is treated by the receiver as 1, and first transition from 1 to 0 is treated as a start bit.
But lets see whats happens, when idle line is treated as logic 0?
000000000000 0 1000 1100 11 000000000000
(nothing, ||^^ ^^^^ ^^ |
framing error) || data treated as stop
1 treated as idle|
0 treated as start
in this case, start bit (level 0) is ignored, and first bit 1 is treated as the stop bit of previous transmission. First bit 0 after that is treated as the start bit of a byte, and following 8 bits are considered as the data.
In our example data would be 11001100, which is 204. Lets see other examples
transmitted '4' (0x34): ..... 0 0010 1100 11 ...........
received: S 1100 11 00 - result 51
transmitted '5' (0x35): ..... 0 1010 1100 01 ...........
received: S10 1100 01 0 - result 141
transmitted '6' (0x36): ..... 0 0110 1100 01 ...........
received: S 1100 01 00 - result 35
transmitted '7' (0x37): ..... 0 1110 1100 11 ...........
received: S 1100 11 00 - result 51
transmitted '8' (0x38): ..... 0 0001 1100 11 ...........
received: S0 11 00000 - result 6
transmitted 0: ..... 0 0000 0000 01 ...........
received: S00000000 - result 0
Although my hypothesis does not add up for the first half of your examples. E.g., for 1 i expect you to get number 192, for 5 - 193, except if you got those numbers while parity was disabled:
transmitted 1: ..... 0 1000 0000 1 ...........
received: S00 0000 1 0 - result 64
transmitted 2: ..... 0 0100 0000 1 ...........
received: S0 0000 1 00 - result 32
transmitted 3: ..... 0 1100 0000 1 ...........
received: S0 0000 1 00 - result 32
transmitted 5: ..... 0 1010 0000 1 ...........
received: S10 0000 1 0 - result 65
transmitted 8: ..... 0 0001 0000 1 ...........
received: S000 1 0000 - result 8
My conclusion: you have to check RS-422 line which goes from PC to the MCU. It has some issues which make the receiver think there is logical 0 when line is in the idle state. Probably there are bias resistors which are connected the wrong way.
And also, as it was said in the comments, you have an issue with initialization:
UCSR0C |= (1<<UCSZ10)|(1<<UCSZ00)|(1<<USBS0)|(1<<UPM10);
^^^^^^ has to be UCSZ01
But, since you are using |= instead of simple assign, and UCSZ01 bit is by default is 1, this also may work as expected.
Also the loop
while ( !(UCSR0A & (1<<RXC0)) );
should not be in the interrupt handler. Since the interrupt fires only when RXC bit is set, you may assume there is a data in UDR, otherwise, this loop may hang your interrupt routine forever.

Resources