Сьогодні досліджуватимемо дисплей покупця від Юнісистем ИП-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
У відповідь дисплей їх повертає назад в порт.
Юрій Р. ◯ 0009-0005-3702-9223. (2018). Дисплей покупця ИП-3 від Юнісистем. Блог UA ID. Взято з: https://blog.uaid.net.ua/unisystem-ip3