Как сделать вывод на LED дисплей за один семинар с нуля

9ca7a0653c41343f1da7954f2e3e5b18.png

Тут пришло приглашение на семинар по освоению программирования RA8M1. Предлагалось сделать четыре лабораторных работы и бесплатный обед с кофе-брейками. В заключении за труды получить очередную плату EK-RA8M1. От такого не отказываются. Хороший повод найти применение плате MKR RGB Shield и дополнить копилку демо-проектов под RA8M1, решил я.

В моем распоряжении было где-то четыре часа чистого времени. Время пошло.

На компьютере уже было установлено ПО для разработки под RA8. Его поставить попросили заранее. Это открытая среда разработки e2studio RA8 на базе Eclipse с плагинами от Renesas. Про неё писал тут. В состав этой среды входит Flexible Software Package (FSP) и его отдельно качать не надо, если скачан и инсталлирован файл setup_fsp_v5_1_0_e2s_v2023–10.exe

Плату MKR RGB Shield я тоже подготовил заранее. Понадобилось припаять от неё четыре провода к разъёму.

9c265577e7fcab713927da2dc95516e2.png

Самая сложная из лабораторных работ предполагала запуск АЦП по таймеру и перенос результатов измерений по DMA в определенную переменную в памяти с миганием светодиодом от того же таймера в режиме фиксированного ШИМ.

В среде начинающих embedder-ов использование DMA считается высшим пилотажем. И видимо организаторы посчитали, что демонстрация лёгкости с которой DMA может быть организован с помощью FSP вызовет у участников приступ энтузиазма. Может оно так и есть, поэтому в своей демке я оставил эту фичу, но речь не о ней.

Плата MKR RGB Shield по сути представляет собой графический LED дисплей с адресными RGB светодиодами типа APA102 с интерфейсом SPI.

d74f41b54ecc8c8592811fbd3ea30ad2.png

Когда речь идёт о графических дисплеях, то вспоминаются трудности подготовки растровых шрифтов, позиционирования, учёта отступов, алиасинга, анимации, реализации видеобуферов, конвертации цветовых представлений и т.д. и т.п. Я спланировал все это решить быстро и эффективно с помощью Azure RTOS GUIX. Этот движок мной был освоен в этой статье. Хорошая новость в том, что с этого года он полностью свободен и опенсорс.

GUIX хорош тем, что его можно присоединить к любому проекту и не придётся иметь дело с зависимостями, реализациями платформенно-зависимых функций и прочими артефактами.
Подключаем исходники, вставляем в свой проект хидеры «gx_api.h» и «gx_display.h» и всё скомпилируется без проблем. Да, ещё забыл что нужно будет иметь на борту само ядро Azure RTOS — ThreadX. Ну потом ещё собственно окно написать и драйвер вывода на дисплей реализовать и зарегистрировать в GUIX. Хоть дисплей и маленький, но в терминах GUI это все же окно, и GUIX на нем может организовать даже многооконный интерфейс.

Ситуацию упрощает то, что в среде e2studio RA8 есть опция создания нового проекта на базе ThreadX для платы EK-RA8M1.

c0f713dd71d38d79ffa83868ea63be4f.png

Т.е. ThreadX в своём проекте получаем автоматически. На это уходят считанные минуты.

Конфигурацию пинов также получаем уже готовую, поскольку выбрали генерацию проекта для конкретной платы EK-RA8M1.

Однако пины микроконтроллера выбранные мной для подключения дисплея в конфигурации уже были заняты какой-то другой периферией. Подозреваю, что Blinky был задуман не таким простым, как кажется из названия.

Пины на плате EK-RA8M1 используемые для подключения дисплея

Пины на плате EK-RA8M1 используемые для подключения дисплея

Ну уборку ненужных функций на пинах P609 и P611ушло ещё с десяток минут. Потом на эти пины были назначены сигналы с SCI0 в режиме 32-bit SPI.

Настало время сконфигурировать периферию для нашего проекта. Конфигурируем модули DAC, ECL, DMA, Timer, SCI и другие. Вид модулей в конфигураторе представлен ниже.

Описание назначения модулей

Описание назначения модулей

Конкретные настройки модулей видны в закладке Properties. Здесь уже надо хорошо разбираться в архитектуре RA8M1. Но потому материал этой статьи и обозначен как сложный. Меня спасло то, что архитектура RA8 полностью повторяет архитектуру Synergy с которой я работаю уже пару лет.

На конфигурацию периферии ушел приблизительно час. Ниже покажу как выглядит конфигурация модуля SCI работающего в режиме 32-bit SPI

