Дисплей покупця ИП-3 від Юнісистем

Сьогодні досліджуватимемо дисплей покупця від Юнісистем ИП-3. Це 2 рядковий 16 символьний контрасний LCD екран із LED підсвіткою.

Екран підключається до касових апаратів або POS систем через 9 контактний DB-9 роз’єм.

Екран виготовлено у 2010 році, живлення 5 вольт, максимальо 0,4А. Також вказано серійний номер.

Інтерфейс: RS-232C, на 4 контакт заведено +5В VCC. Кабель використано 4 жильний телефонний.

Відкрутимо 4 гвинти, і добираємося до нутрощів.

Якісно фіксовано кабель у корпусі, щоб не можна було висмикнути.

Екраном Winstar WH1602L-YGH-CT# Rev. A.

Контролером мостом є AVR процесор від Atmel ATTINY2313-20SU.

Інтерфейсна мікросхема RS232C-TTL MAX232.

На роз’єм X1 виведено стандартну 6 контактну колодку програмування ICSP: MISO (18 pin), VCC, SCK (19 pin), MOSI (17 pin), RST (1 pin), GND.

Підключаємося і вичитуємо flash (2KB), eeprom (128B), fuses (H, L, E).

avrdude -c usbasp -p attiny2313 -U flash:r:uni-flash.hex:i -U eeprom:r:uni-eeprom.bin:r -U hfuse:r:uni-fuse-h.txt:h -U lfuse:r:uni-fuse-l.txt:h -U efuse:r:uni-fuse-e.txt:h

Захисту прошивки від зчитування не було. Правда прошивка якась дивна, багато однакових блоків. Пробував вичитувати із посадженим на землю R/W екрана, але прошивка кожного разу ідентична вичитуєтьтся.

Призначення виходів:

RESET 1 20 VCC
RX 2 PD0  PB7 19 LCD PB6
TX 3 PD1  PB6 18 LCD PB7
кварц 4  PB5 17 LCD PB5
кварц 5  PB4 16 LCD RW
LCD PB1 6 PD2  PB3 15 LCD V
LCD E 7 PD3  PB2 14 LCD PB4
LCD RS 8 PD4  PB1 13 LCD PB3
LCD LED 9 PD5  PB0 12 LCD PB0
GND 10  PD6 11 LCD PB2

Тактування від зовнішнього кварца на 3,6864 Mhz.

Тепер можна зайнятися програмною частиною. Даємо +5В з usb порта, і підключаємося до вільного serial порта. Було визначено, що канальні швидкість 9600. При подачі живлення екран відправляє наступні 4 байти.

0x55 0x49 0x7E 0xE4

При запису на екран цих байт відбувається очистка екрану і відправка їх знову на хост систему. Таким чином можна первірити чи підключено екран.

Зазвичай такі екрани використовують протокол команд Epson (ESC/POS) або FIRICH. Не підійшов жоден протокол.

Методом наукового типу було виявлено, що для відображення букви потрібно відправити 2 байти: адресу за якою відобразити букву і код букви, наприклад:

0x0F 0x41

Виведе букву A в першому рядку в першій клітинці, де 0 – це номер рядка: 0 – перший рядок, 1 – другий рядок;  F – стовбець: F – перший стовбець, 0 – останній 16 стовбець.

Кодова таблиця дуже дивна, містить тільки великі літери, кирилиця йде по CP866 таблиці.

Щоб оновити повністю інформацію потрібно 64 байти інформації.

При відпраці байти від 0xF0 до 0xFF очищається екран і присилається у відповідь байт:

0xFF

Даний протокол не підтримує прокрутки текстів, позиціонування курсора, інверсії, завантаження своїх символів.

Було перебрано усі команди і їх комбінації, і не вдалося увімкнути підсвітку. Попробуємо декомпільнути прошивку і знайти спосіб активації підсвітки. Скоріш за все підсвітку ативовує якась комбінація з 4 байт. Увімкнення підсвітки нижче.

