Arduino RFID checksum calculation and key visualization - embedded

I'm using this RFID module for Arduino Ethernet R3 and I need to retrieve from the Software Serial the card (TAG) ID that is written outside the tag.
The module's datasheet says that 14 bytes are sent to the Arduino. The first is the header, the last the footer, the 2 bytes before the footer are the checksum, and the other 10 bytes are the ASCII data that contains the tag ID.
How can I recreate the ID of the card, and control the checksum? For example with a tag that has this ID: 0013530444, the Arduino response is:
I received: 2
I received: 51
I received: 67
I received: 48
I received: 48
I received: 67
I received: 69
I received: 55
I received: 53
I received: 52
I received: 67
I received: 67
I received: 66
I received: 3
But I've no idea how to print on the screen the ID read by the Arduino. How to calculate the checksum?
http://www.seeedstudio.com/wiki/index.php?title=125Khz_RFID_module_-_UART
Can anyone help me?

Here's a walkthrough of how to calculate the checksum.
Take your card number (this is just directly quoted from your text)
I received: 2
I received: 51
I received: 67
I received: 48
I received: 48
I received: 67
I received: 69
I received: 55
I received: 53
I received: 52
I received: 67
I received: 67
I received: 66
I received: 3
This would give you a number that is equivalent to the following:
2 51 67 48 48 67 69 55 53 52 67 67 66 3
The first numer (2) indicates that this is the beginning of a request.
The last number (3) indicates that this is the end of a request.
2 51 67 48 48 67 69 55 53 52 67 67 66 3
For the purposes of calculating the checksum, we are going to remove these two numbers. So your new number is now:
51 67 48 48 67 69 55 53 52 67 67 66
The last two numbers that you have are your checksum. The remaining numbers are your card number. So:
Your card number is:
51 67 48 48 67 69 55 53 52 67
And your checksum is:
67 66
Next you need to convert your Card Number and your Checksum to ASCII values:
Your card number is:
3 C 0 0 C E 7 5 4 C
And your checksum is:
C B
Next, grab each number into pairs:
Your card number is:
3C 00 CE 75 4C
And your checksum is:
CB
Then you need to treat each pair as a HEXIDECIMAL value and do an XOR against them. So basically you need to prove the following:
3C ^ 00 ^ CE ^ 75 ^ 4C == CB
(3C ^ 00) = 3C
3C ^ CE ^ 75 ^ 4C == CB
(3C ^ CE) = F2
F2 ^ 75 ^ 4C == CB
(3C ^ CE) = 87
87 ^ 4C == CB
(87 ^ 4C) = CB
CB == CB
Because CB == CB, this is a valid transaction.
No doubt someone else can come up with a better approach than this, but there should be enough pseudo code here for you to write it yourself.

