LODA: что кранчат добровольцы в этом проекте и зачем это нужно
LODA: что кранчат добровольцы в этом проекте и зачем это нужно
LODA — это одновременно:
– минималистичный язык наподобие ассемблера для целочисленных последовательностей,
– инструментарий для их исполнения и оптимизации,
– и BOINC-проект для распределённого поиска (майнинга) коротких программ, воспроизводящих последовательности из OEIS (
Цель проекта — найти новые формулы и более эффективные алгоритмы для широкого спектра нетривиальных целочисленных последовательностей.
3 октября 2025 LODA объявил о важной вехе — найдено свыше 140 000 программ (
Параллельно сообщено о запуске публичного API (
и интеграции через Model Context Protocol (MCP) ( Теперь к базе можно обращаться и из чат-агентов
Как работает LODA по шагам:
1. Перебор коротких программ. Программа LODA на компьютерых добровольцев автоматически и систематически порождает компактные программы на языке LODA (описание языка:
2. Сравнение с OEIS. Результаты проверяются с каталогом OEIS ( Совпадения сохраняются в репозиторий — расширяя покрытие последовательностей.
3. Отбор и оптимизация. Инструмент loda-cpp ( умеет майнить, проверять и экспортировать найденные решения, включая генерацию формул и кода для PARI/GP (
4. Композиция решений. Программы могут вызывать другие последовательности (seq), комбинируя найденные блоки (пример:
5. Открытая база. Репозиторий всех найденных программ доступен здесь:
Кому это полезно?
Математикам и редакторам OEIS.
LODA предоставляет исполняемые описания последовательностей, упрощающие проверку, генерацию длинных b-файлов и поиск новых формул. Авторы проекта подчёркивают: найденная программа — это гипотеза, требующая проверки человеком, потому что совпадение с OEIS не является доказательством корректности «для всех n».
Исследователям ИИ и синтеза программ.
LODA — площадка для авто-синтеза и тестирования алгоритмов. Благодаря MCP-интеграции теперь можно использовать базу прямо из ИИ-агентов.
Добровольцам BOINC.
Участники могут подключить CPU-ресурсы через BOINC ( Приложение LODA поддерживает Windows, macOS и Linux (включая ARM).
Преподавателям и популяризаторам.
Проект делает наглядной связь между комбинаторикой и программированием: от таблицы OEIS → кода → формулы.
Почему важна отметка 140 000+ программ
– Существенно увеличено покрытие OEIS программами, где раньше решений не было.
– Ускорена проверка гипотез и генерация новых термов.
– Через API и MCP база становится машинно-ориентированной: можно интегрировать её в собственные инструменты анализа.
Как присоединиться
1. Установить BOINC (
2. Добавить проект LODA через менеджер или напрямую:
Проект активно развивается: документация языка ( и инструменты регулярно обновляются.
Ответ на пост «Я купил игровую консоль и написал для неё BIOS»2
А можно рассмотреть старые компы типа XT?
Эмулятор для них есть в проекте "мурмулятор".
Там же схемы эмуляции различных приставок, компьютеров типа "Радио-86РК" и "ZX-Spectrum".
Надеюсь скоро можно будет эмулировать i286 и i386 - и, возможно, даже получится запустить OS/2 Warp 4.0 Merlin или что-то подобное для офисной работы...
Продолжение поста «Я купил игровую консоль и написал для неё BIOS»2
Меня часто спрашивают, почему я не наносек.
Я маргинал, который знает исключительно вершки-корешки и не умеет ни код нормальный писать, ни что то доводить до конца. Я не закончил три пту в своем городе из за того, что просто отбитый маргинал. Поэтому мне не светит ни госка, ни частная контора, ни даже работа на галере - у меня нет скиллов, а умело продавать себя я не умею и у меня не хватает хватки.
Так что фигня это все, мой максимум - второсортные развлекательные статейки, чисто как бульварное чтиво, только про IT. Почти как нейромусор.
Я купил игровую консоль и написал для неё BIOS2
Осторожно: Статья написана максимально простым языком. Так что если вы гик, но не умеете программировать - вам всё равно будет интересно!
Недавно я наткнулся на DIY-игровую консоль за 1.500 рублей - Waveshare GamePi13. Когда гаджет приехал ко мне, я запустил примеры игр от производителя... и оторопел от 5 FPS в Pong - это ж как плохо нужно код писать!
Не желая мириться с этим, я открыл схему устройства, даташит на RP2040 и принялся писать свой собственный BIOS. Если вам интересно узнать, как работают DIY-консоли «изнутри», можно ли запускать внешние программы на микроконтроллерах из RAM, как реализованы различные подсистемы BIOS, а в конце даже написать «Змейку» - добро пожаловать под кат!
❯ Предисловие
Иногда китайские производители выпускают на рынок дешевые гаджеты с ориентиром исключительно на гиков. Чего-уж говорить, с какой-нибудь R36s чего только не сделали: и кастомные прошивки, и порты игр с ПК, и даже достаточно сложные аппаратные модификации. Однако в тусовке DIY'щиков обычно всё куда хардкорнее...
«Андерграундные» консоли выходят чуть ли не каждый день, но лишь единицы из них становятся хоть сколь либо популярными и попадают на массовый конвейер. От «больших» консолей их отличает простая схемотехника, использование распространенных и дешевых микроконтроллеров общего назначения и полная свобода творчества — что хочешь, то и твори! По характеристикам они чаще всего близки к оригинальному GameBoy или GameBoy Advance, а покупают их инженеры, демосценеры и ретро-энтузиасты, которые не только играют во что-то готовое, но и пишут небольшие игрушки сами!
Самые известные консоли такого формата — это нашумевший Playdate и чуть менее известный Arduboy. Обе консоли сильно ограничены в характеристиках и это подстегивает интерес гиков к постоянной оптимизации кода и попыткам впихнуть «невпихуемое». Выделился даже российский «Микрон», представив свою DIY-консоль «для хардкорных ардуинщиков» — некий MikBoy на базе своего же МИК32 «Амур»!
Я уверен что Микроновцы будут читать эту статью... Если вдруг всё получится и MikBoy пойдёт в серию — то напишите мне пожалуйста сообщение :)
Подобным «ардуинщиком» являюсь и я. Ещё со школьных лет меня нереально тянет к микроконтроллерам и Embedded-электронике в целом. О консоли собственной разработки я мечтаю с 14 лет, при этом мне не просто хочется собрать прототип и «забить», но и запустить мелкосерийное ручное производство и продавать устройства подписчикам! К своим 24-годам я сделал два прототипа и развел три платы, но все эти проекты так или иначе откладывались в долгий ящик...
И вот, 25 сентября мне стукнуло 24 годика. Уже взрослый мальчик получил в качестве подарка донат от постоянного читателя и пошёл изучать маркетплейсы в поисках интересного железа. По ключевым словам «tft lcd diy» был найден «ESP32 Bitcoin Miner V2» (выгодный девкит с 2.8" и ESP32-S2), девкит ESP32 с 4.3" дисплеем и емкостным тачскрином, а также некий Waveshare GamePi13, о котором мы сегодня с вами и поговорим!
Отдельное спасибо хотелось бы сказать тем самым подписчикам. Без вашей поддержки этой статьи бы не было!
Waveshare — знаменитый в кругах энтузиастов SBC производитель. В основном компания занимается дисплеями, модулями расширения и одноплатными компьютерами.
В тот же день я заказал устройство, и уже через 3 недели трепетного ожидания, GamePi13 оказался у меня на столе. На первый взгляд консоль показалась очень маленькой: её 1.3" дисплей был даже меньше, чем у Nokia 6230i, а кнопки оказались расположены непривычно близко друг к другу. Ко всему прочему, у консоли не было предусмотрено вообще никакого корпуса: ни «болванки» от производителя, ни STL-файлов для печати. Что-ж, это только придаёт брутальности нашему устройству!
Как вы уже могли заметить, консоль состоит из двух независимых модулей: платы разработки Waveshare RP2040-PiZero и «бутербродного» геймпада с дисплеем, который подключается к гребёнке основной платы. В этом и кроется главный секрет устройства: геймпад изначально рассчитан именно для «одноплатников» Raspberry Pi, но поскольку Waveshare также выпускает плату RP2040 с Pi-совместимой гребёнкой, они решили заодно адаптировать его и для PiZero.
❯ Что внутри?
Хоть PiZero и похожа на референсную плату в лице Raspberry Pi Pico, у неё есть несколько серьёзных отличий:
Во первых, на плате установлена SPI-флэшка объёмом аж в 16МБ. Это максимальный объём, который поддерживает XIP-контроллер в RP2040. В RPi Pico же используется флэш-память объёмом всего в 2МБ.
Далее внимание привлекает использование менее эффективного ULDO RT9193 вместо полноценного DC-DC преобразователя в оригинальном Pico. Сам микроконтроллер сможет работать при разрядке аккумулятора ниже 3.6В, а вот периферия — под вопросом. Иными словами, мы не сможем использовать «все соки» из аккумулятора и нам придётся реализовывать отсечку по напряжению.
На плате распаяна микросхема-чарджер литий-ионных аккумуляторов ETA6096 с током зарядки аж в 1А. Если захотите использовать аккумулятор меньшей емкости — стоит подобрать резистор ISET большего номинала, иначе есть риск перегрева.
Из разъёмов распаян HDMI (да, я тоже в шоке), слот для MicroSD (под него отдали весь SPI0) и два Type-C: один для аппаратного USB-контроллера в RP2040, второй для USB через PIO. В общем, пытались угодить всем.
Плата с геймпадом не менее интересная. С фронтальной стороны у нас расположилось 10 кнопок и 1.3" IPS-дисплей с разрешением 240x240, использующий контроллер ST7789. Вообще, для такой диагонали разрешение дисплея крайне избыточно: оно не только съедает драгоценные килобайты оперативной памяти для фреймбуфера, но и значительно грузит DMA-контроллер и всю шину SPI. Я бы на месте инженеров установил бы сюда «золотой стандарт» — недорогой 1.8" 128x160. Все кнопки подключены к отдельным пинам без сдвигового регистра и занимают значительную часть доступных GPIO.
С обратной стороны расположился небольшой динамик, усилитель, построенный на базе NS8002, 3.5мм джек для подключения наушников, а также токоограничивающий резистор подсветки и обвязка для дисплея. Подсветка подключена напрямую к VSYS и рассчитана на питание от 3.3В, так что никакой регулировки яркости и продвинутых режимов сна!
Ну что-ж, собираем наш бутерброд обратно, подключаем Type-C и смотрим на одну из представленных демо-игр — Тетрис!
Нет, это не пережатая гифка, игра действительно идёт буквально в 1 FPS и с мерцанием — и это на микроконтроллере с ядром Cortex-M0+ на частоте аж в 150МГц! Я напомню, что N-Gage с процессором TI OMAP на более старом ядре ARM926EJ-S с частотой 104МГц умудрялся тянуть первый Tomb Raider с полностью программным рендерингом в 25 FPS!!!
Далее я решил открыть официальный вики Waveshare и изучить информацию о консоли, где нашел несколько примеров игр для неё, одной из которых был Pong. Какое же было моё разочарование, когда я узнал, что обе игры написаны полностью на Python: игровая логика, маршалинг данных, работа с «железом» — всё это было на интерпретируемом языке и более того, написано плохо и крайне неэффективно!
class hardware():
def init():
spi0=SPI(1,baudrate=900000000, phase=0, polarity=0,
sck=Pin(game_kit.lcd_sck, Pin.OUT),
mosi=Pin(game_kit.lcd_sda, Pin.OUT))
display = st7789.ST7789(spi0, 240, 240,
reset=Pin(game_kit.lcd_rst, Pin.OUT),
dc=Pin(game_kit.lcd_dc, Pin.OUT),cs=Pin(game_kit.lcd_cs, Pin.OUT),
xstart=0, ystart=0, rotation=0)
# 初始界面,提示游戏开始
display.fill(st7789.BLACK)
display.text(font2, "Pong!", 90, 90)
display.text(font2, "Let's go!", 60, 140)
time.sleep(1)
hardware.display = display
class pong():
def __init__(self):
# bgm
self.bgm = p_music(p_music.song2, tempo=1, duty=500, pins=[
Pin(game_kit.buzzer, Pin.OUT)])
# 控制音乐暂停和播放的键start
self.key_start = button(game_kit.key_start, self.key_start_callback)
# led
self.led = Pin(game_kit.led_sta, Pin.OUT)
Ни о каком подобии SDK или библиотеки для абстрагирования работы с железом даже речи не шло, практически всё, кроме номеров пинов, было захардкожено прямо в коде игры. О хорошей архитектуре тоже речи не идёт: один класс на всю логику с глобальными переменными... В общем, сэмплы писал либо новичок, либо прожженный эмбеддер :)
Драйвер дисплея даже не пытается использовать DMA, из-за чего даже Понг, состоящий из трёх прямоугольников умудряется тормозить.
def blit_buffer(self, buffer, x, y, width, height):
"""
Copy buffer to display at the given location.
Args:
buffer (bytes): Data to copy to display
x (int): Top left corner x coordinate
Y (int): Top left corner y coordinate
width (int): Width
height (int): Height
"""
self.set_window(x, y, x + width - 1, y + height - 1)
self.write(None, buffer)
Звуковая подсистема, состоящая из одноканальной тональной пищалки на аппаратном ШИМ-контроллере, тоже была со своими «приколами». Например «тишина» — это 0, то есть магнит всегда прижат к нижней части, хотя должно быть PWM_MAX / 2.
Под впечатлением от такого кода, я решил попробовать написать SDK для этой консоли сам. Однако моё видение идеальной DIY-консоли сильно отличалось от того-же Arduboy или Playdate!
❯ Архитектура
При проработке архитектуры будущего «BIOS», я сразу же поставил для себя несколько чётких задач:
Во первых, BIOS должен быть достаточно абстрактным для того, чтобы скрывать от игры детали реализации конкретного «железа». Иными словами, игра оперирует не DMA-контроллерами, FPU-сопроцессором и SPI, а набором простых и понятных подсистем: графика, ввод, звук, хранилище. Кроме того, это позволяет легко портировать игры для такого BIOS'а на другие платформы: можно без проблем реализовать симулятор (не эмулятор!) консоли на ПК или портировать её на ESP32 с минимальными изменениями.
Во вторых, мы ставим производительность в основной приоритет при разработке устройства. В конце-концов это же позорище, что простейшая игра тормозит и мерцает на мощном микроконтроллере, но при этом тетрисы с трёхмерной графикой вполне шустро работали на телефонах Sony Ericsson 2005 года. Именно поэтому для написания игр используются не скриптовые языки по типу Lua или JS, а самый обычный «C с классами».
В третьих, сам BIOS должен быть легко портируем между разными платами (у SpotPear есть вторая похожая плата — уже с 1.5" и стиком) и даже аппаратными платформами. Этот проект может стать основной прошивкой для консоли уже моей разработки и иметь вот такую «кроссплатформу» было бы отнюдь не лишним!
Руководствуясь критериями выше, я решил писать BIOS на C++ (на деле C с классами) с активным использованием интерфейсов и VMT. Это позволяет не только удобно структурировать модули и повышает читаемость кода игры, но и избавляет от необходимости вручную составлять таблицу системных вызовов к API. Тем не менее, в таком подходе есть один серьёзный нюанс: когда у подсистем появляются новые методы или добавляются перегрузки к прошлым, их необходимо по порядку добавлять в конец интерфейса, иначе VMT ломается.
vtable for CTest:
.word 0
.word typeinfo for CTest
.word CTest::Test()
.word CTest::Abc()
vtable for ITest:
.word 0
.word typeinfo for ITest
.word __cxa_pure_virtual
.word __cxa_pure_virtual
В своё время Microsoft решила эту проблему в COM с помощью QueryInterface и миллиона вариаций этих самых интерфейсов: IDirectSound8, IDirectDraw7 и т.д, но мы можем не изобретать велосипед, а просто предоставлять «старым» играм такие же «старые» версии VMT.
Основным объектом в BIOS'е является CSystem, который содержит в себе ссылки на другие подсистемы консоли, а также на информацию о текущей аппаратной платформе:
/// @brief Primary system service, supplied to both games and system modules.
class ISystem
{
public:
virtual CSystemInfo* GetSystemInfo() = 0;
virtual void* Alloc(uint32_t size) = 0;
virtual void Free(void* ptr) = 0;
virtual IGraphicsService* GetGraphicsService() = 0;
virtual IInputService* GetInputService() = 0;
virtual IDebugService* GetDebugService() = 0;
};
Несмотря на кажущуюся «динамическую» натуру системы, никаких IID я переизобретать не стал. BIOS должен реализовывать ровно тот минимальный функционал системы, который нужен. Экземпляр CSystem создаётся так называемым «портом» на конкретную плату, который должен заполнить структуру с указателями на реализации подсистем — прямо как machine-файлы в Linux! И RAII не нарушили, и полный контроль без костылей сохранили — ляпота!
void InitializePlatform()
{
CommManager = new CCommunicationManager();
CDebugService* dbgSvc = new CDebugService();
/* Print some userful debug information */
CJEDECFlashID* flashId = FlashManager.GetFlashID();
dbgSvc->Print("Initializing platform");
dbgSvc->Print("Flash memory manufacturer: 0x%x, capacity: %dKb", flashId->Manufacturer, flashId->Capacity / 1024);
dbgSvc->Print("CID: %d", FlashManager.GetCID());
dbgSvc->Print("First available: %d", FlashManager.GetFirstUserSector());
/* Service initialization */
InputService = new CInputService(dbgSvc);
GraphicsService = new CGraphicsService(dbgSvc);
/* Platform description info */
PlatformInfo.DebugService = dbgSvc;
PlatformInfo.GraphicsService = GraphicsService;
PlatformInfo.InputService = InputService;
System = new CSystem(&PlatformInfo);
}
int main() {
InitializePlatform();
while (true) {
/* Tick all platform-depend services here */
CommManager->Tick();
PowerStateManager.Tick();
InputService->Tick();
System->Tick();
}
}
В целом, базовая архитектура примитивная и понятная. Перейдем же к деталям реализации конкретных модулей.
❯ Графика
Первая подсистема, которую я реализовал — была графической. Концептуально она разделена на два отдельных модуля: драйвер дисплея, который позволяет получить его параметры и в будущем управлять его состоянием, а также модуль для рисования на поверхностях. Прямо как в DirectDraw:
struct CFrameBufferInfo
{
uint16_t Width;
uint16_t Height;
CColor* Pointer;
uint32_t Size;
};
class IDrawingSurface : public ISystemService
{
public:
virtual void Clear(CColor color) = 0;
virtual void DrawBitmap(CBitmap* bitmap, int x, int y) = 0;
virtual void DrawBitmapEx(CBitmap* bitmap, int x, int y, CSpriteInfo* spriteInfo) = 0;
virtual void DrawRect(CColor color, int x, int y, int width, int height) = 0;
virtual void FillRect(CColor color, int x, int y, int width, int height) = 0;
virtual void DrawLine(CColor color, int x1, int y1, int x2, int y2) = 0;
virtual void DrawString(CColor color, int x, int y, CAnsiChar* str) = 0;
};
class IGraphicsService : public ISystemService
{
public:
virtual void SetPowerState(bool isPowerEnabled) = 0;
virtual void SetBacklightState(bool isBacklightEnabled) = 0;
/* Maybe some controller-related functions in future? Like BIAS and HW rotation? */
virtual CFrameBufferInfo* GetFrameBufferInfo() = 0;
virtual IDrawingSurface* GetDrawingSurface() = 0;
virtual void Flush() = 0;
};
Сам драйвер дисплея классический: в его задачи входит инициализация контроллера, выделение памяти под фреймбуфер и регулярное обновление изображения на матрице. Поскольку в таких устройствах используются стандартные MIPI DBI экраны с набором команд DCS, часть кода инициализации и работы с дисплеем стало возможным унифицировать:
/* Perform hardware reset */
gpio_put(PIN_LCD_RST, 0);
sleep_ms(DISPLAY_INIT_SLEEP_TIME);
gpio_put(PIN_LCD_RST, 1);
sleep_ms(DISPLAY_INIT_SLEEP_TIME); /* Wait for display controller to complete initialization */
Reset(); /* Perform software reset to maintain default register state */
SendCommand(cmdSLPOUT, 0, 0); /* Disable sleep mode */
SendCommand(cmdCOLMOD, 0x05); /* Set color format and decoding*/
SendCommand(cmdINVON, 0, 0); /* Disable inversion */
SendCommand(cmdNORON, 0, 0); /* Enable normal mode */
SendCommand(cmdMADCTL, cmdMADCTL_RGB); /* Set pixel size */
uint8_t windowSize[] = { 0 >> 8, 0, DISPLAY_WIDTH >> 8, DISPLAY_WIDTH }; /* Set display window (note this is not safe for displays with sides not equal in size) */
SendCommand(cmdCASET, windowSize, 4);
SendCommand(cmdRASET, windowSize, 4);
SetPowerState(true); /* Enable display */
Вероятно читатель может спросить: «зачем выделять целых 115КБ под фреймбуфер, если можно использовать команды CASET/RASET и рисовать отдельные спрайты прямо в память дисплея?». Дело в том, что в таком случае скорость отрисовки будет падать обратно пропорционально размеру и числу рисуемых изображений. Если мы попытаемся нарисовать параллакс-фон, состоящий из трёх картинок с размерами 240x240, то нашим узким местом станет не только цена обращения к XIP-кэшу, но и производительность SPI-контроллера (который напрямую тактируется от системного PLL) и мы получим те самые 1-2 FPS. Кроме того мы потеряем возможность использования DMA и нам придётся ждать каждой транзакции на экран: это проблема многих «самодельных» консолей, которую, впрочем, можно решить обратившись к опыту предков — а именно PPU.
В своём проекте я решил активно задействовать DMA-контроллер для отправки фреймбуфера на дисплей. Концепция простая: мы указываем ему переслать фреймбуфер, начинаем подготавливать следующий кадр и если транзакция ещё не завершена - то дожидаемся её окончания, дабы картинка оставалась целостной. Однако если обновление логики следующего кадра завершается быстрее, чем DMA-контроллер успевает отправить сканлайны - мы можем получить эффект тиринга.
/* Setup DMA for SPI */
dmaChannel = dma_claim_unused_channel(true);
dmaConfig = dma_channel_get_default_config(dmaChannel);
channel_config_set_transfer_data_size(&dmaConfig, DMA_SIZE_8);
channel_config_set_dreq(&dmaConfig, spi_get_dreq(spi1, true));
channel_config_set_read_increment(&dmaConfig, true);
channel_config_set_write_increment(&dmaConfig, false);
...
if(!dma_channel_is_busy(dmaChannel))
{
uint8_t cmdByte = cmdRAMWR;
gpio_put(PIN_LCD_CS, 0);
gpio_put(PIN_LCD_DC, 0);
spi_write_blocking(spi1, &cmdByte, 1);
gpio_put(PIN_LCD_DC, 1);
dma_channel_configure(dmaChannel, &dmaConfig, &spi_get_hw(spi1)->dr, frameBufferInfo.Pointer, frameBufferInfo.Size, true);
}
Далее переходим к фактической отрисовке изображений. На данный момент поддерживается только один формат пикселей — RGB565, поскольку нет особого смысла использовать 8-битную палитру для изображений 32x32 (но есть смысл использовать 4х-битную, как на NES). Процесс рисования называется блиттингом и поскольку реализация полноценного альфа-блендинга слишком дорогая для реалтайм графики на микроконтроллерах, для описания прозрачности используется техника колоркеев.
Взято с pinterest
ColorKey — это как ChromaKey, но для описания прозрачного цвета используется только базовый цвет, а не цвет + порог допустимых цветов. Помните как в играх 90-х были картинки с розовым фоном цвета Magenta? Вот это оно самое :)
for(int i = 0; i < min(y + bitmap->Height, frameBufferInfo->Height) - y; i++)
{
CColor* bitmapScanline = &bitmap->Pointer[i * bitmap->Width];
CColor* scanline = &frameBufferInfo->Pointer[(y + i) * frameBufferInfo->Width + x];
for(int j = 0; j < min(x + bitmap->Width, frameBufferInfo->Width) - x; j++)
{
uint16_t sample = *bitmapScanline;
if(sample != bitmap->ColorKey)
*scanline = sample;
scanline++;
bitmapScanline++;
}
}
Рисование текста реализовано знакомым для Embedded-инженеров способом: шрифты описываются в формате 8x8, где 8 битов каждого байта обозначают наличие или отсутствие пикселя в текущей позиции. Такие шрифты не только занимают очень мало места, но их также очень легко и быстро рисовать, а также масштабировать под различные разрешения экранов. На данный момент я задумываюсь — стоит ли добавлять в консоль поддержку полноценного UTF-16, если учесть что основной таргет на русскоязычную аудиторию, где и CP866 хватает с головой?
❯ Ввод
Далее мы плавно переходим к реализации драйвера ввода. Как я уже говорил выше, все кнопки подключены к своим отдельным GPIO без использования сдвигового регистра или I/O Expander'а, что с одной стороны и хорошо (некоторые китайские производители реализовывают консоли с кнопками, основанными на матричном (!!!) принципе), а с другой — отъедает большинство GPIO у RP2040. Свободными пинами мы могли бы выполнять множество полезной работы: получать уровень заряда аккумулятора у Fuel Gauge, управлять уровнем подсветки с помощью ШИМ-контроллера и ключа, или, в конце-концов, сделать порт для подключения периферии... но нет так нет.
Сам по себе драйвер ввода до жути примитивный: он позволяет получить состояние отдельных кнопок, осей (как Input.GetAxis в Unity) и проверить, нажата ли хоть какая-то кнопка:
class IInputService : public ISystemService
{
public:
virtual EKeyState GetKeyState(EKeyCode keyCode) = 0;
virtual int GetAxis(EInputAxis axis) = 0;
virtual bool IsAnyKeyPressed() = 0;
};
Для удобства и портабельности BIOS'а между платами, кнопки геймпада маппятся к соответствующим GPIO в отдельной таблице трансляции, которая также содержит состояния этих самых кнопок:
// Should be layouted in order of EKeyCode enum
CButtonState ButtonMapping[] = {
{
PIN_KEY_LEFT
},
{
PIN_KEY_RIGHT
},
{
PIN_KEY_UP
},
{
PIN_KEY_DOWN
},
{
PIN_KEY_A
},
{
PIN_KEY_B
},
{
PIN_KEY_X
},
{
PIN_KEY_Y
},
{
PIN_KEY_LEFT_TRIGGER
},
{
PIN_KEY_RIGHT_TRIGGER
}
};
Дело в том, что в нашем проекте недостаточно иметь лишь одно булево: нажата-ли кнопка или нет, для компенсации дребезга кнопок у нас также реализуется задержка перед следующей проверкой и дополнительное состояние для удобства реализации меню — «только что отпущена».
void CInputService::Tick()
{
timeStamp = get_absolute_time();
for(int i = 0; i < ButtonMappingCount; i++)
{
CButtonState* buttonState = &ButtonMapping[i];
bool gpioState = !gpio_get(buttonState->GPIO); // Buttons are pull-up to high when not pressed
// Check if there was elapsed enough time
if(timeStamp > buttonState->LastStateChange)
{
if(buttonState->State == EKeyState::ksReleased)
buttonState->State = EKeyState::ksIdle;
if(buttonState->State == EKeyState::ksIdle && gpioState)
buttonState->State = EKeyState::ksPressed;
if(buttonState->State == EKeyState::ksPressed && !gpioState)
buttonState->State = EKeyState::ksReleased;
buttonState->LastStateChange = timeStamp + KEY_DEBOUNCE_THRESHOLD;
}
}
}
Таким образом, мы получаем куда более удобную подсистему ввода, чем условная битовая маска с обозначением каждой кнопки и ручной обработкой её состояний в игре...
EKeyState CInputService::GetKeyState(EKeyCode keyCode)
{
uint32_t code = (uint32_t)keyCode;
if(keyCode >= ButtonMappingCount)
return EKeyState::ksIdle; /* Maybe we should throw an exception? */
return ButtonMapping[code].State;
}
int CInputService::GetAxis(EInputAxis axis)
{
EKeyCode a = EKeyCode::keyLeft;
EKeyCode b = EKeyCode::keyRight;
if(axis == EInputAxis::inputAxisVertical)
{
a = EKeyCode::keyUp;
b = EKeyCode::keyDown;
}
return GetKeyState(a) == EKeyState::ksPressed ? -1 : (GetKeyState(b) == EKeyState::ksPressed ? 1 : 0);
}
А вот и результат:
❯ Запуск программ
Вот мы и подошли к, возможно, самой интересной подсистеме в нашем BIOS'е. Думаю многие читатели так или иначе интересовались тем, как же компилятор и линкер превращают исходный код и объектный файлы в пригодные для выполнения программы и библиотеки. Вопрос запуска нативных программ на микроконтроллерах интересовал и меня — я даже написал целых три статьи об этом: в первой мы поговорили о ESP32 и Xtensa, а во второй реализовали BinLoader путём реверс-инжиниринга и хакинга кнопочного телефона, а в третьей сделали полу-универсальный ElfLoader для нескольких моделей телефонов на разных платформах.
Но начнём мы с простого. Каждая программа делится на три основных секции:
.text — содержит в себе машинный код функций и так называемые Literal pools. Может быть как в ROM, так и в RAM. На системах, где есть возможность выполнять код и в ROM, и в RAM, есть отдельная секция - .iram.
.data — содержит инициализированные переменные, которые обычно попадают в оперативную память. Для статических констант есть отдельная секция, называемая .rodata.
.bss — содержит в себе не-инициализированные переменные, обычно это нули. В исполняемый файл секция .bss напрямую не записывается, остаётся лишь информация о том, каков её размер, а саму секцию затем выделит динамический линкер.
Куда попадут части программы определяет специальная утилита — линкер, которая на основе специального скрипта «раскладывает» данные по нужным секциям. Благодаря этому скрипту, мы можем, например, перенести часть функций в оперативную память для более быстрого исполнения или добавить в начало программы заголовок с описанием приложения.
В моём случае, я решил загружать игры в SRAM и дабы не реализовывать нормальный динамический линкер и релокации, решил выделить под игру фиксированный кусочек оперативной памяти объёмом в 128КБ. Для этого я отредактировал скрипт линкера Pico C SDK так, чтобы сразу после вектора прерываний шла наша программа:
. = ALIGN(4);
.ram_vector_table (NOLOAD): {
*(.ram_vector_table)
} > RAM
iram_program_reserve_size = 128K;
.iram_program (NOLOAD) : {
. = ALIGN(4);
PROVIDE(iram_program_origin = .);
. += iram_program_reserve_size;
} > RAM
.uninitialized_data (NOLOAD): {
. = ALIGN(4);
*(.uninitialized_data*)
} > RAM
Для компиляции программы также используется кастомный скрипт для линкера и особый Makefile, где после сборки программы мы копируем все её секции в выходной файл в «сыром» виде. Поскольку программа собирается под выполнение из конкретного адреса — пока речь идёт о переносимости только между одной аппаратной платформой. На RP2040, RP2350 и возможно STM32 такое «прокатит», но вот на других ARM-процессорах — большой вопрос!
OUTPUT_FORMAT("elf32-littlearm")
SECTIONS
{
. = 0x200000c0;
.program_info : {
*(.program_info*)
}
.text : {
*(.vtable*)
*(.text*)
*(.rodata*)
*(.data*)
*(.bss*)
}
/DISCARD/ : {
*(.ARM.*)
*(.comment*)
}
}
Каждое приложение, как и базовая система, предполагает использование ООП и поэтому представляет из себя реализацию класса IApplication. Для этого нам нужна некоторая runtime-поддержка: аллокатор, функция для создания экземпляра приложения, а также указатель на ISystem. Именно поэтому каждая программа должна экспортировать специальный заголовок, где содержится указатель на функцию-инициализатор:
#define PROGRAM_HEADER 0x1337
#define PROGRAM_INFO(name, clazz) int test; CAllocator* __Allocator; IApplication* __createInstance(CAllocator* allocator, ISystem* systemPtr) { __Allocator = allocator; return new clazz(systemPtr); } \
CProgramInfo __program_info __attribute__ ((section(".program_info"))) = { PROGRAM_HEADER, BIOS_VERSION, name, &__createInstance };
struct CProgramInfo
{
uint32_t Header;
uint32_t BIOSVersion;
CAnsiChar Name[32];
CreateApplicationInstanceFunction CreateApplicationInstance;
};
...
PROGRAM_INFO("Blink", CBlinkApplication)
Таким образом, для выполнения нашей программы и вызова её обработчиков событий нам достаточно лишь загрузить файл по адресу 0x200000c0 и создать экземпляр IApplication. Всё очень просто и понятно!
CAllocator allocator;
allocator.Alloc = malloc;
allocator.Free = free;
IApplication* app = ((CProgramInfo*)ptr)->CreateApplicationInstance(&allocator, System);
Но "моргалка" ведь слишком просто, согласитесь? Поэтому мы с вами напишем ремейк классической игры Змейка, которая работает в настоящие 60 FPS!
❯ Заключение
Вот таким нехитрым образом я понемногу реализовываю свою мечту детства: «андерграунд" консоль собственной разработки. Конечно здесь ещё много чего нужно доделывать перед тем, как начинать разводить свою плату, но начало ведь положено! В контексте GamePi13, я считаю что моя реализация SDK для консоли всё таки немного лучше, чем то, что предлагает производитель «из коробки».
Я понимаю что мой не совсем трушный эмбеддерский подход может вызвать разные ощущения у читателей: так что приглашаю всех заинтересованных в комментарии, обсудим с вами «сломанный Branch-prediction из-за виртуалов», «UB из-за того, что порядок указателей на реализации в VMT может отличаться» и «какого фига игры у тебя оказались в SRAM, а высокопроизводительный код на Flash, если у XIP кэш всего в 16КБ!».
А если вам интересна тематика ремонта, моддинга и программирования для гаджетов прошлых лет — подписывайтесь на мой Telegram-канал «Клуб фанатов балдежа», куда я выкладываю бэкстейджи статей, ссылки на новые статьи и видео, а также иногда выкладываю полезные посты и щитпостю. А ролики (не всегда дублирующие статьи) можно найти на моём YouTube канале.
Если вам понравилась статья...
И у вас появилось желание что-то мне задонатить (например прикольный гаджет) - пишите мне в телегу или в комментариях :) Без вашей помощи статьи бы не выходили! А ещё у меня есть Boosty.
Подготовлено при поддержке @Timeweb.Cloud
Почему Palm 2004 года работает быстрее, чем iPhone?
В наше время эталоном плавности и производительности среди мобильных устройств принято считать iPhone. Действительно, инженеры Apple проделали довольно большую работу по оптимизации скорости отрисовки и плавности интерфейса, однако не одним iPhone мы были едины!
В 2004 году, Palm выпустила уникальный смартфон, который сочетал в себе привычный интерфейс, широкий функционал, невероятную производительность и... эмулятор M68k. Я решил разобраться, в чём-же заключается его главный секрет и готов рассказать вам о Treo 650 во всех подробностях!
Для ЛЛ: особая архитектура ОС
❯ Предыстория
Устройства Palm всегда были уникальными и концептуально отличались от других карманных компьютеров. Пока другие производители гнались за самым мощным железом и функционалом, Palm делала акцент на обратную совместимость программ, высокую производительность и синхронизацию с ПК. История портативных гаджетов Palm начинается с КПК Pilot 1000, который вышел в 1996 году и стал одним из первых действительно массовых гаджетов в таком форм-факторе.
Pilot 1000 отдаленно напоминал современные смартфоны: у него был интерфейс, адаптированный для работы стилусом или пальцем, функционал органайзера, а также возможность установки сторонних программ и синхронизации с ПК. При этом у Palm'ов была одна очень интересная особенность: для ввода текста предлагалось использовать не виртуальную клавиатуру, а развитую технологию рукописного ввода Graffiti, которая стала визитной карточкой компании на протяжении долгих лет! Внутри Pilot'а был современный для тех лет процессор Motorola MC68328, работавший на частоте 16МГц и целых 128КБ оперативной памяти, а розничная цена составляла всего 299$, что обеспечило популярность модели и интерес со стороны разработчиков софта.
После успеха Pilot 1000, Palm продолжила развивать линейку КПК на всё той-же аппаратной платформе, постепенно проводя её апгрейды: сначала вышел Pilot Personal/Professional с поддержкой модема от 3Com, затем Pilot III с 2МБ оперативной памяти, подсветкой экрана и ИК-портом, а годом позже и флагманский Palm VII с доступом к интернету с помощью сети Mobitex. К 2000 году для PalmOS вышло довольно много различного софта, причём большинство было платным и для его покупки надо было выписывать чек или покупать физическую копию на диске.
К 2001-ому году, Palm начала терять позиции на рынке карманных компьютеров из-за появления Microsoft PocketPC: операционная система на базе Windows CE имела многозадачность, позволяла легко портировать программы с ПК благодаря схожему API и поддерживала самые разные архитектуры процессоров. Несмотря на то, что устройства на PPC были значительно дороже, многие пользователи отдавали предпочтение именно им — и с этим нужно было что-то делать.
В марте 2001 года компания представила новую модель — m505, которая отличалась наличием 16-битного цветного дисплея, новым процессором Motorola Dragonball VZ, работавшем на частоте 33МГц и целыми восемью мегабайтами оперативной памяти, а также новой операционной системой PalmOS 4.0. Кроме этого, компания начала лицензировать PalmOS сторонним производителям, благодаря чему появилась линейка самобытных КПК Sony CLIÉ.
Однако уже в 2002 году, сомнительные перспективы низкочастотных процессоров Dragonball и устаревшей архитектуры m68k были очевидны для Palm и они решились на рискованный шаг: в новой линейке Tungsten они решили перейти на процессоры TI OMAP с архитектурой ARM. Но как тогда быть с уже существующим софтом, который распространялся на дисках? Правильно — встроить эмулятор m68k (PACE) в новую систему PalmOS 5.0 «Garnet»!
И если на первый взгляд эта затея кажется глупой, вы просто сравните Dragonball VZ и TI OMAP 1510:
Ядро: M68EC000 (корни идут от CMOS-версии M68k из 1985 года) vs ARM925T (почти самое современное ядро ARM на момент появления Tungsten, современнее только ARM926E)
Частота: 33МГц vs 144МГц
MIPS (число миллионов инструкций в секунду): 5.4 MIPS vs ~159 MIPS
Кэш-память: Отсутствует vs 16КБ для инструкций и 8КБ для данных
Таким образом, программы для m68k на ARM Palm'ах работали не хуже, чем на оригинальных устройствах, однако с SDK для новых устройств был очень неприятный нюанс...
В том же 2002 году, Palm выпустила первое устройство, где отошла от концепции рукописного ввода и установила полноценную QWERTY-клавиатуру — Tungsten W. Влияние BlackBerry на тенденции бизнес-устройств в те годы было очевидным, поэтому Palm разработали не просто КПК, а целый коммуникатор — с собственным радиомодулем, дисплеем высокого разрешения и... почему-то всё тем-же процессором Dragonball VZ!
Пс, если кому-то Tungsten W не нужен или вы хотите его продать — пните в комментариях пожалуйста. Можно даже нерабочий — ремонтировать такие штучки для меня одно удовольствие!
На то время процессор в Tungsten W казался малость устаревшим... Но сейчас я понимаю — по сути это один из немногих смартфонов с процессором m68k помимо Motorola Accompli!
А через год компания Handspring, созданная выходцами из Palm, представила своё собственное видение смартфона на PalmOS — Treo 600, который является кровным братом Treo 650, о котором мы с вами сегодня и поговорим. Но перед тем, как переходить к обзору устройства — мы с вами сначала его разберём и узнаем, что у него скрывается «под капотом» — здесь действительно есть на что посмотреть!
Свой Treo 650 я купил на китайской онлайн-барахолке примерно за 1.900 рублей вместе с кабелем, а выкупить и привезти его в Россию мне помогли подписчики Роман, Андрей и сервис YouCanBuy, за что вам огромное спасибо.
❯ Что внутри?
Разборка начинается с снятия задней крышки и выкручивания шести винтиков по периметру устройства. Однако перед разборкой я сразу обратил внимание на необычный 6-пиновый АКБ, который явно напоминал HTC'шные аккумуляторы тех лет. Главная их особенность в том, что на BMS (плата защиты) распаяны дополнительные чипы для обмена информацией о модели аккумулятора, его заряде, температуре и другие необходимые данные. Если запитать коммуникатор HTC тех лет от «лабораторника» просто подключив плюс и минус, то гаджет скорее всего включится, но драйвер контроллера питания не даст разрешение на старт зарядки и в меню не будет виден индикатор уровня заряда.
После разборки нас встречает «бутербродная» плата и до боли знакомая схемотехника. К сожалению, в процессе эксплуатации гаджет залили водой — на защитных экранах и контактах видны следы лёгкой коррозии, а на тест-поинтах и пятачках не распаянных SMD-компонентов — заметные потемнения.
Начнём пожалуй с верхней части бутерброда — платы, на которой виднеется слот под сим и IMEI. Крепится она на двух винтах и подключена с помощью разъёма штырькового типа. Думаю всем читателям уже очевидно, что это GSM-модем устройства, однако даже такая банальная вещь реализована здесь весьма необычным способом. Дело в том, что в коммуникаторах нулевых, использование внешних модемов было отнюдь не редкостью. В тех-же самых устройствах RoverPC и O2 можно было встретить внешние платы-модемы Telit, припаянные к основной плате методом поверхностного монтажа. Однако здесь, судя по всему, если радиочасть устройства выходила из строя, можно было самому просто поменять плату с модемом на другую и продолжать пользоваться смартфоном как ни в чем не бывало!
Конструктивно модем достаточно прост и построен на относительно распространенной компонентной базе тех лет:
В качестве Baseband-процессора процессора используется система на кристалле Broadcom BCM2132. На самом деле, этот SoC самодостаточен и способен в одиночку выполнять практически все функции необходимые для простого кнопочного телефона. Состоит он из одного ядра ARM926EJ, способного работать на частоте до 74МГц, DSP-сопроцессора на архитектуре Teaklite, контроллера дисплея, камеры, SD-карт, NAND-флэшек, а также шин общего назначения — I2C, SPI, UART, USB.
Чуть правее расположилась так называемая eMCP-микросхема Spansion S71PL032JA0, которая в одном корпусе содержит как оперативную, так и флэш-память, позволяя значительно сэкономить место на плате. Объём памяти скромный — 2МБ PSRAM и 4МБ NOR-памяти. Классика!
Выше процессора находится чип Infineon PMB6258, который выполняет задачи RF-фронтэнда или трансивера. Простыми словами, именно он ответственен за преобразование аналогового сигнала с антенны в цифровой пакет, который затем обрабатывает DSP в Baseband'е. Справедливо и обратное: когда Baseband подготовил GSM-пакет, он отсылает его в трансивер, а тот «пускает» его в эфир!
Рядом с PMB6258 расположился чип PMB2259, который выполняет роль VGA-драйвера или же усилителя сигнала. Вполне возможно, что это некий предусилитель, поскольку рядом с флэш-памятью скрывается ещё один безымянный GSM-усилитель.
С модемом закончили, здесь всё стандартно. Пора разбирать и изучать гаджет дальше: вытаскиваем шлейф клавиатуры и видим очень интересный парт-номер...
HTC... Ну мало-ли, в те годы они были крупным ODM и OEM-производителем, может Palm Treo просто собирали на их заводах?!
После снятия защитных экранов сомнений больше не осталось: рядом с процессором расположился чип производства самой HTC — 30H80049. Точное его назначение мне неизвестно, но по опыту с другими коммуникаторами этого вендора осмелюсь предположить, что он выполняет роль контроллера питания. Поскольку чипы HTC используются только в собственных разработках компании — становится очевидным, что аппаратную часть Palm Treo разработал именитый тайваньский производитель! Кто бы мог подумать?
Также косвенно это подтверждает тот факт, что кроме PalmOS были Treo с Windows Mobile на борту, а как известно — HTC один из главных производителей устройств на WM.
Далее мы видим сердце основной части устройства — топовый для своих лет чипсет Intel PXA270. На самом деле, о крутости этого процессора можно рассказывать часами, чипы на базе микроархитектуры XScale были легендарными в гиковских и промышленных кругах благодаря хорошей документации, отличной производительности и наличию порта Linux. Но давайте по порядку:
Одно ARMv5-совместимое ядро, построенное на собственной микроархитектуре Intel XScale, способное работать на частоте до 624МГц. Также PXA270 поддерживал набор SIMD-инструкций Wireless MMX (олды смахнули слезу, услышав знакомую аббревиатуру).
32 килобайта L1-кэша инструкций + 32 килобайта L1-кэша данных.
Возможность выполнения до 800 миллионов инструкций в секунду (MIPS) при максимальной рабочей частоте.
Контроллеры шин общего назначения: UART, I2C, SPI, USB.
Периферийные модули для управления DRAM, NAND и NOR-памятью, а также контроллер SD-карт.
Контроллеры клавиатуры, дисплея, ШИМ, GPIO и даже встроенный RTC...
64МБ встроенной NOR-памяти типа StrataFlash
И всё это будучи изготовленным на 180нм техпроцессе!
Чуть ниже процессора расположился один-единственный чип SDRAM-памяти производства Infineon объёмом в 32МБ, а также микросхема NAND-памяти M-Systems объёмом аж в 64МБ. Одна флэшка под систему, вторая под пользовательские данные — где такое ещё можно увидеть?!
Над процессором можно заметить микросхему Broadcom BCM2035, которая выполняет роль Bluetooth-контроллера.
Около разъёма можно наблюдать ещё два «питальника» устройства: ШИМ-контроллер MAX1887, а также контроллер зарядки аккумулятора MAX1874E. Чуть ниже расположилась неизвестная микросхема, судя по характерной для Sony маркировке — это контроллер дисплея.
Не менее интересен и сам дисплей смартфона — это крупная 2.8" матрица Sony ACX533AKM с разрешением аж в 320x320, выполненная по технологии TFT-LCD (LTPS). По меркам 2004 года это очень большое разрешение для кнопочного устройства, примерно как в наше время 4K в смартфоне!
Лично меня удивляет тот факт, что на шлейфе присутствует нетипично-большое количество обвязки и в первую очередь внешняя микросхема формирования BIAS-напряжения (контрастности) TI TPS65110, который обычно встроен в сам кристалл дешифратора. Кроме того, похоже что сразу на шлейфе распаян драйвер подсветки — такое тоже встретишь не часто!
Ну что-ж, теперь мы знаем, что у Treo 650 находится «под капотом». На самом деле, у смартфона достаточно необычный даже по меркам тех лет конструктив, местами он напоминает плату самого первого коммуникатора от HTC — Wallaby и именно благодаря этой характерной преемственности, я сразу же понял откуда идут корни устройства!
С оценкой аппаратной части устройства мы закончили, давайте перейдем к программной!
❯ PalmOS — это чудо?
После включения нас встречает калибровка тачскрина, диалог первоначальной настройки и наконец главный экран. У Treo была интересная особенность: концепции рабочего стола в привычном понимании у него могло и не быть, а главным экраном являлось меню приложений, которое было разделено на несколько подгрупп.
В отличии от современников на Windows Mobile, Treo работает невероятно быстро. Почти все приложения открываются моментально и сразу готовы к работе, никаких экранов загрузки, ANR и тормозящих интерфейсов — всё работает так, как в новом iPhone сразу после покупки. И хотя iPhone куда более плавный, чем Treo 650, в некоторых кейсах смартфон от Palm показывает себя не хуже, а то и лучше какого-нибудь iPhone 15 на самой последней iOS!
За такой впечатляющей производительностью скрывается сразу две архитектурные тайны PalmOS. Первая заключается в том, что система от Palm «однозадачная» — и в ней одновременно может работать только один процесс, а для реализации отложных задач предлагается использовать кооперативную многозадачность и события. На самом деле, в ядре системы есть потоки и задачи, однако API для них задокументировано плохо, а планировщик включается лишь по запросу. Таким образом, приложению доступно практически всё процессорное время без необходимости делить его на кванты.
Вторая тайна удивит вас не меньше: помните в начале статьи я рассказывал о встроенном эмуляторе m68k — PACE? Дело в том, что Palm по каким-то причинам не успела портировать системные приложения на ARM и поэтому почти все системные и сторонние программы написаны для архитектуры m68k и выполняются в эмуляторе, сохраняя при этом невероятную производительность! А секрет здесь прост: дело в том, что PACE эмулирует только само процессорное ядро, но не весь КПК Palm. Когда программа вызывает системную функцию, эмулятор её перехватывает и вызывает соответствующую нативную реализацию для ARM.
По такой-же концепции написан эмулятор PPSSPP, а также слой совместимости с x86 в Windows 10 for ARM. По сути, это превращает нативные m68k-приложения в что-то типа интерпретируемых...
Интересно также то, что у PalmOS по сути и не было концепции файловой системы. Приложения хранили свои данные в собственных базах данных, которых могло быть несколько, а сделано это было для упрощения процесса синхронизации с компьютером. Для этого у Palm'ов была очень удобная программа — HotSync. С её помощью производился процесс авторизации пользователя, устанавливался софт (но никто не мешал устанавливать программы с SD-карты), делались бэкапы, а также переносились мультимедийные файлы.
Не менее интересна реализация сетевого стека в Palm'е, которая позволяет прицепить PPP вообще к любым портам в Treo. Сеть через UART? Пожалуйста. Сеть через ИК-порт — тоже без проблем. Сеть через BT или модем 3Com от модели 1998 года? Вообще без проблем! Можно было подключить даже Wi-Fi модуль в формате SDIO-карточки!
Однако в современном интернете у Treo 650 уже всё не так хорошо. К почтовым серверам с SSL он подключится не может, а браузер даже OpenNet не открывает. Это очень грустно...
Зато у Treo 650 всё хорошо с играми. В своё время известный мобильный издатель Astraware портировал на PalmOS многие Shareware-хиты нулевых. Здесь есть полноценная Zuma, Raging Thunder, классические игры Atari, арканоиды, головоломки и множество других игр из нулевых. Не все они работают идеально быстро (в том числе из-за необходимости эмуляции m68k), но поиграть было во что!
А для тех, кому не хватает нативных приложений, есть экзотическая Java-машина от IBM с поддержкой MIDP 2.0. Благодаря ей появляется возможность играть в легендарные игры для J2ME-телефонов, если они не используют специфичное API по типу 3D...
❯ Заключение
Вот такими были смартфоны Palm в начале нулевых годов. По правде сказать, Treo контрастирует на фоне Windows Mobile и Symbian-смартфонов не только невероятной производительностью, но и весьма странными архитектурными решениями. Уж чего-чего, но однозадачную ОС в смартфоне 2006 года точно не ожидаешь встретить, когда даже в самых недорогих и простых кнопочниках трудится полноценная RTOS!
Однако Treo 650 кажется диковинкой только в наше время. В те годы это было желаемое устройство для тех, кому необходимо много переписываться, читать и даже играть... Надеюсь, вам было интересно!
А если вам интересна тематика ремонта, моддинга и программирования для гаджетов прошлых лет — подписывайтесь на мой Telegram-канал «Клуб фанатов балдежа», куда я выкладываю бэкстейджи статей, ссылки на новые статьи и видео, а также иногда выкладываю полезные посты и щитпостю. А ролики (не всегда дублирующие статьи) можно найти на моём YouTube канале.
Если вам понравилась статья...
И у вас появилось желание что-то мне задонатить (например прикольный гаджет) - пишите мне в телегу или в комментариях :) Без вашей помощи статьи бы не выходили!
Подготовлено при поддержке @Timeweb.Cloud
Устройства, которые мы потеряли: на чём работает легендарная Nokia 6600?
Под прошлой статьей о Siemens C65, многие читатели ставили под сомнение легендарность немецких телефонов и говорили о том, что настоящими легендами были устройства от Nokia. И это правда — именно поэтому я решил написать подробную ретроспективную статью, в которой расскажу не только об аппаратных платформах легендарных Symbian-смартфонов, но и об их программных особенностях.
Если вам интересно узнать что внутри у легендарной «бочки», причём здесь КПК Psion и какие необычные решения использовали инженеры Nokia — добро пожаловать под кат!
❯ Предисловие
Телефоны Nokia, наравне с Sony Ericsson, справедливо считаются легендарными. В своё время финские устройства были чуть ли не у каждого: у кого-то были простенькие звонилки на S30, у ребят побогаче — продвинутые мультимедийные телефоны на S40, ну а у совсем крутых были смартфоны на операционной системе Symbian с оболочкой S60. И именно о смартфонах в рамках данной статьи мы с вами и поговорим.
Изначально слово «смартфон» обозначало кнопочное устройство с полноценной операционной системой, многозадачностью и широкими коммуникационными возможностями. В нулевых этот термин в основном применялся к тем гаджетам, где была возможность установки программ написанных на C/C++ и использующих родное API системы. В отличии от простых Java-приложений, такие программы могли использовать практически весь функционал устройства, а также появлялась возможность портирования программ с других платформ.
Устройства на PocketPC for Smartphone — типичные представители смартфонов из нулевых. Предков современных смартфонов с тачскринами называли коммуникаторами.
В нулевых на рынке смартфонных операционных систем было два главных конкурента: Windows Mobile в редакции Smartphone Edition и Symbian. И что очень интересно — обе системы берут корни от электронных органайзеров. В случае с Windows Mobile всё очевидно — это просто специальная версия Windows CE, знакомой нам по устройствам Casio Cassiopeia и HP Jornada, однако с Symbian всё было гораздо интереснее.
Fujitsu Intertop CX-300 — один из представителей HPC на WinCE. Условно говоря, HPC и электронные органайзеры Psion — достаточно близкие по концепции устройства.
Всё началось в 1991 году, когда Psion представила линейку портативных органайзеров (мини-ноутбуков) Series 3. Устройства были относительно недорогими, практичными и долго работали от одного заряда батареек, а в качестве операционной системы использовали многозадачную ОС собственной разработки Psion — EPOC16. В целом, эти устройства нашли своего пользователя и стали достаточно популярными, хотя безусловно были гаджеты и покруче.
В 1997 году Psion представила следующее поколение — Series 5, которое использовало мощные по меркам тех лет 32-х битные процессоры на архитектуре ARM и новую систему EPOC32, которая на этот раз была написана полностью на C++ и на уровне ядра закладывала концепцию ООП. От современников, EPOC32 отличалась очень высокой производительностью, малыми требованиями к объёму ОЗУ и стабильностью благодаря микроядерной архитектуре: большинство драйверов и модулей в системе были отдельными процессами, с которыми как программы, так и ядро могли общаться с помощью встроенного механизма для IPC. ООП-подход на уровне системы также был революционным, однако с его реализацией были определенные проблемы...
В 1996 году выходит первое устройство из серии Nokia Communicator — 9000. Гаджет совмещал в себе функционал как мобильного телефона, так и x86-компьютера на процессоре AMD Elan. Примерно в 1998 году, в Psion понимают, что концептуально 9000 очень сильно напоминает Series 5 и будущее будет за гаджетами, которые совмещают в себе функционал как телефона, так и компьютера. Вместе с Nokia, Motorola и Ericsson, Psion создаёт новую компанию — Symbian Ltd. и в том же 1998 году, она выпускает EPOC Release 5.
Первым мобильным устройством на Symbian (а вернее EPOC Release 5u) стал Ericsson R380, вышедший в 2000 году. Именно к нему впервые был официально применен термин «смартфон», ведь его дизайн и функционал были просто невероятными. В закрытом состоянии это был обычный кнопочный телефон, по дизайну ничем особо не отличающийся от Motorola DynaTAC или Nokia тех лет, однако если откинуть клавиатурный блок — перед нами открывался широкий монохромный дисплей с приличным разрешением в 120x360, а также резистивным тачскрином. В отличии от органайзеров Psion, на R380 нельзя было устанавливать сторонний софт, но всё равно это было революционное для своих лет устройство.
Годом позже подтянулась и Nokia, выпустив в 2001 году новую модель из линейки Communicator — 9210. Модель отличалась форм-фактором ноутбука, цветным внутренним дисплеем и достаточно высоким уровнем интеграции. Для нового устройства Nokia специально доработала существующую аппаратную платформу DCT-3, выделив её в отдельную ветку DCT-L. Именно 9210 стал первым Symbian-смартфоном от Nokia, однако в отличии от знакомой нам оболочки S60, коммуникаторы использовали S80 — специально разработанную для подобного формата устройств. Помимо этого, 9210 был первым Symbian-смартфоном с возможностью установки сторонних программ.
В 2002 году на свет появился первый Symbian-смартфон в привычном для нас форм-факторе — им стал флагманский слайдер 7650 с VGA-камерой. Это было первое устройство, которое использовало фирменную оболочку S60, а также построенное на новой аппаратной платформе WD2, которая и стала основой для легендарных смартфонов из первой половины нулевых...
Но сегодняшним героем станет легендарная «бочка» — Nokia 6600, которая является одним из самых популярных смартфонов эпохи WD2 наравне с N-Gage. Таких устройств у меня целых два и оба подарены подписчиками, за что вам огромное спасибо! Давайте же посмотрим, что у WD2-гаджетов было «под капотом»!
❯ Разбираем
В те годы смартфоны от Nokia делили не только общую аппаратную платформу, но и конструктив. Многие модели были выполнены как эдакий «бутерброд»: верхняя крышка, средняя часть корпуса с отдельной платой клавиатуры, сама плата и задняя часть корпуса. При этом «навесные» модули по типу вибромотора и разъёма зарядки зачастую прижимались пружинными контактами, благодаря чему их можно было легко заменить, а сами детали стоили копейки и были взаимозаменяемыми. Нередко «ремонт» заключался лишь в чистке в контактов... сравните это с заменой слухового динамика на последнем айфоне :)
Первым делом в процессе разборки мы встречаем TN-дисплей с разрешением 176x208. Довольно интересен тот факт, что практически все WD2-смартфоны использовали один и тот же дисплей с одинаковой диагональю и распиновкой. В некоторых моделях менялся лишь направление шлейфа дисплея, но если подключить к N-Gage обратной стороной матрицу от 6600 — она запустится и будет работать. Помимо WD2-устройств, этот дисплей встречался в переходных устройствах таких как N70 и N72, но необычные инженерные решения этих устройств — тема для отдельной большой статьи!
С подключением дисплеев в смартфонах Nokia был отдельный казус. Дело в том, что для устранения наводок на сигнальные линии от радиотракта, инженеры решили использовать EMIF-фильтры в корпусе «стеклях». Только вот эти самые фильтры были очень хрупкими и легко повреждались как в следствии падения, так и погружения под воду — из-за чего телефон показывал белый экран при общей работоспособности. Мастера нередко заменяли эти фильтры на перемычки и всё работало прекрасно.
С фронтальной стороны платы расположилась основная платформа смартфона, а в её центре — чипсет (AP-процессор) под названием UPP WD2. На практике это специальная заказная версия TI OMAP с одним ядром ARM926EJ-S, работающим на частоте 104МГц, SDRAM-контроллером, контроллером NOR-памяти, DSP для работы с GSM-стеком, специальным ASIC'ом и другой периферией по типу контроллера UART и шины I2S. Весьма интересным является тот факт, что Nokia в паре с TI не использовала внешние Baseband'ы (модемы) в паре с AP-процессором, как это было принято в Windows Mobile-устройствах, а уместила всё в один чип...
Чуть ниже процессора расположились 4 чипа NOR-памяти производства AMD, каждый объёмом в 8МБ, что в сумме даёт целых 32МБ! В отличии от NAND-флэшек, NOR включались напрямую в адресное пространство процессора и реализовывали технологию XIP — eXecute In Place. Поскольку EPOC изначально была ориентирована именно на XIP NOR и ROM память, в системе сразу же была оптимизация по потреблению оперативной памяти за счёт того, что библиотеки не загружались в ОЗУ, а выполнялись напрямую из флэш-памяти. Левее процессора расположился чип SDRAM-памяти производства Samsung объёмом в 16МБ — что для тех лет было весьма неплохо!
Чуть выше процессора распаян чип UEM, который выполняет роль контроллера питания, ЦАП/АЦП для динамиков и микрофона, а также «часового» — если процессор в течении 32 секунд после включения не откликается — UEM отключает питание (помним «белые экраны», после которых телефон отключается?). Кроме того, UEM согласовывает напряжение логических уровней для SIM-карты и F-BUS (UART) интерфейса с процессором, а также отвечает за переход в тестовый режим и мониторинг потребления тока с помощью микросхемы токового датчика Zocus.
У разъёма дисплея в верхней части платы можно заметить тот самый фильтр-стекляшку. Такие же фильтры можно увидеть слева от контактов для клавиатуры!
Под защитными экранами скрывается ещё два чипа: первый — PMB3346, который выполняет роль RF-фронтэнда (трансивера) для работы с GSM-сетью. Если говорить очень грубо, то это чип, которому на вход поступают цифровые пакеты GSM, а в эфир уходит радиоволна. Справедливо и обратное — как только приемнику прилетает «пакет» от GSM, он отправляет его DSP Baseband'а, а тот обрабатывает их в читабельный или прослушиваемый вид и отдаёт центральному процессору (или через DMA отправляет аудиотракту — реализации могут быть разными).
Левее расположился GSM-усилитель производства Renesas. Тут особо ничего и не добавить кроме того, что радиочасть у смартфонов на WD2 была относительно больным местом и зачастую при ремонте в этих смартфонах меняли всё по очереди: UPP, UEM, PMB3346, усилок и так далее пока не получат нормальный прием сети.
С обратной стороны платы расположился лишь BT-модуль и камера. В целом, конструктив у устройства простой, но из-за использования жесткого компаунда, который нужно было долго и упорно вычищать из под процессора и UEM, аппаратный ремонт смартфонов Nokia не всегда был простой задачей. Кроме того, особенно отличалась программная часть: мало того что для прошивки необходим программатор, так ещё если не забэкапить сертификаты или, например, в процессе ремонта отъехала флэш-память, то приходилось ещё и покупать эти самые сертификаты, иначе смартфон вообще не работал или падал в ошибку. Вот такая веселуха!
❯ Включаем
Вы когда-нибудь задумывались о том, что происходит после нажатия на красную кнопку? Вот я — да и поэтому по крупицам на основе опыта с другими устройствами выстроил следующую схему. Начинается всё с того, что контроллер питания обнаруживает низкий уровень на пине PWRBUTTON после нажатия на кнопку включения и переходит в состояние «включения». UEM включает необходимые для работы процессора и памяти регуляторы напряжения, а также разрешает работу драйвера подсветки, после чего в течении 32х-секунд ожидает начала поступления сигналов Ping от процессора — это этап «белого экрана».
В это время, процессор сначала выполняет первичный код инициализации из BootROM для настройки периферии, а затем начинает выполнение первичного загрузчика (SPL) из NOR-памяти. В это время загрузчик проверяет показания от токового датчика (Zocus), среднего пина аккумулятора — BSI (если установить BL-4C в смартфон на WD2 — то можно получить лого Nokia без подсветки), и проверяет режим, в котором необходимо запустить смартфон — например Local mode или Test mode. После этого, загрузчик передаёт управление ядру Symbian, ядро проводит быструю самопроверку (как POST в ПК), а затем показывает логотип Nokia — пока ещё без анимации. В процессе загрузки ядра, смартфон инициализирует драйверы необходимые для работы устройства, запускает службы, инициализирует GSM-стек и если не найдена SIM-карта — показывает соответствующее диалоговое окошко. В обратном случае, Symbian показывает ту самую анимацию Nokia и запускает приложение домашнего экрана.
После включения, Symbian показывает себя во всей красе. На самом деле, эта ОС была очень крутой и продвинутой по меркам своих лет, однако из-за сложного API системы и отсутствия совместимости с POSIX (была лишь частичная, да и то через стороннюю библиотеку), разработка приложений для неё была слишком сложна. В отличии от Windows Mobile, для Symbian не было нормального симулятора с отладчиком, адекватной IDE (Carbide — это неадекватная IDE) и даже базовые концепции ОС были чужды для многих разработчиков десктопных приложений. Взять хотя-бы те же самые конструкторы объектов: рантайм C++ в Symbian не поддерживал исключений в угоду производительности и из-за этого каждый объект может иметь два конструктора и два метода-фабрики — один из которых может кидать псевдоисключение и возвращать null, а другой — нет.
Помимо этого, у системы была сложная оконная система. Поскольку играм нужен был прямой доступ к фреймбуферу, предлагалось получить указатель на дескриптор дисплея, ручками определять версию структуры этого самого дескриптора и относительно него выбирать формат пикселя (к слову именно поэтому некоторые игры на поздних Symbian имели искаженные цвета) — коих было целых три — 12, 16 и 18 бит. В общем, полная жесть!
Но тем не менее, те, кто справлялся с сложностью программирования под Symbian — получали максимальную отдачу от железа. Чего уж там говорить, если на 104МГц процессоре такая легендарная 3D-игра, как Lock'n'Load, шла в стабильные 25-30 кадров без какого либо GPU? Чего уж говорить об эмуляторах NES и SMD, которые 6600 уже в 2004-2005 году переваривал практически в Full Speed!
Однако для тех, кому C++ был слишком сложен, была передовая Java-машина. Помимо базового профиля MIDP 2.0, Nokia добавляла свой собственный набор API для работы с устройством. В целом, на Symbian-устройствах чаще можно было встретить именно Java-приложения, поскольку весили они немного и нередко покрывали все потребности пользователя. Мессенджер? Аська! Браузер? Opera MIni или UC Web. Игры? Bobby Carrot и Asphalt!
Стоит ли говорить о том, что мультимедийные возможности смартфона были тоже на высоте? И пристойная VGA-камера, и поддержка как аудиофайлов в формате MP3, так и видеороликов в MP4/AVI и многих других форматах. И всё это умудрялось работать с настоящей, трушной многозадачностью без «скриншотов» как на айфоне, умещаясь в какие-то жалкие 16МБ памяти? Вот то-то же, умели раньше оптимизировать софт!
Заключение
Вот такими были легендарные смартфоны Nokia на платформе WD2. Вся информация бралась из официальной документации на API Symbian и EPOC, схем на устройства и из немногочисленных утечек и наблюдений моддеров. Пожалуй, это самый доступный ретроспективный экскурс в мир Symbian-устройств для гиков!
А если вам интересна тематика ремонта, моддинга и программирования для гаджетов прошлых лет — подписывайтесь на мой Telegram-канал «Клуб фанатов балдежа», куда я выкладываю бэкстейджи статей, ссылки на новые статьи и видео, а также иногда выкладываю полезные посты и щитпостю. А ролики (не всегда дублирующие статьи) можно найти на моём YouTube канале.
Очень важно! Разыскиваются девайсы для будущих статей!
Друзья! Для подготовки статей с разработкой самопальных игрушек под необычные устройства, объявляется розыск телефонов и консолей! В 2000-х годах, китайцы часто делали дешевые телефоны с игровым уклоном — обычно у них было подобие геймпада (джойстика) или хотя бы две кнопки с верхней части устройства, выполняющие функцию A/B, а также предустановлены эмуляторы NES/Sega. Фишка в том, что на таких телефонах можно выполнять нативный код и портировать на них новые эмуляторы, чем я и хочу заняться и написать об этом подробную статью и записать видео! Если у вас есть телефон подобного формата и вы готовы его задонатить или продать, пожалуйста напишите мне в Telegram (@monobogdan) или в комментарии. Также интересуют смартфоны-консоли на Android (на рынке РФ точно была Func Much-01), там будет контент чуточку другого формата :)
Кроме того, я ищу подделки на брендовые смартфоны 2009-2015 года выпуска. Многие из них работают на весьма интересном железе и об их моддинге я бы мог сделать интересный контент. Особо разыскиваются подделки Apple iPhone и HTC (по типу HD2 и Touch Diamond 2) на Windows Mobile и Android, а также Samsung Galaxy. Также представляют моддерский интерес первые смартфоны Xiaomi из серии Mi, Meizu (ещё на Exynos) и телефоны Motorola на Linux (например, EM30, RAZR V8, ROKR Z6, ROKR E2, ROKR E6, ZINE ZN5, о которых я хотел бы подготовить отдельные статью и видео, поскольку они работали на очень мощных для своих лет процессорах, поддавались серьезному моддингу и были способны запустить даже Quake.
Большое спасибо читателям и зрителям за подгоны, без вас контент бы не выходил!
Подготовлено при поддержке @Timeweb.Cloud
Как провалилась сделка NVIDIA + ARM за $40млрд: уроки для отрасли
Конфликт на стыке AI и лицензирования
В сентябре 2020 Года NVIDIA предложила выкупить британскую компанию ARM у SoftBank за $40 млрд (наличными и акциями). ARM была ядром мобильной, серверной и встраиваемой электроники — её архитектура лежит в основе 70 % устройств мира. Предложение пожертвовать независимость ARM вызвало тревогу у регуляторов и конкурентов.
Почему сделка считалась угрожающей
Вертикальная интеграция: NVIDIA использует архитектуру ARM для своих GPU и DPU — объединение могло дать ей доступ к конфиденциальным данным конкурентов, использующих чипы ARM
Риски «отсечения» конкурентов: CMA указала, что NVIDIA могла бы ограничить доступ к ARM IP для производителей серверных CPU, SmartNIC, автомобильных SoC
Угроза национальной безопасности: Великобритания инициировала фазу 2 расследования после обращения министра digital, отмечая, что ARM — стратегический актив
Регуляторы США, ЕС, Китай, Япония и Южная Корея начали свои проверки одновременно — под давлением многочисленных компаний, включая Google, Microsoft, Qualcomm, Samsung и Apple
Жесткая ответная реакция регуляторов
FTC (США) — в декабре 2021 подала административный иск по Sherman Act, заявляя, что сделка угрожает конкуренции на рынках дата-центров, SmartNIC и автопилотов
CMA (Великобритания) — в августе 2021 перешла к фазе 2 и заявила, что предложенные NVIDIA «поведенческие меры» не могут компенсировать угрозы конкуренции
ЕС, Китай и другие — усилили давление, изучая воздействие на открытость архитектуры ARM .
Конец 2021 года стал периодом беспрецедентного одновременного вмешательства регуляторов в сделку вертикального характера.
Почему NVIDIA отказалась
7 февраля 2022 обе стороны объявили о расторжении сделки, сославшись на непреодолимые регуляторные барьеры . Также NVIDIA потеряла $1.25 млрд предоплаты, что было признано «ценой сохранения конкурентного рынка» ARM
Последствия для NVIDIA и ARM
ARM. Возвращаясь самостоя́тельно, компания готовилась к IPO (на весну 2023 года), сохранив бренд, модели лицензирования и R&D в Кембридже .
NVIDIA. Сфокусировавшись на AI и GPU, она продолжила работу с ARM как лицензиат — отказ от поглощения помог избежать расходов на интеграцию и потери влияния на конкурентов.
Что это означает для индустрии
Реструктуризация ролей. ARM осталась нейтральной платформой, что важно для производителей, конкурирующих с NVIDIA и другими.
Сигнал регуляторов. Компании должны учитывать вертикальные сделки в условиях усиленного контроля.
Конкуренция усилилась. Без поглощения ARM стала публичной и открыла новые возможности для компаний вроде Qualcomm, Samsung, Apple, Google.
Архитектурный контроль важен. Независимость ARM сохранит экосистему SoC, IoT и AI гибкой и разнообразной.
UX в сфере чипов? Методы защиты ценности
Хотя речь не о пользовательском интерфейсе напрямую, решение CMA и FTC — это защита архитектурного UX: доступность ARM для всех, даже если это угрожает вертикальной интеграции. С сохранением конкуренции пользователи устройств получают выгоду от технологического разнообразия.
Итоги и выводы
Сделка NVIDIA + ARM провалилась под ударами регуляторов — масштаб и структура не позволяли избежать antitrust.
ARM сохранила независимость, ускорила IPO, сохранила поддержку лицензиатов.
NVIDIA продолжает развивать AI без юридических рисков и затрат, сохранив партнерские отношения.
Для тех, кто строит технологии в масштабах платформ — кейс показывает: угроза вертикальной интеграции ещё сильнее, чем финансовая.
Это кейс не просто о провале сделки, а о защите архитектурной экосистемы, влиянии регуляторов и стратегических рисках вертикальных объединений.



































