cc6fe175dbcd2c866285cf4028112c2e.png

Модуль DTC применяемый для обмена по SPI аналогичен DMA. Просто в RA8 есть два механизма прямого доступа, но с разными названиями: DMAC и DTC. Тут мы получили работу с SPI по DMA практически не изучая и не углубляясь в специфику DMA.

Следующим шагом было подключить к проекту исходники GUIX. Это делается быстро.

Затем нужно в среде разработки интерфейсов GUIX под названием Azure RTOS GUIX Studio. Выглядит забавно, но окно очень маленькое:

8e9976bfa6800bfdfed7b48c8515a70a.png

Ну и дисплей наш маленький, если судить по количеству пикселей. Для такого дисплея нужны маленькие шрифты. Максимум 5 на 7 пикселей, можно и 4 на 5 пикселей. Рисовать самому шрифты в GUIX Studio не нужно. Конвертировать чужие растровые шрифты откуда-то тоже не нужно. Просто скачиваем пиксельный ttf шрифт с нужной пиксельностью и вставляем в GUI Studio без антиалиасинга.

365896615c3d739544e3e948a58942e8.png

Получаем отличный растровый шрифт малого размера с полным набором символов ASCII. Надо признаться на поиски шрифта время я не тратил. Он уже был у меня присмотрен.

Итак мы имеем окно в GUI, там размещенную текстовую строку,. Строке назначен нужный шрифт, цвет и позиция в окне. Нажимаем Generate All Output Files и получаем файлы ресурсов GUI нужные для прорисовки дисплея со строкой.

Теперь нужно инициализировать все драйвера. Это делается так:

static void HAL_start(void)
{

  err = R_ELC_Open(&g_elc_ctrl,&g_elc_cfg);
  err = R_ELC_Enable(&g_elc_ctrl);
  err = R_GPT_Open(&g_timer0_ctrl,&g_timer0_cfg);
  err = R_ADC_Open(&g_adc0_ctrl,&g_adc0_cfg);
  err = R_ADC_ScanCfg(&g_adc0_ctrl,&g_adc0_channel_cfg);
  err = R_DTC_Open(&g_transfer_ADC0_ctrl,&g_transfer_ADC0_cfg);
  err = R_DTC_Enable(&g_transfer_ADC0_ctrl);
  err = R_DTC_Reset(&g_transfer_ADC0_ctrl,(void *)&R_ADC0->ADTSDR,&g_temperature, 1);
  err = R_GPT_Start(&g_timer0_ctrl);
  err = R_ADC_ScanStart(&g_adc0_ctrl);
}

Вывод экранного буфера на дисплей элементарен:

void Write_to_screen(void)
{
  R_SCI_B_SPI_Write(&g_sci_spi0_ctrl,&dbuf, sizeof(dbuf), SPI_BIT_WIDTH_32_BITS);
}

Кодирование цвета в GUI принимаем как RGB16(5–6–5), а наш дисплей работает с цветом RGB29(8–8–8–5). Поэтом напишем еще простенький конвертер из кодировки видеобуфера в кодировку дисплея Ж

void Videobuf_to_screen(void)
{
  uint16_t pixel;
  uint8_t  r;
  uint8_t  g;
  uint8_t  b;
  uint32_t w;
  for (uint32_t row=0; row < ROWS; row++)
  {
    for (uint32_t col=0; col < COLS; col++)
    {
      pixel = videobuf[row][col];
      r  =(pixel >> 11) & 0x1F;
      g  =(pixel >> 5) & 0x3F;
      b  =(pixel >> 0) & 0x1F;
      w  = r << 24;
      w |= g << 16;
      w |= b << 8;
      w |= 0xE7;
      dbuf.data[row*COLS + col] = w;
    }
  }
}

Работа хоть и не сложна, но два часа заняла. Обмена с APA102 пришлось настраивать методом проб и ошибок. Информационный листок по протоколу обмена довольно неоднозначен.

Плата EK-RA8M1 удобна тем что сразу содержит интегрированный SWD отладчик J-Link.
Правда это урезанная версия отладчика без трассировки и без лицензии на программатор, но пошаговую символьную отладку выполняет хорошо. Поэтому скомпилированная программа сразу отправляется на исполнение в плату.

И вот результат:

fadde6ee2a2ee573e3f384255f8c21ec.gif

Дисплей настолько ярок, что легко просвечивает конструкционные материалы:

e9f9eba88e9690f05e0008dbe98b55f2.gif

Готово.

Проект можно скачать здесь

© Habrahabr.ru