Pull to refresh

Хакаем спортивные часы

Reading time4 min
Views5.4K
Original author: Tavis Ormandy

Введение



Взглянув на эти часы, можно подумать, что это обычные часы для бегунов.

Ну а я считаю, что это одни из самых лучших потребительских цифровых часов со сверхнизким энергопотреблением в мире!

Позвольте мне объясниться…

Спецификации


Это Timex m851. В них установлены 8-битный CPU Seiko SC188, 48 КБ ROM, 2 КБ RAM и матричный дисплей 42x11.

CPU спроектирован с расчётом на работу со сверхнизким энергопотреблением — одной батарейки хватает на три года!

Это очень важный аспект для меня, не думаю, что сейчас делают подобные часы потребительского класса.


А что это за контакты сбоку? Это USB. Естественно, можно синхронизировать информацию наподобие встреч и тому подобного (для этого есть удобная Linux-библиотека).

И вот что интересно — у часов есть SDK, и он на удивление хорош!

Достаточно ввести $ cc helloworld.c и загрузить код в часы.

Изначально я не думал, что влюблюсь в эти часы — мастер разработки, который Timex предоставлял в эпоху Windows XP, был ужасен. Однако оказалось, что он просто управляет находящимся внутри тулчейном в стиле UNIX.

А если его вытащить, то хакинг становится довольно увлекательным занятием!



WatchApps


Просто хотите увидеть код? Без проблем. я загрузил на github hello world и Makefile для его сборки:

https://github.com/taviso/timex/

Если хотите почитать руководство, то ниже есть ссылки.

Можно поразвлекаться, люди написали кучу всевозможных игр, утилит и инструментов.

А если вы хотите TL;DR по разработке, то я попробую рассказать!

Проектирование


Состояния и режимы


Приложение необходимо разделить на состояния.

Состояние — это просто способ замены кода по необходимости. При переключении состояний активный код сбрасывается, и его заменяет новый код.

Можно написать приложение, использующее примерно до 30 КБ кода и/или данных, но RAM в устройстве всего около 2 КБ. Именно поэтому нужно использовать состояния, в устройстве нет разбивки на страницы, и уместить в него такой объём не получится!

Есть место для общего кода, который используют все состояния, и, разумеется, место для переменных, вместе с API базы данных для хранимых данных.

Первые несколько состояний зарезервированы для обработки общих событий. Остальные можно использовать под что угодно — достаточно просто попросить ядро при необходимости переключить состояние!

if (foo > bar) {
    coreRequestStateChange(FOOBAR_STATE);
}

Режим — это просто активное приложение.

У вашего приложения может быть режим, но также можно добавлять и фоновые задачи, периодические задачи и так далее.

Запрос на смену режима похож на exit(), контроль переходит следующему приложению.

coreRequestModeChangeNext();

События


Каждому состоянию нужен обработчик событий. Самый простой может выглядеть так:

void default_state_manager(void)
{
    switch (CORECurrentEvent) {
        // Вызывается, когда состояние становится активным.
        case COREEVENT_STATEENTRY:
            coreEnableSwitchReleaseEvents();
            coreAllowKeys(COREALLOWALLSWITCHES);
            break;
        // Вызывается, когда пользователь вытягивает заводную головку.
        // При вдавливании её обратно происходит событие CROWN_HOME.
        // Её можно вращать в исходное или в установленные положения.
        case COREEVENT_CROWN_SET:
            coreRequestStateChange(CORESETBANNERSTATE);
            break;
        // Можно также получать события кнопок, например, start/split:
        case COREEVENT_STARTSPLITDEPRESS:
            show_message();
            break;
        // Кнопка режима, вероятно, означает, что пользователь хочет выйти...
        case COREEVENT_MODEDEPRESS:
            coreRequestModeChangeNext();
            break;
    }

    return;
}

В общем случае можно игнорировать все ненужные вам события.

Сервисы


Ядро занимается работой с оборудованием, передачей разработчику событий, а также предоставляет различные сервисы.

Это такие вещи, как таймеры, генерация сигналов (писка), скроллинг дисплея, доступ к записям базы данных и так далее.

uint8_t banner[] = {
    LCDBANNER_COL10,
    DM5_H, DM5_E, DM5_L, DM5_L, DM5_O, DM5_EXCLAMATION,
    LCD_END_BANNER
};

lcdClearDisplay();

// Отрисовываем "hello!" при помощи сервисов ядра.
lcdDispBannerMsg(&banner);

У часов есть заводная головка и можно попросить ядро сконфигурировать её одним из нескольких способов. Например, можно включить импульсный режим, чтобы можно было отслеживать, как быстро пользователь её поворачивает.


У часов есть подсветка, которой тоже можно управлять программно.

Отладка


У устройства нет никакой защиты памяти и тому подобного, при желании можно просто захламить ядро. Так что же произойдёт в случае сбоя?

Одна из задач ядра заключается в том, что каждые две секунды оно уведомляет сторожевой механизм, что по-прежнему активно. Если сторожевой механизм не видит этого уведомления, он просто выполнит сброс часов, так что постарайтесь до этого не доводить!

При выполнении активных вычислений можно случайно вызвать срабатывание сторожевого механизма. Просто не забывайте сообщать ему, что ядро всё ещё активно:

 // Сообщаем сторожевому механизму, что ядро живо.
 hwResetWatchdog();

Симулятор


К счастью, для часов есть очень хороший симулятор, поэтому вам не придётся терпеливо ожидать сброса после каждой опечатки в коде. На самом деле, это опенсорсный сторонний инструмент Virtual Datalink (исходники).

К сожалению, он предназначен только для Windows. Я бы портировал его в Linux, но он написан на Delphi… Можно ли портировать его на Free Pascal? Подскажите!

В симуляторе есть условные контрольные точки, дизассемблер, сохранение состояний и анализ энергопотребления. Мне он показался довольно мощным.


Заключение


Основное приложение, над которым я работаю сейчас — это интеграция часов с remind.

Хакинг этих часов оказался очень увлекательным проектом!

Доступность


Теперь, когда я рассказал так много о любви к этому устройству, пора переходить к плохим новостям.

Часы давно не выпускают и их сложно найти.

Я купил набор из двух устройств на eBay, достаточно было сменить батареи, и они стали как новенькие.

Ссылки


  • Самый важный документ — это очень качественно написанный Design Guide.
  • Также, разумеется, вам понадобится руководство по CPU. Оно тоже замечательное!
  • У тулчейна тоже есть подробное руководство.
  • Наконец, в полной справке по API перечислены предоставляемые ядром сервисы.
Tags:
Hubs:
Total votes 39: ↑38 and ↓1+37
Comments13

Articles