I found this blog which has an implementation in Arduino, I've adapted it to work in Java and results are good. Since there are a lot of bitwise operations - I used http://www.miniwebtool.com/bitwise-calculator/ to try to understand what's going on. I understand all of it except (val | (tempbyte << 4)), I mean I understand what the statement does, I just struggle to see how that produces the result I want.
void loop () {
byte i = 0;
byte val = 0;
byte code[6];
byte checksum = 0;
byte bytesread = 0;
byte tempbyte = 0;
if(Serial.available() > 0) {
if((val = Serial.read()) == 2) {
// check for header
bytesread = 0;
while (bytesread < 12) {
// read 10 digit code + 2 digit checksum
if( Serial.available() > 0) {
val = Serial.read();
if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) {
// if header or stop bytes before the 10 digit reading
break;
// stop reading
}
// Do Ascii/Hex conversion:
if ((val >= '0') && (val <= '9')) {
val = val - '0';
} else if ((val >= 'A') && (val <= 'F')) {
val = 10 + val - 'A';
}
// Every two hex-digits, add byte to code:
if (bytesread & 1 == 1) {
// make some space for this hex-digit by
// shifting the previous hex-digit with 4 bits to the left:
code[bytesread >> 1] = (val | (tempbyte << 4));
if (bytesread >> 1 != 5) {
// If we're at the checksum byte,
checksum ^= code[bytesread >> 1];
// Calculate the checksum... (XOR)
};
} else {
tempbyte = val;
// Store the first hex digit first...
};
bytesread++;
// ready to read next digit
}
}
// Output to Serial:
if (bytesread == 12) {
// removed code for clarity
LCD.print("Check:");
LCD.print(code[5], HEX);
LCD.print(code[5] == checksum ? "-passed" : "-error");
}
bytesread = 0;
}
}
}
My Java/Android port is listening over a BluetoothSocket. I'm using the code from BlueTerm as the base, this code goes in the ConnectedThread. Apologies for all silly comments, but I'm still learning Java).
//assume you have checksum as int and code as int array. it will overflow if bytes are used like above example
public void run() {
Log.d(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
Log.d(TAG, "Running");
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
for (int i = 0; i < bytes; i++) {
Log.d(TAG, "Reading: " + i + " of " + bytes + " from input stream");
byte b = buffer[i];
try {
if(bytesread >= 0) {
//just printing ASCII
char printableB = (char) b;
if (b < 32 || b > 126) printableB = ' ';
Log.d(TAG, "'" + Character.toString(printableB) + "' (" + Integer.toString(b) + ")");
if((b == 0x0D)||(b == 0x0A)||(b == 0x03)||(b == 0x02)) {
// if header or stop bytes before the 10 digit reading
Log.e(TAG, i + " Unexpected header while processing character " + Integer.toString(b));
} else {
// Do ASCII/Hex conversion
if ((b >= '0') && (b <= '9')) {
b = (byte) (b - '0');
} else if ((b >= 'A') && (b <= 'F')) {
b = (byte) (10 + b - 'A');
}
if ((bytesread & 1) == 1) {
//if isOdd(bytesread)
// make some space for this hex-digit by shifting the previous hex-digit with 4 bits to the left:
code[bytesread >> 1] = (b | (tempbyte << 4));
if (bytesread >> 1 != 5) {
// If we're not at the checksum byte,
checksum ^= code[bytesread >> 1];
// Calculate the checksum... (XOR)
}
} else {
// Store the first hex digit first
tempbyte = b;
}
}
bytesread++;
} else if(b == 2) {
bytesread = 0;
Log.d(TAG, "Header found!");
}
if(bytesread == 12) {
String check = (code[5] == checksum ? "-passed" : "-error");
String r = "";
for(int j = 0; j < 5; j++){
r += Integer.toString(code[i]);
}
Log.d(TAG, "Check:" + Integer.toString(code[5]) + check);
init();
} else if(bytesread > 12){
Log.e(TAG, "Too many bytes!");
}
} catch (Exception e) {
Log.e(TAG, i + " Exception while processing character " + Integer.toString(b), e);
}
}
String a = buffer.toString();
a = "";
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
Log.i(TAG, "END mConnectedThread");
}

Related

sigsegv compilation error of simple kotlin code

Following code generates error which looks like an error in compiler, its has nothing to do with the kotlin code, or maybe I am missing something? I have JDK error on macos and some more informative error (like pasted at the end of this post) from online compiler. How can I fix it?
Code: https://pl.kotl.in/CfdXHeDyn
import kotlin.math.pow
fun calculateNumberOfContainers(data: String): Int {
val containerSizes = mutableListOf<Int>()
data.lines().forEach { containerSizes.add(it.toInt()) }
var foundCorrect = 0
val maxSubSets = (2.0).pow(20).toULong()
for (n in 0UL until maxSubSets) {
var total = 0
for (k in 0 until 20) {
val mask = 1UL shl k
if ((mask and n) != 0UL) {
total += containerSizes[k]
if (total > 150)
break
}
}
if (total == 150)
foundCorrect++
}
return foundCorrect
}
fun runcode() {
val data =
"""
33
14
18
20
45
35
16
35
1
13
18
13
50
44
48
6
24
41
30
42
""".trimIndent()
calculateNumberOfContainers(data)
}
fun main() {
runcode()
}
Error:
Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: Unexpected character ('#' (code 35)): was expecting double-quote to start field name
at [Source: (String)"{#
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007fc646ef2eba, pid=1900, tid=0x00007fc6307f7700
#
# JRE version: OpenJDK Runtime Environment (8.0_201-b09) (build 1.8.0_201-b09)
# Java VM: OpenJDK 64-Bit Server VM (25.201-b09 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V [libjvm.so+0x382eba]
#
# Core dump written. Default location: /var/task/core or core.1900
#
# An error report file with more information is saved as:
# /tmp/"[truncated 195 chars]; line: 1, column: 3]
at com.fasterxml.jackson.core.JsonParser._constructError (JsonParser.java:1851)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportError (ParserMinimalBase.java:707)
at com.fasterxml.jackson.core.base.ParserMinimalBase._reportUnexpectedChar (ParserMinimalBase.java:632)
Update:
it works with 1.4.30, fails with 1.5.21, so its a bug in compiler
I changed from Unsigned Long to Unsigned Int and problem went away, code after changes looks as follows:
https://pl.kotl.in/XedacixZK
import kotlin.math.pow
fun calculateNumberOfContainers(data: String): Int {
val containerSizes = mutableListOf<Int>()
data.lines().forEach { containerSizes.add(it.toInt()) }
var foundCorrect = 0
val maxSubSets = (2.0).pow(20).toUInt()
for (n in 0U until maxSubSets) {
var total = 0
for (k in 0 until 20) {
val mask = 1U shl k
if ((mask and n) != 0U) {
total += containerSizes[k]
if (total > 150)
break
}
}
if (total == 150)
foundCorrect++
}
return foundCorrect
}
fun runcode() {
val data =
"""
33
14
18
20
45
35
16
35
1
13
18
13
50
44
48
6
24
41
30
42
""".trimIndent()
print(calculateNumberOfContainers(data))
}
fun main() {
runcode()
}

macOS weird crash in [NSString stringWithUTF8String:]

We started seeing crashes that happen when our app starts. I wasn't able to reproduce it, and it happens only to a few users.
The exception is:
Exception Type: EXC_BAD_ACCESS (SIGBUS) Exception Codes: 0x00000000
at 0x0000000105e1f32c Crashed Thread: 8
stack here
Thread 8 Crashed:
0 libsystem_platform.dylib 0x00007fff203b56f8 _os_semaphore_wait.cold.1 + 129
1 libsystem_malloc.dylib 0x00007fff20193793 szone_malloc_should_clear + 66
2 libsystem_malloc.dylib 0x00007fff201aceb7 _malloc_zone_calloc + 59
3 CoreFoundation 0x00007fff203e7b0a _CFRuntimeCreateInstance + 290
4 CoreFoundation 0x00007fff203e7289 __CFStringCreateImmutableFunnel3 + 2099
5 CoreFoundation 0x00007fff203f34fe CFStringCreateWithBytes + 27
6 Foundation 0x00007fff210eadbe +[NSString stringWithUTF8String:] + 68
7 MyApp 0x0000000104551576 +[Utility getCommandLine:] + 934
source code here
+ (void)getCommandLine:(LCProcessInfo*)process
{
int mib[3], argmax, nargs, c = 0;
char *procargs, *cp, *sp, *np;
size_t size;
mib[0] = CTL_KERN;
mib[1] = KERN_ARGMAX;
size = sizeof(argmax);
if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1)
{
ERROR(#"sysctl() of KERN_ARGMAX has failed.");
return;
}
procargs = malloc(argmax);
if (procargs == NULL)
{
ERROR(#"malloc() has failed");
return;
}
mib[0] = CTL_KERN;
mib[1] = KERN_PROCARGS2;
mib[2] = (int)process.pid;
size = argmax;
if (sysctl(mib, 3, procargs, &size, NULL, 0) == -1)
{
// Failure here means it's a system process.
process.commandLine = [NSString stringWithFormat:#"(%#)", process.name];
goto exit;
}
memcpy(&nargs, procargs, sizeof(nargs));
cp = procargs + sizeof(nargs);
for (; cp < &procargs[size]; cp++)
{
if (*cp == '\0')
{
break;
}
}
if (cp == &procargs[size])
{
goto exit;;
}
// Skip trailing '\0' characters.
for (; cp < &procargs[size]; cp++)
{
if (*cp != '\0')
{
break;
}
}
if (cp == &procargs[size])
{
goto exit;
}
// Save where argv[0] string starts.
sp = cp;
/*
* Iterate through the '\0'-terminated strings and convert '\0' to ' '
* until a string is found that has a '=' character in it (or there are
* no more strings in procargs). There is no way to deterministically
* know where the command arguments end and the environment strings
* start, which is why the '=' character is searched for as a heuristic.
*/
for (np = NULL; c < nargs && cp < &procargs[size]; cp++) {
if (*cp == '\0') {
c++;
if (np != NULL) {
/* Convert previous '\0'. */
*np = ' ';
}
/* Note location of current '\0'. */
np = cp;
}
}
/*
* sp points to the beginning of the arguments/environment string, and
* np should point to the '\0' terminator for the string.
*/
if (np == NULL || np == sp) {
/* Empty or unterminated string. */
goto exit;
}
/* Make a copy of the string. */
process.commandLine = [NSString stringWithUTF8Strin:sp];
exit:
/* Clean up. */
free(procargs);
}
Would appreciate any help to understand what's can cause this kind of crash.
Look at the value of sp before you call this. I expect there's a bug in how you advance cp. You probably advance it too far. I would suspect problems in your = searching heuristic.
If sp is NULL, this will crash.
nullTerminatedCString
A NULL-terminated C array of bytes in UTF-8 encoding. This value must not be NULL.
Important
Raises an exception if nullTerminatedCString is NULL.

How to auto increment in Arduino Mega Board while loop?

Please understand that the tone is awkward using a translator
I coded the below code for Arduino Mega Board.
However, the value of buf_i is not increasing in the second while loop.
char buf[] = {0, };
if (Serial3.available()) {
int inByte = Serial3.read();
int nextChar = 0;
if (inByte == 90) { //find Header 1
nextChar = Serial3.read();
if (nextChar == 165) { // find Header 2
int buf_i = 0;
int dataLen = Serial3.read(); // get Message Length
//save data [ char buf[] ] ---> works well!
while (buf_i < dataLen) {
buf[buf_i] = Serial3.read();
buf_i++;
}
buf_i = 0;
//print data to Serial ---> not work (Does not increase buf_i)
while (buf_i < dataLen) {
Serial.print(" ");
Serial.println(buf[buf_i]);
buf_i++;
}
}
}
Serial.write(inByte);
}
and this is Serial Moniter Log
in Serial3 Message
5A A5 06 83 21 00 01 00 11
in Serial Message
enter image description here
Thank you for your help :)
The buffer you created has only one element. If you try to insert more than one, then the behavior is undefined.
char buf[] = {0, };
You must make this buffer large enough for the largest message.
char buf[maximum_data_length] = {0};

CANNOT COMPILE:: I don't understand my errors. Mostly the "declared as void" errors and "StudentType was not declared in this scope".

I keep receiving these errors when I run the compiler:
Program04.cpp:21:14: error: variable or field âgetDataâ declared void
Program04.cpp:21:14: error: âStudentTypeâ was not declared in this scope
Program04.cpp:21:26: error: expected primary-expression before â]â token
Program04.cpp:21:29: error: expected primary-expression before âintâ
Program04.cpp:23:15: error: variable or field âsortDataâ declared void
Program04.cpp:23:15: error: âStudentTypeâ was not declared in this scope
Program04.cpp:23:27: error: expected primary-expression before â]â token
Program04.cpp:23:30: error: expected primary-expression before âintâ
Program04.cpp:27:22: error: variable or field âcomputeAveragesâ declared void
Program04.cpp:27:22: error: âStudentTypeâ was not declared in this scope
Program04.cpp:27:34: error: expected primary-expression before â]â token
Program04.cpp:27:37: error: expected primary-expression before âintâ
Program04.cpp:29:16: error: variable or field âprintDataâ declared void
Program04.cpp:29:16: error: âStudentTypeâ was not declared in this scope
Program04.cpp:29:28: error: expected primary-expression before â]â token
Program04.cpp:29:31: error: expected primary-expression before âintâ
Program04.cpp: In function âint main()â:
Program04.cpp:34:1: error: âStudentTypeâ was not declared in this scope
Program04.cpp:34:13: error: expected â;â before âstudentsâ
Program04.cpp:37:9: error: âstudentsâ was not declared in this scope
Program04.cpp:37:19: error: ânâ was not declared in this scope
Program04.cpp:37:20: error: âgetDataâ was not declared in this scope
Program04.cpp:38:21: error: âsortDataâ was not declared in this scope
Program04.cpp:39:25: error: âcomputeAveragesâ was not declared in this scope
Program04.cpp:40:19: error: âprintDataâ was not declared in this scope
Program04.cpp: At global scope:
Program04.cpp:45:14: error: variable or field âgetDataâ declared void
Program04.cpp:45:14: error: âStudentTypeâ was not declared in this scope
Program04.cpp:45:38: error: expected primary-expression before âintâ
Everything looks good to me, so i'm obviously not understanding something.
Any suggestions?
PROGRAM FILE
using namespace std;
#include "StudentType.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <climits>
#include <string>
const int MAX_STDS = 20;
void getData(StudentType[], int&);
void sortData(StudentType[], int&);
void getFormat(string&);
void computeAverages(StudentType[], int&);
void printData(StudentType[], int&);
int main () {
StudentType students[MAX_STDS];
StudentType();
getData(students, n);
sortData(students, n);
computeAverages(students);
printData(students);
return 0;
}
void getData(StudentType students[], int n){
ifstream fin;
int grade;
string filename, name;
bool done = false;
cout << "Enter filename: ";
cin >> filename;
fin.open(filename.c_str());
while(true) {
try {
fin.open(filename.c_str());
if(!fin) {
throw(string("Could not open " + filename + "."));
}
break;
}
catch (string s) {
cout << s << endl;
cout << "Enter a different file name: ";
cin >> filename;
}
}
n=0;
while(n<MAX_STDS && getline(fin, name)) {
students[n].setName(getFormat(name));
for(int i = 0; i < NUM_GRDS; ++i) {
fin >> grade;
student[n].setGrade(grade, i);
}
getline(fin, name);
++n;
}
}
void printData(StudentType students[], int n) {
for(int i = 0; i < n; ++i) {
students[i].printLine();
}
}
void computeAverages(StudentType students[], int n) {
for(int i = 0; i < n; ++i) {
students[i].computeAverage();
}
}
void sortData(StudentType students[], int n) {
for(int i=0; i<n-1; i++) {
for(int j=0; j < n-1-i; ++j) {
if(students[j].getName() > students[j+1].getName()) {
swap(students[j], students[j+1]);
}
}
}
}
void getFormat(string& name) {
string first;
string middle;
string last;
char n, m;
int size = 0;
n = name.find(' ');
first = name.substr(0, n);
m = name.find(' ', n + 1);
size = name.size();
if (m != string::npos) {
middle = name.substr(n+1, m-(n+1));
last = name.substr(m+1, size - (m+1));
}
else {
middle = "";
last = name.substr(n + 1, size - (n + 1));
}
name = last + ", " + first;
if (middle != "") {
name = (name + ' ') + middle[0];
}
}
HEADER FILE
#ifdef STUDENTTYPE__H
#define STUDENTTYPE__H
#include <string>
#include<iostream>
const int NUM_GRDS = 10;
class StudentType {
public:
StudentType();
void setName(std::string);
void setGrade(int, int);
void computeAverage();
std::string getName() const;
void print(std::ostream& = std::cout) const;
private:
std::string name;
int grades[NUM_GRDS];
float avg;
};
#endif
IMPLEMENTATION FILE
#include "StudentType.h"
#include <iomanip>
StudentType::StudentType(){
name = "";
for(int i =0; i <NUM_GRDS; ++i){
grades[i] = 0;
}
avg = 0.0;
}
void StudentType::setName(std::string newName){
name = newName;
}
void StudentType::setGrade(int grade, int num){
grades[num] = grade;
}
void StudentType::computeAverage(){
float total = 0;
for(int i = 0; i<NUM_GRDS; ++i){
total += grades[i];
}
avg = total/NUM_GRDS;
}
std::string StudentType::getName() const{
return name;
}
void StudentType::printLine(std::ostream& out) const {
out.setf(std::left);
out.setf(std::fixed);
out.setf(std::showpoint);
out << "\n" << setw(25) << "Student" << setw(50) << "Grades" << setw(10) << "Average" << endl;
out << "_____________________________________________________________________________________" << endl;
out << std::left << std::setw(25) << name << std::right << ' ';
for(int i = 0; i < NUM_GRDS; ++i){
out << std::setw(5) << grades[i] << ' ';
}
out << setprecision(2) << std::setw(6) << avg << endl;
}
My output should look like this after the program compiles...
Enter file name: grades.dat
Student Grades Average
________________________________________________________________________________________
Last, First 90 80 70 60 50 40 30 20 10 0 45.00
Last, First 40 40 40 40 40 40 40 40 40 40 40.00
Last, First 54 98 65 32 21 87 54 65 98 32 60.60
Flames, Blood A 9 8 7 6 5 4 3 2 1 0 4.50
Bottoms, Car 32 65 98 87 54 24 56 89 78 68 65.10
Guitars, Dean 10 10 10 10 10 10 10 10 10 10 10.00
Honer, Ruth T 78 56 12 23 45 89 31 64 97 79 57.40
Hot, Zepher R 12 54 87 89 56 32 51 46 97 31 55.50
.
.
.
The input file should have this format and include over 20 students for testing purposes:
g0, g1,...g9 should be 10 grades ranging from 0 to 100
First Middle Last
g0 g1 g2 g3 g4 g5 g6 g7 g8 g9
First Last
g0 g1 g2 g3 g4 g5 g6 g7 g8 g9
Change
#ifdef STUDENTTYPE__H
to
#ifndef STUDENTTYPE__H
then you have proper double-inclusion guard
(quite a common typo I must say)
From taking a sharp look at your files, i spotted 2 main errors:
your include guard in the header file is messed up:
#ifdef STUDENTTYPE__H
#define STUDENTTYPE__H
you probably want:
#ifndef STUDENTTYPE__H
#define STUDENTTYPE__H
Also, in the program file:
void getData(StudentType[], int&);
does not match the implementation
void getData(StudentType students[], int n){
as it should be
void getData(StudentType students[], int& n){
which is also true for the other methods.
Also, i am not sure whether stackoverflow is the correct place for you, as you do not have a specific question but just seem to "debug" all your errors here. Maybe start with some c++ tutorials and try to use the error messages of the compiler to trace down all errors.

arm cortex m3 display

hi i am working on arm controller lm3s8962 i m not able to understand the code below as per my understanding it is checking if the character is from the array or not, which he created using the ascii characters{i.e in the while loop : while(*pcStr != 0) },
i am not able to get what he is doing in the code after the line "Build and display the character buffer" plz can anyone explain this
void
RIT128x96x4StringDraw(const char *pcStr, unsigned long ulX,
unsigned long ulY, unsigned char ucLevel)
{
unsigned long ulIdx1, ulIdx2;
unsigned char ucTemp;
//
// Check the arguments.
//
ASSERT(ulX < 128);
ASSERT((ulX & 1) == 0);
ASSERT(ulY < 96);
ASSERT(ucLevel < 16);
//
// Setup a window starting at the specified column and row, ending
// at the right edge of the display and 8 rows down (single character row).
//
g_pucBuffer[0] = 0x15;
g_pucBuffer[1] = ulX / 2;
g_pucBuffer[2] = 63;
RITWriteCommand(g_pucBuffer, 3);
g_pucBuffer[0] = 0x75;
g_pucBuffer[1] = ulY;
g_pucBuffer[2] = ulY + 7;
RITWriteCommand(g_pucBuffer, 3);
RITWriteCommand(g_pucRIT128x96x4VerticalInc,
sizeof(g_pucRIT128x96x4VerticalInc));
//
// Loop while there are more characters in the string.
//
while(*pcStr != 0)
{
//
// Get a working copy of the current character and convert to an
// index into the character bit-map array.
//
ucTemp = *pcStr++ & 0x7f;
if(ucTemp < ' ')
{
ucTemp = 0;
}
else
{
ucTemp -= ' ';
}
//
// Build and display the character buffer.
//
for(ulIdx1 = 0; ulIdx1 < 6; ulIdx1 += 2)
{
//
// Convert two columns of 1-bit font data into a single data
// byte column of 4-bit font data.
//
for(ulIdx2 = 0; ulIdx2 < 8; ulIdx2++)
{
g_pucBuffer[ulIdx2] = 0;
if(g_pucFont[ucTemp][ulIdx1] & (1 << ulIdx2))
{
g_pucBuffer[ulIdx2] = (ucLevel << 4) & 0xf0;
}
if((ulIdx1 < 4) &&
(g_pucFont[ucTemp][ulIdx1 + 1] & (1 << ulIdx2)))
{
g_pucBuffer[ulIdx2] |= (ucLevel << 0) & 0x0f;
}
}
//
// Send this byte column to the display.
//
RITWriteData(g_pucBuffer, 8);
ulX += 2;
//
// Return if the right side of the display has been reached.
//
if(ulX == 128)
{
return;
}
}
}
}
He is doing some bit manipulations to build up bytes.
x |= y is the same as x = x | y, which keeps all the 1s in x and also changes some of the 0s to 1 if y has a 1 in the same position.
1 << i is a byte with a single 1 bit in the ith position from the right.
x = y & 0xf0 copies only the left 4 bits of y into x.
So he is looking up values in an array, checking particular bits of those values, then filling up another array with number created from those bits. You will have to work out the particulars for yourself.