Решив использовать последние дни отпуска для приведения имеющихся у меня запасов электронных компонентов к некоторому подобию порядка я наткнулся на неизвестную михросхему SOT-23-6 с еле читаемой маркировкой.
Микроскоп и гугл помогли идентифицировать микосхему как Attiny10 с 1024 байтами FLASH и 32 байтами SRAM.
Увидев такие весьма ограниченные характеристики я уже хотел было убрать Attiny10 обратно в коробку но почувствовал настальгию. Дело в том, что свой путь в микроэлектронике я начинал именно с микроконтроллеров серии AVR. Мне захотелось сделать на базе микроконтроллера какой нибудь полноценный девайс. В наличии у меня так же оказался OLED LCD Display размером 128x64.

Таким образом идея тетриса и сформировалась окончательно.
Электронная часть:
Я решил подключить LCD дисплей по протоколу 3-SPI. Сам протокол отличается от обычного SPI тем, что значение D/C отвечающее за выбор передачи данных или комманд для дисплея, передается дополнительным нулевым битом в SPI транзакции. Тем самым позволяя не подключать D/C вывод.
Схема подключения дисплея получилась следующая:

После подключения дисплея у микроконтроллера остается всего один свободный вывод PB3, на который требуется подключить как минимум четыре кнопки. Решением в даной ситуации является использование PB3 как вход ADC для следующей схемы:

Наличие делителя обусловлено тем, что PB3 так же является сигналом reset и напряжение на нем при штатной работе не должно падать ниже 0.9V. Конечно, можно было отключить внешний ресет с помощью фьюза RSTDISBL, но в таком случае я бы потерял возможность перепрошивать микроконтроллер, который у меня к слову был всего один.
В итоге получилась следующая общая схема:

Питание осуществляется от крошечной lipo батарейки 3.7V, 180mAh подключаемой к разъему P1. Батарейка оказался единственным элементом который мне пришлось докупить для этого проекта и по заверениям продавца имеет встроенный контроль за over discharge. По этой причине на схеме отсутствует какой либо контроль за разрядкой источника питани��. Так же на схеме нет отдельного разъема для программирование, не считая PLS штырька для RESET. Часть сигналов программирования (PB0 — TPIDATA, PB1 — TPICLK) подключается через разъем дисплея P2. Сам дисплей съемный и стыкуется через PLS.
Вот так выглядит плата после разводки:

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

Программная часть
Учитывая ограниченный объем имеющихся ресурсов Attiny10 вся программная часть реализована на ассемблере без использования сторонних библиотек.
Первое что я сделал это получил значения ADC для нажатия кнопок. Для этого написал отдельную программу суть которой постоянно считывать значения ADC и выводитьэти значения на gpio в формате 8 битной посылки. Дабы не тратить время на прием данных я просто подключился осциллографом к нужным gpio и таким образом считал нужные значения ADC.
Для примера вот так выглядит посылка при нажатии кнопки UP:

Получив значения для нажатия кнопок я перешел к написанию основной логики тетриса, в которой можно выделить следующие ключевые моменты.
Работа с дисплеем
Все объекты отображаемые на дисплее хранятся в SRAM микроконтроллера и учитывая объем в 32 байта тут не обойтись без масштабирования. Поэтому минимальной единицей отображения на дисплее будет квадрат 8х8 пикселей в результате игровое поле получилось размером 8х16 квадратов. Поскольку дисплей монохромный то для хранения значения квадрата хватит одного бита. В итоге, все объекты отображаемые на дисплее укладываются в массив из 16 байт. Чтобы было понятней приведу пример:
0 — 00010000
1 — 00111000
2 — 00 000 000
……………...
15 — 00 000 000
uint8_t t_field[] = {0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Нулевой байт массива соответствует первой строчке игрового поля, 15 — последней. Вот как выглядит это на дисплее:

Сам дисплей работает в horizontal addressing mode, что позволяет легко обновлять изображение просто последовательно передавая данные, инкрементация страниц происходит в самом дисплее.
Отрисовка элементов
Чтобы максимально упростить задачу отрисовки каждый элемент я задаю 8 битным паттерном. Например для элемента

паттерны будут следующие:

Каждый внутренний квадрат содержит номер бита в паттерне. В центре находится точка вращения. Структура описывающая текущий элемент содержит следующие поля:
brick_x координата x
brick_y координата y
brick_rot положение относительно точки вращения
brick_type тип элемента
Плюс такого подхода в том что существенно сокращается объем кода так как все элементы обрабатываются одинаково.
Минус же заключается в том, что невозможно задать элемент составляющий прямую линию из 4 квадратов. Как показало тестирование это довольно существенно, возможно в будущем я добавлю этот элемент с помощью отдельной отрисовки, благо в микроконтроллере осталось место.
Псевдо рандом и некоторые детали реализации
Рандом я сделал на основе комбинировании событий от нажатия кнопок и free run счетчика изменяющегося по таймеру. Получилось не идеально но вполне играбельно.
После включения питания на дисплее отображается заставка с надписью PUSH, разница во времени от появления заставки до нажатия произвольной клавиши обеспечивает случайность в выборе начальной фигуры. Предусмотрен счетчик для подсчета результатов. Каждый раз когда происходит удаление заполненной линии, счетчик инкрементирует на единицу. Изначально я хотел выводить результат в последней строке в виде двоичного кода, но в итоге от этого отказался, выглядело странно и сбивало игрока с толку. Счетчику нашлось другое применение: пауза между смещениями элемента вниз изначально равна 0.7 секунд, по мере набора очков пауза меняется следующим образом:
счетчик: 0..15 пауза 0.7
счетчик:16..31 пауза 0.6
счетчик:32..63 пауза 0.5
счетчик: > 63 пауза 0.4
В результате по мере прогресса в игре скорость падения элементов ускоряется внося дополнительную сложность.
Исходники собирались в Atmel Studio 6. Вся прошивка занимает 898 байт.
Корпус и сборка
Для полноценного девайса нужен корпус и этот корпус стал наверное самой сложной частью проекта. Я перепробовал несколько вариантов, истратил метры филламента и в итоге удалось создать приемлемый вариант:

Для создания 3д модели корпуса я использовал Fusion 360, печатал на Flying Bear Ghost 6, материал PLA.
Процесс сборки

Все исходники и материалы к проекту лежат по ссылке
Посмотреть как все выглядит в процессе работы можно на видео:
UPD: Добавил элемент "прямая линия из 4х квадратов". Репозиторий обновил. Всем спасибо за отзывы.