Project Spirit

Компьютер "Спринтер" http://sprinter.nedopc.org

Moderator: Shaos

User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

fifan wrote:Неа, только гербер, я уже пытался им впихнуть не гербер от игла - не взяли.
Ну вот кстати игл многие китайцы берут :)

P.S. Хм, чото поглядел по китайцам что знаю - действительно только герберы стали брать :(
А вот американцы до сих пор берут и герберы, и иглы, и кикад:
Screenshot from 2023-10-06 20-31-22.png
P.P.S. У меня в дебияне стоит KiCAD 5.0.2 - могу научиться генерить герберы, если надо, но пока не въехал:
Screenshot from 2023-10-06 22-22-46.png
P.P.P.S. Вот на JLCPCB есть объяснялка как в пятом кикаде герберы делать: https://jlcpcb.com/help/article/10-How-to-generate-Gerber-and-Drill-files-in-KiCad-5
You do not have the required permissions to view the files attached to this post.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Кстати у бейджа есть интерфейс "картриджа" - у меня например сзади воткнут картридж-макетка со вторым последовательным EEPROM 16MB, который также как и бортовая EEPROM подключается по USB к компу как флеш-накопитель (я туда свои эльфы на погонять заливаю), а так там ног полно (30 штук) - можно поди и Z80 живой прицепить :dj:
Badge-cartridge-proto.jpg
Badge-cartridge-pcb.png
Badge-cartridge-sch.png
You do not have the required permissions to view the files attached to this post.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Shaos wrote:Кстати у бейджа есть интерфейс "картриджа" - у меня например сзади воткнут картридж-макетка со вторым последовательным EEPROM 16MB, который также как и бортовая EEPROM подключается по USB к компу как флеш-накопитель (я туда свои эльфы на погонять заливаю), а так там ног полно (30 штук) - можно поди и Z80 живой прицепить :dj:
Эти 30 сигналов GENIO в текущей версии прошивки программно управляются, но прошивку можно и "подковырять" ;)

Code: Select all

