Skip to content

Commit b58ca1e

Browse files
committed
Initial commit (v0.1)
1 parent c567aec commit b58ca1e

File tree

9 files changed

+822
-0
lines changed

9 files changed

+822
-0
lines changed

Makefile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
rtd_prog: main.cpp crc.o gff.o i2c.o
2+
${CXX} ${CPPFLAGS} ${CXXFLAGS} ${LDFLAGS} crc.o gff.o i2c.o main.cpp -o rtd_prog
3+
4+
crc.o: crc.cpp crc.h
5+
${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o crc.o crc.cpp
6+
7+
gff.o: gff.cpp gff.h
8+
${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o gff.o gff.cpp
9+
10+
i2c.o: i2clinux.cpp i2c.h
11+
${CXX} ${CPPFLAGS} ${CXXFLAGS} -c -o i2c.o i2clinux.cpp
12+
13+
clean:
14+
rm -f *.o rtd_prog

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,35 @@
11
# rtd266x_programmer
22
Programmer for RTD266X using linux and i2c-dev
3+
4+
This allows you to program these devices just using a VGA cable plugged in to your graphics card (it uses the I2C from the DDC pins).
5+
6+
This is based on the code here https://github.com/ghent360/RTD-2660-Programmer that uses an external USB I2C interface and MS windows.
7+
8+
Using it
9+
--------
10+
11+
Make sure to "modprobe i2c-dev"
12+
13+
Then run "i2cdetect -l". I get the following output:
14+
15+
i2c-0 i2c i915 gmbus ssc I2C adapter
16+
i2c-1 i2c i915 gmbus vga I2C adapter
17+
i2c-2 i2c i915 gmbus panel I2C adapter
18+
i2c-3 i2c i915 gmbus dpc I2C adapter
19+
i2c-4 i2c i915 gmbus dpb I2C adapter
20+
i2c-5 i2c i915 gmbus dpd I2C adapter
21+
i2c-6 i2c DPDDC-B I2C adapter
22+
i2c-7 i2c DPDDC-C I2C adapter
23+
i2c-8 i2c DPDDC-D I2C adapter
24+
25+
Clearly i2c-1 is the i2c bus connected to the VGA DDC pins. Now I can plug a VGA cable between my laptop and the RTD2660 board and run "rtd_prog -d 1 -b backup.bin" to backup my firmware.
26+
27+
Usage: rtd_prog -d <device #> [-option[s]]
28+
Options:
29+
-d <device #> : Specify the i2c bus to use, e.g. -d 1 means /dev/i2c-1
30+
-b <file> : Backup the current firmware on the RTD266X to a file
31+
-f <file> : Flash a file to the RTD266X
32+
33+
Building
34+
--------
35+
No special requirements. On ubuntu I needed to "sudo apt-get install i2c-tools libi2c-dev" and that's it. Then just run "make"

crc.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "crc.h"
2+
3+
static unsigned gCrc = 0;
4+
5+
void InitCRC() {
6+
gCrc = 0;
7+
}
8+
9+
void ProcessCRC(const uint8_t *data, int len)
10+
{
11+
int i, j;
12+
for (j = len; j; j--, data++) {
13+
gCrc ^= (*data << 8);
14+
for(i = 8; i; i--) {
15+
if (gCrc & 0x8000)
16+
gCrc ^= (0x1070 << 3);
17+
gCrc <<= 1;
18+
}
19+
}
20+
}
21+
22+
uint8_t GetCRC() {
23+
return (uint8_t)(gCrc >> 8);
24+
}

crc.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef __CRC_H__
2+
#define __CRC_H__
3+
4+
#include <stdint.h>
5+
6+
void InitCRC();
7+
void ProcessCRC(const uint8_t *data, int len);
8+
uint8_t GetCRC();
9+
10+
#endif /* __CRC_H__ */
11+

gff.cpp

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
#include "gff.h"
2+
3+
class CBitStream {
4+
public:
5+
CBitStream(uint8_t* data_ptr, uint32_t data_len)
6+
: mask_(0x80),
7+
data_ptr_(data_ptr),
8+
data_len_(data_len) {}
9+
10+
bool HasData() const { return mask_ != 0 || data_len_ != 0; }
11+
uint32_t DataSize() const { return data_len_; }
12+
bool ReadBit() {
13+
if (!mask_) {
14+
NextMask();
15+
}
16+
bool result = (*data_ptr_ & mask_) != 0;
17+
mask_ >>= 1;
18+
return result;
19+
}
20+
21+
private:
22+
void NextMask() {
23+
if (data_len_) {
24+
mask_ = 0x80;
25+
data_ptr_++;
26+
data_len_--;
27+
}
28+
}
29+
30+
uint8_t mask_;
31+
uint8_t* data_ptr_;
32+
uint32_t data_len_;
33+
};
34+
35+
static uint8_t gff_decode_nibble(CBitStream* bit_stream) {
36+
uint8_t zero_cnt = 0;
37+
bool bit;
38+
39+
do {
40+
if (!bit_stream->HasData()) return 0xf0;
41+
42+
bit = bit_stream->ReadBit();
43+
if (bit) break;
44+
zero_cnt++;
45+
} while (zero_cnt < 6);
46+
47+
if (zero_cnt > 5) {
48+
if (bit_stream->DataSize() == 1) {
49+
return 0xf0;
50+
}
51+
return 0xff;
52+
}
53+
54+
switch (zero_cnt) {
55+
case 0:
56+
return 0;
57+
58+
case 1:
59+
bit = bit_stream->ReadBit();
60+
return (bit) ? 0xf : 1;
61+
62+
case 2:
63+
bit = bit_stream->ReadBit();
64+
return (bit) ? 8 : 2;
65+
66+
case 3:
67+
bit = bit_stream->ReadBit();
68+
return (bit) ? 7 : 0xc;
69+
70+
case 4:
71+
bit = bit_stream->ReadBit();
72+
if (bit) {
73+
bit = bit_stream->ReadBit();
74+
return (bit) ? 9 : 4;
75+
} else {
76+
bit = bit_stream->ReadBit();
77+
if (bit) {
78+
bit = bit_stream->ReadBit();
79+
return (bit) ? 5 : 0xa;
80+
} else {
81+
bit = bit_stream->ReadBit();
82+
return (bit) ? 0xb : 3;
83+
}
84+
}
85+
break;
86+
87+
case 5:
88+
bit = bit_stream->ReadBit();
89+
if (bit) {
90+
bit = bit_stream->ReadBit();
91+
return (bit) ? 0xd : 0xe;
92+
} else {
93+
bit = bit_stream->ReadBit();
94+
return (bit) ? 6 : 0xff;
95+
}
96+
break;
97+
}
98+
return 0xff;
99+
}
100+
101+
uint32_t ComputeGffDecodedSize(uint8_t* data_ptr, uint32_t data_len) {
102+
CBitStream bs(data_ptr, data_len);
103+
uint32_t cnt = 0;
104+
while (bs.HasData()) {
105+
uint8_t b = gff_decode_nibble(&bs);
106+
if (b == 0xff) return 0;
107+
if (b == 0xf0) return cnt; // End of file
108+
109+
b = gff_decode_nibble(&bs);
110+
if (b > 0xf) return 0; // Error or odd number of nibbles
111+
cnt++;
112+
}
113+
return cnt;
114+
}
115+
116+
bool DecodeGff(uint8_t* data_ptr, uint32_t data_len, uint8_t* dest) {
117+
CBitStream bs(data_ptr, data_len);
118+
while (bs.HasData()) {
119+
uint8_t n1 = gff_decode_nibble(&bs);
120+
if (n1 == 0xf0) return true; // End of file
121+
if (n1 == 0xff) return false;
122+
123+
uint8_t n2 = gff_decode_nibble(&bs);
124+
if (n2 > 0xf) return false;
125+
126+
uint8_t byte = (n1 << 4) | n2;
127+
*dest++ = byte;
128+
}
129+
return true;
130+
}

gff.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef __GFF_H__
2+
#define __GFF_H__
3+
4+
#include <stdint.h>
5+
6+
uint32_t ComputeGffDecodedSize(uint8_t* data_ptr, uint32_t data_len);
7+
bool DecodeGff(uint8_t* data_ptr, uint32_t data_len, uint8_t* dest);
8+
9+
#endif /* __GFF_H__ */
10+

i2c.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#ifndef __I2C_H__
2+
#define __I2C_H__
3+
4+
#include <stdint.h>
5+
6+
bool InitI2C(int adapter_nr);
7+
bool CloseI2C();
8+
9+
bool SetI2CAddr(uint8_t addr);
10+
11+
bool WriteReg(uint8_t reg, uint8_t value);
12+
uint8_t ReadReg(uint8_t reg);
13+
int32_t ReadBytesFromAddr(uint8_t reg, uint8_t* dest, uint8_t len);
14+
bool WriteBytesToAddr(uint8_t reg, uint8_t* values, uint8_t len);
15+
16+
#endif /* __I2C_H__ */
17+

i2clinux.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#include "i2c.h"
2+
#include <stdio.h>
3+
#include <fcntl.h>
4+
#include <unistd.h>
5+
#include <sys/ioctl.h>
6+
extern "C"
7+
{
8+
#include <linux/i2c-dev.h>
9+
}
10+
11+
static int file;
12+
static char filename[20];
13+
14+
bool
15+
InitI2C(int adapter_nr) {
16+
snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
17+
file = open(filename, O_RDWR);
18+
if (file < 0) {
19+
/* ERROR HANDLING; you can check errno to see what went wrong */
20+
fprintf(stderr, "Error: could not open %s\n", filename);
21+
return false;
22+
}
23+
return true;
24+
}
25+
26+
bool
27+
CloseI2C() {
28+
if (close(file) < 0) {
29+
fprintf(stderr, "Error: could not close %s\n", filename);
30+
return false;
31+
}
32+
return true;
33+
}
34+
35+
bool
36+
SetI2CAddr(uint8_t addr) {
37+
if (ioctl(file, I2C_SLAVE, addr) < 0) {
38+
/* ERROR HANDLING; you can check errno to see what went wrong */
39+
fprintf(stderr, "Error: could not set slave address to %x\n", addr);
40+
return false;
41+
}
42+
return true;
43+
}
44+
45+
bool
46+
WriteReg(uint8_t reg, uint8_t value) {
47+
if (i2c_smbus_write_byte_data(file, reg, value) < 0) {
48+
fprintf(stderr, "Error: could not write to register %d\n", reg);
49+
return false;
50+
}
51+
return true;
52+
}
53+
54+
uint8_t
55+
ReadReg(uint8_t reg) {
56+
int32_t result;
57+
if ((result = i2c_smbus_read_byte_data(file, reg)) == -1)
58+
fprintf(stderr, "Error: could not read from register %d\n", reg);
59+
60+
return (uint8_t)result;
61+
}
62+
63+
int32_t
64+
ReadBytesFromAddr(uint8_t reg, uint8_t* dest, uint8_t len) {
65+
int read;
66+
//if ((*len = i2c_smbus_read_block_data(file, reg, dest)) == -1) {
67+
if ((read = i2c_smbus_read_i2c_block_data(file, reg, len, dest)) == -1) {
68+
fprintf(stderr, "Error: could not read block from register %d\n", reg);
69+
return -1;
70+
}
71+
return read;
72+
}
73+
74+
bool
75+
WriteBytesToAddr(uint8_t reg, uint8_t* values, uint8_t len) {
76+
//if (i2c_smbus_write_block_data(file, reg, len, values) < 0) {
77+
if (i2c_smbus_write_i2c_block_data(file, reg, len, values) < 0) {
78+
fprintf(stderr, "Error: could not write block data to register %d\n", reg);
79+
return false;
80+
}
81+
return true;
82+
}
83+

0 commit comments

Comments
 (0)