Casio PD‑700 — Часть 4: заводской метод загрузки программ

    Казалось, что всё уже ясно: процессор, язык программирования, распиновка коннектора. Но одно оставалось загадкой, а именно - как заливались программы на заводе, когда калькулятор уже собран и нет доступа к пинам клавиатуры. Ведь сейчас я пишу, подпаявшись к процессору, и даже если заливаю через 30-пиновый порт, всё ещё ввожу LOAD "COM0:".

    В поисках возможных вариантов я обнаружил, что если во время запроса на регулировку контраста нажать "+", выходит текс на английском: "LOAD RAM. OK ?". Вот оно!

    Все функции, доступные в этом меню:
"+"
LOAD RAM. OK ?
"-"
SAVE RAM. OK ?
  • Клавиша "+" выводит запрос "LOAD RAM. OK ?"
  • Клавиша "-" выводит запрос "SAVE RAM. OK ?"
Всё остальное работает только после нажатия одной из вышеуказанных клавиш!

    Во время запроса на LOAD или SAVE:
"*" - changes Baud Rate (9600 / 19200 BPS)
                          / "1" - PROG: DIR:
"/" CHECK SUM. PRESS(1-3) - "2" - FILE: DIR:
                          \ "2" - START? END?
"=" or "YES" - starts loading or saving
Any other key cancels last operation
  • Клавиша "*" меняет скорость связи. Доступно две скорости: 9600 BPS и 19200 BPS.

  • Клавиша "/" открывает меню для проверки чексумм: появляется запрос " CHECK SUM. PRESS(1-3)".

    В этом подменю:
1
PROG:
DIR:
Program area checksum
Program addresses area checksum
2
FILE:
DIR:
Program & Data area checksum
Program & Data addresses area checksum
3
START?
END?
Start-End range checksum
  • При нажатии "1" выводится чексумма области, занятой программами, и чексумма области адресов программ.

  • При нажатии "2" выводится чексумма области, занятой всеми файлами, и чексумма области адресов всех файлов.

  • При нажатии "3" сначала выводятся запросы на ввод "START?" и "END?", а затем чексумма указанного диапазона памяти. Начальный и конечный адрес вводятся в десятичном виде, а результат отображается в HEX.

    Чексумма представляет из себя обычную сумму байт.
    Подтвердить действие на каждом из этапов можно клавишами "=" или "YES", а отменить последнее действие любой другой клавишей.

    Для начала я поставил себе задачу считать данные с помощью SAVE RAM и залить их обратно с помощью LOAD RAM, чтобы убедиться, что всё работает.
    Я сохранил всё через PUTTY, настроив логирование данных в файл, но эти данные не получалось залить обратно. Всё дело в том, что PuTTY интерпретирует полученные данные как текст, и искажает байты со значением меньше 0x20. Я перепробовал несколько программ, и не встретив такой, которая бы гарантированно сохраняла поток побайтово, без изменения управляющих и очистки непечатаемых символов, написал свою программу для сохранения HEX данных в текстовом виде. На этот раз всё сработало!
    Настройки связи для этого режима: скорость 9600 или 19200 BPS (на выбор), DATA LENGTH 8, PARITY EVEN, STOP BITS 2. Но при отправке с калькулятора на компьютер возможно появление лишних вопросительных знаков (0x3F3F), поэтому лучше устанавливать PARITY NONE. Теперь, имея уверенность в том, что передо мной правильный образ RAM, пригодный для загрузки предусмотренным разработчиком методом, я принялся его разбирать.

    Перед данными идут 8 байт стартовой информации, затем область RAM, начиная с адреса 0x0CC4, в конце ещё один байт - контрольный.

    Стартовая информация:
  • 43 — StartByte
  • 0000 — ADDsta с ROM-карты, если вставлена
  • 3CF3 — объём отправляемых данных
  • C40C00 — стартовый адрес для записи
    Калькулятор начинает слушать только после байта 0x43 (символ "C"), любые данные до него игнорируются. Несоответствие любого следующего значения из этого списка приводит к "RW error" после получения последнего из них.
    Далее следует адрес таблицы указателей на ROM-карте (если предусмотрено её использование, и она вставлена). Указывается для проверки соответствия загружаемого образа RAM данному экземпляру устройства. При отсутствии карты ROM (а она скорее всего отсутствует) указывается значение 0x0000.
    Стартовый адрес для записи указан в little-endian и всегда равен 0x000CC4. С этого адреса в памяти калькулятора начинаются значимые данные (Parameter Area).
    Объём отправляемых данных также указан в little-endian и равен разнице верхней границы памяти и стартового адреса (старший байт верхней границы не имеет значения). При общем объёме памяти калькулятора в 64 кБ объём отправляемых данных составляет 0x10000-0x0CC4=0xF33C. Верхняя граница памяти хранится по адресу 0x0CF1 и выставляется при выполнении RESET. При желании загрузить меньший образ, можно заменить в его стартовой информации значение объёма отправляемых данных на ожидаемое калькулятором, или заменить верхнюю границу в памяти калькулятора на соответствующую отправляемому образу (мне это пригождалось для дальнейших частых экспериментов).

    Значение контрольного байта вычисляется путём вычитания из 0x00 суммы всех переданных байтов, включая 8 байт стартовой информации, с учётом переполнения (модуль 256). Контрольный байт используется только для проверки. Если он неправильный, отобразится "PR error", если его вовсе нет, калькулятор не почувствует конец и продолжит его ждать, можно остановить клавишей "CAL". При этом, в обоих случаях всё запишется.

    Отлично! Теперь мы знаем, как на заводе программировали Casio PD-700. Но работает это не так, как я изначально ожидал. Выходит, что задумано заливать не программы на BASIC в текстовом виде, а целый образ RAM, где программы уже токенизированы и все адреса проставлены, да и ещё много системных параметров.
    Для этого нужен специальный инструмент - программа для сборки образа. Очевидно, что такая была у Casio, но заказчики ничего о ней не знали и получали уже запрограммированный калькулятор. Возможно, в Casio или у продавца, номер которого указан на моём экземпляре, ещё сохранилась программа или хотя бы какие-то сведения о ней, но вероятнее всего она растворилась во времени.

    Что же, буду искать способы обойтись без неё. Казалось, что всё уже понятно, но на самом деле всё только начинается!

Комментарии