soc.v:		input [29:0] genio_in,
soc.v:		output reg [29:0] genio_out,
soc.v:		output reg [29:0] genio_oe,
...
soc.v:	parameter MISC_REG_GENIO_IN = 17;
soc.v:	parameter MISC_REG_GENIO_OUT = 18;
soc.v:	parameter MISC_REG_GENIO_OE = 19;
soc.v:	parameter MISC_REG_GENIO_W2S = 20;
soc.v:	parameter MISC_REG_GENIO_W2C = 21;
...
soc.v:			end else if (mem_addr[6:2]==MISC_REG_GENIO_IN) begin
soc.v:				mem_rdata = {2'h0, genio_in};
soc.v:			end else if (mem_addr[6:2]==MISC_REG_GENIO_OUT) begin
soc.v:				mem_rdata = {2'h0, genio_out};
soc.v:			end else if (mem_addr[6:2]==MISC_REG_GENIO_OE) begin
soc.v:				mem_rdata = {2'h0, genio_oe};
...
soc.v:				end else if (mem_addr[6:2]==MISC_REG_GENIO_OUT) begin
soc.v:					genio_out <= mem_wdata[29:0];
soc.v:				end else if (mem_addr[6:2]==MISC_REG_GENIO_OE) begin
soc.v:					genio_oe <= mem_wdata[29:0];
soc.v:				end else if (mem_addr[6:2]==MISC_REG_GENIO_W2S) begin
soc.v:					genio_out <= genio_out | mem_wdata[29:0];
soc.v:				end else if (mem_addr[6:2]==MISC_REG_GENIO_W2C) begin
soc.v:					genio_out <= genio_out & ~mem_wdata[29:0];
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Shaos wrote:
Shaos wrote: Я хочу сделать включаемую отдельно Спринтеровскую нарезку фреймбуфера квадратами 8х8 пикселов - чтобы это получилось, надо оценить скорость перенастройки DMA, которое сейчас делается один раз для каждой строки, а мне надо до 80 раз в пределах одной строки (чтобы поддержать не только линейные графические режимы Спринтера, но и текстовые). В худшем случае мне придётся сделать конвейер, при котором в тени будет готовиться новая строка из кусочков памяти, пока аппаратный рисовальщик будет рисовать текущую строку. Ну и кроме того я хочу прямо в железе сделать сплющивание 720-пиксельных 16-цветных режимов в 480 пикселов по алгоритму, который я описал чуть раньше (и уже реализовал программно). Спринтеровские описатели экранов и палитра (у бейджовского фреймбуфера она одна, но я знаю как поддержать 4 - надо просто сделать массив цветов палитр длиннее) будут находится внутри FPGA (что должно потребовать как раз порядка 40 килобайт).
На самом деле в текстовом режиме будет не 80 чтений в пределах одной строки, а 80 чтений по ДВА 32-битных слова (8 байт, чтобы вычитать букву из знакогенератора) в пределах горизонтального ряда квадратиков (8 строк), так что наверное надо будет конвеерно готовить цепочку квадратиков 8x8 разве что под это дело надо будет найти 480x8=3840 байт (причём дважды ибо конвеер). Однако для графических режимов всё-таки придётся вычитывать построчно, причём заранее подсчитав если видеопамять идёт линейно через несколько квадратов, то читать её надо за "один присест" одним DMA запросом. Усложняет задачу ещё и то, что теоретически текстовые и графические режимы могут перемешиваться и нужно уметь правильно настраивать DMA по ходу пьесы.

Другой сложный момент заключается в том, что например расположенная выше картинка (FN с запредельной рамкой-оконтовкой) на реальном Спринтере состоит из квадратиков разной цветности и разрешения - FN имеет высокое разрешение и 16-цветные пиксела, а рамка - низкое разрешение и 256-цветные пикселы (а в примере выше я просто привёл рамку к высокому разрешению и 16-цветам, чтобы не усложнять пример). Так как я предполагаю "сплющивать" высокое разрешение, а низкое оставлять "как есть", мне придётся отслеживать встречались ли в пределах кадра (по видимому прошлого) квадратики высокого разрешения и если был хотя бы один, то надо будет включать "сплюскивание" для квадратиков повышенной чёткости, а квадратики пониженной чёткости придётся "апскейлить", превращая каждые 3 пиксела в 4 (повторяя каждый третий пиксел 2 раза). Если же весь экран состоит из квадратиков пониженной чёткости (и повышенной цветности с 8-битными пикселами), то графика должна выводиться как есть (выдавая в пределе 448 пикселов в ширину - максимум того, что может себе позволить описатель экранов Спринтера, состоящий из 56 квадратиков по горизонтали).
Придумал алгоритм, который вот это всё будет учитывать на лету - вобщем у нас будет флаг global_hires, который устанавливается в 1 если в предыдущем кадре был хотя бы один квадратик высокой чёткости (16x8 16-цветных пикселов) - в начале следующего кадра устанавливаются начальные условия в зависимости от состояния этого флага:

Если global_hires=0, то мы имеем зацикленную в кольцо последовательность описателей 112 квадратиков начиная с номера 97, по которой мы будем двигаться с шагом 2 (это позволит иметь по горизонтали максимум 448 256-цветных пикселов - можно это назвать "суперзапредельным" режимом Спринтера, который невозможен на старом Спринтере), причём если по ходу рендеринга попадутся квадратики высокого разрешения, то они будут выведены неправильно в пределах этого кадра, однако после этого флаг global_hires будет установлен в 1, и следующий кадр будет показан правильно (в режиме высокой чёткости и со "сплюснутыми" пикселами).

Если global_hires=1, то мы стартуем с квадратика 107 и идём до квадратика 86 (после номера 111 будет идти номер 0), игнорируя квадратики с номерами от 87 до 106 (они будут за пределами видимого экрана) - в этом режиме надо пропустить первые 3 байта, т.е. из самого левого квадратика будут показаны только 5 256-цветных пикселов либо 10 16-цветных пикселов (в зависимости от битов режима в текущем квадратике и столько же мы потеряем с правого края), либо для простоты можно стартовать с самого левого пиксела, но тогда справа мы потеряем 16 16-цветных пикселов вместо 10 (т.к. при таком подходе можно показать только 720 "сплюснутых" пикселов из 736).

По ходу движения по квадратикам мы будем генерировать четвёрки 256-цветных пикселов (т.е. 1 байт на пиксел), которые можно назвать бинарно 00, 01, 10 и 11:
  • Чтобы получить пиксел 00 мы просто копируем текущий пиксел источника как есть (там будет либо 1 полноцветный пиксел либо 2 16-цветных);
  • Чтобы получить пиксел 01 мы смотрим на состояние флага global_hires и битов режима текущего квадратика:
    • если global_hires=0 или текущий квадратик 256-цветный, то копируем текущий пиксел источника как есть (там будет один 256-цветный пиксел);
    • если global_hires=1 и текущий квадратик 16-цветный, то в младший ниббл копируемого байта надо записать младший ниббл из предыдущего байта (тут может произойти путаница палитр, если они были разные у предыдущего и текущего байтов);
  • Чтобы получить пиксел 10 мы смотрим на состояние флага global_hires, битов режима текущего квадратика и режим предыдущего пиксела (мы могли попасть на границу квадратиков):
    • если global_hires=0 или текущий квадратик 256-цветный:
      • если предыдущий пиксел тоже был 256-цветным, то копируем текущий пиксел источника как есть (там будет один 256-цветный пиксел);
      • если предыдущий пиксел был 16-цветным, то копируем байт, составленный из младших нибблов предыдущего байта (с сохранением его палитры);
    • если global_hires=1 и текущий квадратик 16-цветный:
      • если предыдущий пиксел тоже был 16-цветным, то копируем байт, составленный из младшего ниббла предыдущего байта и старшего ниббла текущего байта (тут может произойти путаница палитр, если они были разные у предыдущего и текущего байтов);
      • если предыдущий пиксел был 256-цветным, то копируем байт, составленный из старших нибблов текущего байта;
    • если global_hires=1, то инкремент указателя источника в данном такте НЕ ПРОИЗВОДИТСЯ (т.е. мы в глобальном режиме высокой чёткости идём тройками байт источника, а при низкой чёткости - четвёрками)
  • Чтобы получить пиксел 11 мы смотрим на состояние флага global_hires и битов режима текущего квадратика:
    • если global_hires=0 или текущий квадратик 256-цветный, то копируем байт как есть;
    • если global_hires=1 и текущий квадратик 16-цветный, то в копируемом байте переставляем нибблы местами;
Также при копировании номера палитры (0...63) вместе с байтом графики в режиме global_hires=1 надо будет обнулять старший бит номера палитры если текущий квадратик является 16-цветным (таким образом мы будем превращать 16-цветную палитру в комбинированную 256-цветную, которая будет заполняться программно в палитрах с номерами N-32) либо пока оставить номер палитры нетронутым, но тогда надо быть готовым, что заполнив 16-цветную палитру программно, мы будем читать обратно не те RGB значения, которые были туда записаны.

P.S. Чтобы не было перепутывания палитр на границах "сплюснутых" квадратиков в многопалитровых 16-цветных картинках надо делать смену палитр с шагом 48 16-цветных пикселов, либо делать так, чтобы в пикселах на границах квадратиков использовлись цвета, которые имеют одинаковые RGB значения в разных палитрах, либо чередовать 16-цветные квадратики с 256-цветными - в этом случае границы будут без цветных помех.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Всё что написано выше имеет отношение только к графическим режимам (4 бита на пиксел либо 8 бит на пиксел), а для текстовых режимов (1 бит на пиксел - частным случаем текстового режима является режим ZX-Spectrum) надо делать по другому - там придётся забирать 8 байт знакогенератора нужного символа из внешней памяти и затем переиспользовать эти байты для формирования 8 графических строк в 4 разных палитрах (см. тут) - это относительно несложно для режима низкого разрешения (40 символов в строке), но будет вызывать трудности для режима высокого разрешения, при котором мы миксим соседние пикселы, чтобы влезть в 480 экранных пикселов. Возможно для такой прошивки надо вообще отказаться от подходов к текстовым режимам как в классическом Спринтере и либо остаться в рамках низкого разрешения текста 40x32 (60x36), либо сделать специальный режим высокого разрешения в котором не будет знакомест 8х8 (фактически чтобы попадать в сплюснутые квадратики ширина знакомест должна быть 5.333 пиксела или 3 знакоместа на каждые 16 пикселов).

Ну или самый прямой способ - забыть про 4 палитры по 256-цветов каждая, которые использовались в Спринтере для имитации досовских текстовых атрибутов (FRGBIRGB) и спринтеровских атрибутов (FIBRGBRG) - оба с мерцанием (можно сделать отключаемым) - и просто привести эту задачу к уже решёной - формировать аппаратно картинку байт на пиксел для режима низкого разрешения либо 2 байта на пиксел для режима высокого разрешения и далее работать по алгоритму, описанному выше. Комбинационная схема приводящая текст к нужному графическому виду может принимать на вход 8 битов строки знака, 8 битов атрибутов, 1 бит для индикации досовские это атрибуты или спектрумовские, 1 бит мерцания (можно предусмотреть ещё один бит, отключающий мерцание - в этом случае бит флеша будет задействован как яркость фона) и на выходе будет 8 четвёрок битов, которые будут обозначать 16-цветные пикселы - они годятся как есть для режима высокого разрешения, а для режима низкого разрешения к ним надо добавить по 4 нулевых бита на каждый пиксел. Каждые 4 бита цвета будут выбирать значения RGB из нужной 16-цветной палитры, т.е. палитра будет программно настраиваемая, хоть и одна (хотя можно воспользоваться скрытыми 4 битами на квадратик для выбора другой палитры - в этом случае можно иметь до 16 разных текстовых палитр в пределах экрана).
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Shaos wrote:
Shaos wrote:(лого по-быстрому нарисовано моей супругой-дизайнером в сентябре 2023 по мотивом логотипа петерсплюса)
Вот вставил пикселизированное лого в эмуль:

Image
А вот так текст выглядит на бейдже (с рамкой):
SpiritRetroHandheld-prototype-5.jpg
И на телеке по HDMI (upscaled):
SpiritRetroHandheld-prototype-5-HDMI.jpg
You do not have the required permissions to view the files attached to this post.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Shaos wrote:наверное по большому счёту полноэкранные режимы 800x300 и даже 800x600 по сути и не очень то требуются, а самым большим разрешением первое время может быть околоспектрумовополутекстовый Mode 0x01 с "бордюром":

Image
Вот как будет выглядеть "запредельноспектрумовский" режим 768x288 (в данном случае откушены средние 720 пикселов, который "сплюснуты" в экранные 480):
SpiritRetroHandheld-prototype-6.jpg
И на экране большого телека через HDMI с апскейлом:
SpiritRetroHandheld-prototype-6-HDMI.jpg
P.S. А вообще это моё хитрое "сплюскивание", когда уменьшается количество пикселов по горизонтали, но увеличивается цветность (16 -> 256 цветов), выглядит на маленьком экранчике очень даже неплохо - может быть когда у меня таки дойдут руки до материнской платы Spirit Retro с VGA-выходом, то в первой версии так и сделать - ограничиться полуторным пиксельклоком 26.667 МГц вместо 40.0 и 512 пикселами по горизонтали? Правда настоящий Спринтеровский текстовый режим с 4 палитрами по 256 цветов каждая там также не выйдет - для него надо иметь полноценные 768 полноцветных пикселов по горизонтали без сплющивания...

P.P.S. А если взять пиксельклок 28 МГц, то можно заодно поддержать спец-режимы MiniWhiz и более "родные" частоты для Z80 - 14 МГц, 7 МГц, 3.5 МГц :roll:
You do not have the required permissions to view the files attached to this post.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Для воможности вывода произвольных RGB изображений (например JPG или полноцветные PNG) важно иметь универсальные палитры, способные аппроксимировать цвета без квантования - таких палитр за последние десяток лет я наизобретал 3 штуки:
  • EGA2VGA.gpl - палитра в которой замешаны 16 егашных цветов (интерполяция 2 егашных пикселов в одну 256-цветную точку) - в ней лишь порядка 90 уникальных цветов;
  • GigasRGBx.gpl - палитра составленная из цветов ZX-гигаскрина с учётом гаммы плюс некоторый набор других промежуточных цветов, чтобы покрыть дырки в цветовом пространстве;
  • Uniform676G.gpl - равномерно распределённая палитра, выдуманная мною в мае 2013 года, в которой линейно замешаны 6 градаций красного, 7 градаций зелёного и 6 градаций синего, что даёт 252 цвета, плюс ещё 4 промежуточных градации серого (я их добавил сегодня).
Можно их попробовать на разных примерах без дизеринга (с выбором ближайшего цвета из палитры) и с дизеригом (по Флойду-Стейнбергу).

Вот оригинальная картинка:
ShaosBuick-384x288.jpg
Для сравнения берём только егашные 16 цветов:
ShaosBuick-EGA16.png
EGA2VGA:
ShaosBuick-EGA2VGA.png
GigasRGBx:
ShaosBuick-GigasRGBx.png
Uniform676G:
ShaosBuick-optimal.png
You do not have the required permissions to view the files attached to this post.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

Ещё одна картинка 384x288:
goldengate-384x288.jpg
16 цветов EGA:
goldengate-EGA16.png
EGA2VGA:
goldengate-EGA2VGA.png
GigasRGBx:
goldengate-GigasRGBx.png
Uniform676G:
goldengate-optimal.png
You do not have the required permissions to view the files attached to this post.
Я тут за главного - если что шлите мыло на me собака shaos точка net
User avatar
Shaos
Admin
Posts: 23763
Joined: 08 Jan 2003 23:22
Location: Silicon Valley

Re: Project Spirit

Post by Shaos »

И ещё одна картинка 384x288:
PastaGirl-384x288.jpg
16 цветов EGA:
PastaGirl-EGA16.png
EGA2VGA:
PastaGirl-EGA2VGA.png
GigasRGBx:
PastaGirl-GigasRGBx.png
Uniform676G:
PastaGirl-Optimal.png
Тут вроде как выходит, что Uniform676G лучше для Флойда-Стейнберга, а GigasRGBx лучше для приближённых цветов?

Кстати быстрый подбор цвета из палитры по входному значению RGB888 можно сделать внутри FPGA ;)

P.S. Хотя например индекс цвета из палитры Uniform676G можно программно получить по простой формуле без поиска: INDEX=INT((R+25.5)/51)+INT((G+21.25)/42.5)*6+INT((B+25.5)/51)*42 (целочисленный вариант формулы см. тут)

P.P.S. И такой быстрый способ выбора цвета из палитры можно задействовать в нашем будущем графическом редакторе nedopixels ;)

P.P.P.S. Палитру обозначенную выше как Uniform676G я выдумал в 2013 году и назвал её тогда "optimal", но сейчас вот думаю, что лучше назвать её словом UNIFORM (типа как равномерное распределение):
https://www.compuphase.com/unifpal.htm
В приведённой заметке подход с равномерным перемешиванием цветов называется "6x6x6 RGB color cube", которым также является так называемая "Web Safe Palette", которая состоит из 216 цветов:
https://www.rapidtables.com/web/color/Web_Safe.html
То что придумал я в 2013 году на самом деле является "6x7x6 RGB color cube" ( даже уже и не cube, а "прямоугольный параллелепипед" ; ) который состоит из 252 цветов, к которым я вчера добавил ещё 4 уровня серого, чтобы получить 6 градаций серого в дополнение к цветовому "кубу" 6x7x6. что даёт полные 256 цветов - сегодня вот решил официально переименовать эту палитру в Uniform676G.gpl (и поменял тексты сообщений выше):
You do not have the required permissions to view the files attached to this post.
Я тут за главного - если что шлите мыло на me собака shaos точка net