#include "brand_image.h"
uint8_t image_type = 0; //0=none,1=mono 2bit,2=RGB656little,3=RGB656giant
bool large_screen = true; //check ipod screen size toby default ipod is small screen (128x64) / large screen (256x128)
uint16_t packet_counter = 0; //set_display_screen block counter
/* WORK PARAMETER TEST
set_display_image(brand_small_mono,128,64,1,4,false);//128x64, mono, 4 row, short packet
set_display_image(brand_big_mono,128,128,1,2,false);//128x128, mono, 2 row, short packet
set_display_image(brand_big_mono,256,128,1,2,false);//256x128, mono, 2 row, short packet
*/
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
image_type = 1;//for now force image_type =1 for mono only
//small_screen determine from screen limit check
set_display_image(false,0);// row, short package
}
void loop() {
packet_counter++;
set_display_image(false,packet_counter);//128x64, mono ,4 row, short package
}
//--------------------------------------
//convert integer to byte array
void intToHexByteArray(int value, byte* byteArray) {
byteArray[0] = (value >> 24) & 0xFF;
byteArray[1] = (value >> 16) & 0xFF;
byteArray[2] = (value >> 8) & 0xFF;
byteArray[3] = value & 0xFF;
}
//--------------------------------------
//convert byte array to integer number
//byte array = [1,2,3,4] -> integer number
int hexByteArrayToInt(byte* byteArray,byte length) {
int result = 0;
for (int i = 0; i <length; i++) {
result |= (byteArray[length-1-i] << (8 * i));
}
return result;
}
//--------------------------------------
String byteArrayToString(byte *byteArray, size_t length) {
String result = "";
for (size_t i = 0; i < length; i++) {
result += char(byteArray[i]);
}
return result;
}
//--------------------------------------
//calcualte CRC = ( (0x100 - (length+mode+command)) & 0xFF)
uint8_t CRC(uint8_t arrays[]) {
uint16_t sum = 0;
uint8_t length = arrays[2];
//Serial.println(length);
for (uint8_t i=2;i<3+length;i++) {//shift 2 + len 1
sum = sum + arrays[i];
//Serial.print(arrays[i],HEX);
}
uint16_t crc = 0x100 - (sum & 0xFF);
//Serial.print("CRC = ");
//Serial.println(crc,HEX);
return crc;
}
//--------------------------------------
//calcualte CRC = ( (0x100 - (length+mode+command)) & 0xFF)
uint8_t longCRC(uint8_t arrays[]) {
uint32_t sum = 0;
uint16_t length = word(arrays[3],arrays[4]);
// Serial.println(length);
for (uint32_t i=3;i<5+length;i++) {//shift 3 +lenght 2
sum = sum + arrays[i];
// Serial.print(arrays[i],HEX);
}
uint16_t crc = 0x100 - (sum & 0xFF);
//Serial.print("Long CRC = ");
//Serial.println(crc,HEX);
return crc;
}
//--------------------------------------
//Send command to control ipod (without parameter)
void SEND_COMMAND(uint8_t cmd[]) {
uint8_t shiftbyte;
uint16_t length;
uint8_t crc;
if (cmd[2] == 0x00) {//large packet command payload 256 - 65535 bytes
length = word(cmd[3],cmd[4]);//get data length
crc = longCRC(cmd);
shiftbyte = 5;//header byte 2 + long packet byte 1 + length byte 2
} else {//small packet command payload <= 255 bytes
length = cmd[2];//get data length
crc = CRC(cmd);
shiftbyte = 3;//header byte 2 + length byte 1
}
//send to serial
for (uint8_t i=0;i < shiftbyte + length; i++) {//header byte 2 + long packet byte 1 + length byte 2
Serial1.write(cmd[i]);
//Serial.print(cmd[i],HEX);
//Serial.print(",");
}
Serial1.write(crc);
Serial1.flush();// Wait for all data to be sent
}//send command
//--------------------------------------
/* WORK PARAMETER TEST
set_display_image(brand_small_mono,128,64,1,4,false);//128x64, mono, 4 row, short packet
set_display_image(brand_big_mono,128,128,1,2,false);//128x128, mono, 2 row, short packet
set_display_image(brand_big_mono,256,128,1,2,false);//256x128, mono, 2 row, short packet
*/
//user after check support display resolution (image data, image width px, image height px, image type 0,1,3 , packet type, send at block number)
void set_display_image(bool large_packet,uint16_t packet_number) {
const uint8_t *image = brand_image_table[image_type-1][large_screen];//choose image mono/color , small/big
uint16_t width, height;
if (large_screen) {//determin image widht and height by screen size flag
width = 256;
height = 128;
} else {
width = 128;
height = 64;
}
uint8_t stride;
//calculate stride (number of bytes to display 1 row of image(width))
if (image_type == 0x01) stride = width / 4; //stride (number of byte in 1 row of image) 2 bit/pixel
else stride = width * 2;//stride for color display (2 byte /pixel)
uint8_t row_to_read = 128 / stride;//not more than 128 bytes.
uint16_t num_packet_to_read = height / row_to_read;//target to count response by command 0x32
uint16_t data_byte_to_read = stride * row_to_read;//num of byte to read in 1 block to sent
if (packet_number >= num_packet_to_read) {
while (1) {};
} else {//send from block 0 to n
//----- small packet payload <= 255 bytes ------------------------------
if (!large_packet) {//monochrome 4 pixel/byte bitmap image
if(packet_number == 0) {//first block
packet_counter = 0;//reset counter to 0
uint8_t len = data_byte_to_read + 14;//mode+para+data
// Header |len|mode|set disp| desc ind |mono 2bit|width px |height px|num of byte in 1row|
uint8_t SET_DISPLAY_IMAGE[len+4] = {0xff,0x55,len,0x04,0x00,0x32,0x00,0x00,image_type,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//+raw data+checksum
//1st block
byte byteArray[4];
intToHexByteArray(width, byteArray);
for (byte i=0;i<2;i++) SET_DISPLAY_IMAGE[i+9] = byteArray[i+2];//get only 2 byte (image width)
intToHexByteArray(height, byteArray);
for (byte i=0;i<2;i++) SET_DISPLAY_IMAGE[i+11] = byteArray[i+2];//get only 2 byte (image height)
intToHexByteArray(stride, byteArray);
for (byte i=0;i<4;i++) SET_DISPLAY_IMAGE[i+13] = byteArray[i];//get 4 stride
for (uint16_t i=0;i < data_byte_to_read; i++) SET_DISPLAY_IMAGE[i+17] = image[i];//copy image data to command
SEND_COMMAND(SET_DISPLAY_IMAGE);//send first block
Serial.printf("Packet %d/%d = %d bytes sent\n",SET_DISPLAY_IMAGE[7],num_packet_to_read-1,data_byte_to_read);
} else {//block number = 2....n //2nd block and so on..
uint8_t len = data_byte_to_read + 5;//cmd+para+data+crc
// |Header |Len|mode|set disp | desc ind |
uint8_t SET_DISPLAY_IMAGE[len+4] = {0xff,0x55,len,0x04,0x00,0x32,0x00,0x00};//+ raw data
byte byteArray[4];
intToHexByteArray(packet_number, byteArray);
for (byte i=0;i<2;i++) SET_DISPLAY_IMAGE[i+6] = byteArray[i+2];//get 2 byte desc_index
for (uint16_t i=0;i < data_byte_to_read; i++) SET_DISPLAY_IMAGE[i+8] = image[i+(data_byte_to_read * packet_number)];//copy image data to command
SEND_COMMAND(SET_DISPLAY_IMAGE);//send the next block
Serial.printf("Packet %d/%d = %d bytes sent\n",SET_DISPLAY_IMAGE[7],num_packet_to_read-1,data_byte_to_read * (packet_number+1));
}//else packet_number = 0
//----- large packet payload > 256 - 65535 bytes ------------------------------
} else {
if(packet_number == 0) {//first block
packet_counter = 0;//reset counter to 0
uint16_t len = data_byte_to_read + 14;//mode+para_data
// |Header |Larg| Length |mode|set disp| desc ind |RGB565 |width px |height px|num of byte in 1row|
uint8_t SET_DISPLAY_IMAGE[len+6] = {0xff,0x55,0x00,0x00,0x00,0x04,0x00,0x32,0x00,0x00,image_type,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};//+raw data+checksum
//1st block
byte byteArray[4];
intToHexByteArray(len, byteArray);
for (byte i=0;i<2;i++) SET_DISPLAY_IMAGE[i+3] = byteArray[i+2];//get 2 byte length
intToHexByteArray(width, byteArray);
for (byte i=0;i<2;i++) SET_DISPLAY_IMAGE[i+11] = byteArray[i+2];//get only 2 byte (image width)
intToHexByteArray(height, byteArray);
for (byte i=0;i<2;i++) SET_DISPLAY_IMAGE[i+13] = byteArray[i+2];//get only 2 byte (image height)
intToHexByteArray(stride, byteArray);
for (byte i=0;i<4;i++) SET_DISPLAY_IMAGE[i+15] = byteArray[i];//get 4 stride
for (uint16_t i=0;i < data_byte_to_read; i++) SET_DISPLAY_IMAGE[i+19] = image[i];//copy image data to command
SEND_COMMAND(SET_DISPLAY_IMAGE);//send 1st block
Serial.printf("Packet %d/%d = %d bytes sent\n",SET_DISPLAY_IMAGE[9],num_packet_to_read-1,data_byte_to_read);
} else {//block number = 2....n //2nd block and so on..
uint16_t len = data_byte_to_read + 5;//cmd+para+data+crc
// |Header |Larg| Length |mode|set disp| desc ind 2 byte|
uint8_t SET_DISPLAY_IMAGE[len+6] = {0xff,0x55,0x00,0x00,0x00,0x04,0x00,0x32,0x00,0x00};//+raw data
byte byteArray[4];
intToHexByteArray(packet_number, byteArray);
for (byte i=0;i<2;i++) SET_DISPLAY_IMAGE[i+8] = byteArray[i+2];//get 2 byte desc_index
for (uint16_t i=0;i < data_byte_to_read; i++) SET_DISPLAY_IMAGE[i+10] = image[i+(data_byte_to_read * packet_number)];//copy image data to command
SEND_COMMAND(SET_DISPLAY_IMAGE);//send next block
Serial.printf("Packet %d/%d = %d bytes sent\n",SET_DISPLAY_IMAGE[9],num_packet_to_read-1,data_byte_to_read * (packet_number+1));
}//if packet_number = 0
}//imageTYpe >=2
}//else (packet_number == num_packet_to_read )
}//set display iamge
//--------------------------------------
//encode UTF-8 (title,album,song title in other language cause web client UTF-8 decoding error)
//code will be decode with Javascript in web page "ก" -> E0E881
String encodeToUTF8(const String &input) {
String sanitized = "";
for (size_t i = 0; i < input.length()-1; i++) {//remove suffix 00 by minus length with 1
char c = input.charAt(i);
if (isPrintable(c) && c != '\0') { // Remove NULL and printable characters
sanitized += c;//skip ascii char
} else {
char hexString[3]; // 2 characters for the hex representation + 1 for the null terminator
snprintf(hexString, sizeof(hexString), "%02X", (unsigned char)c); // Convert character to hex and store in hexString
sanitized += hexString;
}
}
return sanitized;
}