Реверс прошивки

Фюзи: L=0xCF H=0xDF E=0xFF

EEPROM містить 128 байт.

01 03 07 07 05 07 07 07 01 03 07 07 05 07 07 07
01 03 07 07 05 07 07 07 01 03 07 07 05 07 07 07
41 43 47 47 45 47 47 47 41 43 47 47 45 47 47 47
41 43 47 47 45 47 47 47 41 43 47 47 45 47 47 47
01 03 07 07 05 07 07 07 01 03 07 07 05 07 07 07
01 03 07 07 05 07 07 07 01 03 07 07 05 07 07 07
41 43 47 47 45 47 47 47 41 43 47 47 45 47 47 47
41 43 47 47 45 47 47 47 41 43 47 47 45 47 47 47

FLASH 2048 байт.

TBD Зчитана програма містить повторювані блоки, і в емуляторі не запсукається. Скоріш на вичитування впливає дисплей. Ракорочував SA1, садив на GND R/W вихід дисплея. Попробуя зняти чіп і вичитати без обвязки.

UPD1. Написав годинник на Lua.

-- POS DISPLAY
sp = "COM1"

socket = require("socket")
function sleep(sec) socket.sleep(sec) end
function ss(st,po) return string.sub(st,po,po) end
function sh(st) return st:gsub("\\x(%x%x)",function (x) return string.char(tonumber(x,16)) end) end
function fill(char) for i = 0,1,1 do for j = 15,0,-1 do ch=16*i+j serial:write(string.char(ch)..sh(char)) serial:flush() end end end
function blink(sec) fill("\xac") sleep(sec) fill("\x20") end

serial = io.open(sp,"ab")
print ("Runned clock")
serial:write(sh("\xff"))
 
while 1 do 
 d = os.date("%Y.%m.%d %H:%M:%S")
 m = ss(d,6)..ss(d,7)
 if m=="01" then mn="\x1c\x91\x1b\xa2\x1a\x97" end
 if m=="02" then mn="\x1c\x8b\x1b\x9e\x1a\x92" end
 if m=="03" then mn="\x1c\x81\x1b\x85\x1a\x90" end 
 if m=="04" then mn="\x1c\x8a\x1b\x82\x1a\xa2" end
 if m=="05" then mn="\x1c\x92\x1b\x90\x1a\x80" end
 if m=="06" then mn="\x1c\x97\x1b\x85\x1a\x90" end
 if m=="07" then mn="\x1c\x8b\x1b\x88\x1a\x8f" end
 if m=="08" then mn="\x1c\x91\x1b\x85\x1a\x90" end
 if m=="09" then mn="\x1c\x82\x1b\x85\x1a\x90" end
 if m=="10" then mn="\x1c\x86\x1b\x8e\x1a\x82" end
 if m=="11" then mn="\x1c\x8b\x1b\x88\x1a\x91" end
 if m=="12" then mn="\x1c\x83\x1b\x90\x1a\x93" end
 
 if ss(d,15)..ss(d,16)..ss(d,18)..ss(d,19) == "0000" then blink(2) end
 
 s= "\x1f"..ss(d,9).."\x1e"..ss(d,10)..mn..
 "\x17"..ss(d,12).."\x16"..ss(d,13).."\x15"..ss(d,14).. "\x14"..ss(d,15).."\x13"..ss(d,16).."\x12"..ss(d,17).."\x11"..ss(d,18).."\x10"..ss(d,19)
 serial:write(sh(s))
 serial:flush() 
 sleep(1)
end
serial:close()

UPD2. Дякуючи Igor Profyelec підсвітку включають наступні байти:

0x55 0x4C 0xFF 0x60

Вимкнути підсвітку:

0x55 0x4C 0x00 0x5F

У відповідь дисплей їх повертає назад в порт.

Використання фотографій або текстового контенту на інших ресурсах без клікабельного індексованого посилання заборонено.