В этом году компания Atmel анонсировала линейку «младших» кортексов М0+ семейства SAM D09, SAM D10, SAM D11. Эти не сильно «навороченные» контроллеры имеют низкую цену и небольшие корпуса. Причем в линейке присутствуют камни в легкопаяемых корпусах SOIC-14 и SOIC-20. Для ознакомления с возможностями контроллера доступны очень дешевые отладки из серии Xplained mini, которые совместимы с шилдами от Arduino. Эти особенности, возможно, вызовут интерес не только среди профессиональных разработчиков, но и у радиолюбителей.
Когда отладки попали к нам в руки, захотелось вместо «серьёзной» демонстрационной задачи в честь приближающегося Нового года сделать что-нибудь забавное и креативное. Мы поскребли по сусекам и нашли старенький проектик — тетрис на MEGA168 через терминалку и решили портировать его на новый камень и представить общественности. Практического смысла в этом никакого, что называется Just for fun. Кому интересны подробности, прошу под кат.


Внешний вид отладочной платы. Программатор на борту, подключение через разъем Micro USB.
Работа тетриса основана на нескольких базовых принципах:
Тетрис использует три команды из протокола VT100: очистка экрана, перемещение курсора в начало и сделать курсор невидимым.
Для работы по этому протоколу можно использовать терминалку Tera term, например.
Для управления используются 5 клавиш-букв клавиатуры:
Скорость игры устанавливается таймером. Для более опытных игроков можно задать «тиканье» быстрее, тогда и фигуры будут падать быстрее.
Конечно же, подсчитываются очки: за каждую исчезнувшую строку добавляется 100 очков. За каждую следующую «исчезнувшую» одновременно с первой, добавляется в два раза больше очков, чем за предыдущую.
Из периферии контролера нам нужен SERCOM в режиме UART для непосредственной передачи фигурок и картинки, и таймер для отсчета времени обновления картинки.
Вместо милой сердцу любого программиста 8-битных контроллеров настройки UART битами в регистрах:
конфигурируем sercom для работы в режиме uart, не забывая разрешить прерывания и callback по приему символа.
В исходном коде для меги данные по uart принимались с помощью putc, для samd10 сделаем проще: пусть просто по прерыванию каждый полученный байт сваливается в определенную переменную. Это решение не претендует на правильность и безопасность, оно для простоты перехода и ускорения его.
Подробно про то, как победить порой слишком «умную» ASF для приема одного байта по прерываниям, мы писали в нашей статье на сайте we.easyelectronics.ru.
Перейдем к таймерам.
Код для меги:
И соответствующий код для samd10
Вот и все. Весь остальной код для обработки движения фигур и всей остальной логики остается таким же.
Полностью проект для samd 10 лежит на github.
Стоимость отладочной платы ATSAMD10-XMINI составляет 450 рублей.
Когда отладки попали к нам в руки, захотелось вместо «серьёзной» демонстрационной задачи в честь приближающегося Нового года сделать что-нибудь забавное и креативное. Мы поскребли по сусекам и нашли старенький проектик — тетрис на MEGA168 через терминалку и решили портировать его на новый камень и представить общественности. Практического смысла в этом никакого, что называется Just for fun. Кому интересны подробности, прошу под кат.

Кратко о новых микроконтроллерах
- SAM D09 — младший представитель семейства SAM D. Имеет 8К или 16К флеша и 4К SRAM. Варианты корпусов QFN-24 и SOIC-14. На борту DMA и Event system. 2 SERCOM — универсальных коммуникационных модулей, которые могут конфигурироваться как USART, SPI или I2C. 5-ти или 10-ти канальный 12-ти битный АЦП.
- SAM D10 — апгрейд D09 в части добавления дополнительных таймеров, аналогового компаратора, ЦАП и контроллера сенсорных кнопок, а так же дополнительного SERCOM для некоторых модификаций. Варианты корпусов QFN-24, SOIC-14, SOIC-20.
- SAM D11 — тот же D10, но с добавлением Full-Speed USB Device.

Внешний вид отладочной платы. Программатор на борту, подключение через разъем Micro USB.
Теперь про сам тетрис
Работа тетриса основана на нескольких базовых принципах:
- общение с терминалкой осуществляется по протоколу VT100,
- обновление картинки происходит по таймеру,
- любая фигура вписывается в квадрат определенных размеров (4 на 4 символа).
Тетрис использует три команды из протокола VT100: очистка экрана, перемещение курсора в начало и сделать курсор невидимым.
Для работы по этому протоколу можно использовать терминалку Tera term, например.
Для управления используются 5 клавиш-букв клавиатуры:
- n – начать новую игру,
- w или space – повернуть фигуру,
- s – уронить фигуру,
- d – переместить вправо,
- a – переместить влево.
В коде можно легко переназначить клавиши управления на другие
switch (c)
{
case 'w':
case ' ':
//ROTATE
tetris_rotate();
break;
case 's':
//DOWN
tetris_gravity();
break;
case 'd':
//RIGHT
tetris_move_right();
break;
case 'a':
//LEFT
tetris_move_left();
break;
default: break;
}
if (c == 'n')
{
c=0;
//Seed random function so we do not get same start condition
//for each new game. In essence we will not start a new game
//exactly at the same time.
srand(tick);
//New Game
is_running = true;
terminal_cursor_off();
terminal_clear();
tetris_init();
tetris_new_block();
terminal_cursor_home();
tetris_print();
}
Скорость игры устанавливается таймером. Для более опытных игроков можно задать «тиканье» быстрее, тогда и фигуры будут падать быстрее.
Конечно же, подсчитываются очки: за каждую исчезнувшую строку добавляется 100 очков. За каждую следующую «исчезнувшую» одновременно с первой, добавляется в два раза больше очков, чем за предыдущую.
Портируем с mega на samd10
Из периферии контролера нам нужен SERCOM в режиме UART для непосредственной передачи фигурок и картинки, и таймер для отсчета времени обновления картинки.
Вместо милой сердцу любого программиста 8-битных контроллеров настройки UART битами в регистрах:
static void board_init(void)
{
/*Configure IO pins:
* - UART pins
* - SW pin
* - LED pin
*/
DDRD &= ~USART_RX_PIN_bm;
DDRD |= USART_TX_PIN_bm;
PORTD |= USART_TX_PIN_bm;
PORTB |= SW_PIN_bm;
DDRB &= ~SW_PIN_bm;
/*Disable all modules we will not use*/
PRR = (1 << PRTWI) | (1 << PRTIM2) | (1 << PRTIM0) | (1 << PRSPI) | (1 << PRADC);
}
конфигурируем sercom для работы в режиме uart, не забывая разрешить прерывания и callback по приему символа.
Конфигурация Sercom в режиме uart
static void configure_console(void)
{
struct usart_config usart_conf;
usart_get_config_defaults(&usart_conf);
usart_conf.mux_setting = CONF_STDIO_MUX_SETTING;
usart_conf.pinmux_pad0 = CONF_STDIO_PINMUX_PAD0;
usart_conf.pinmux_pad1 = CONF_STDIO_PINMUX_PAD1;
usart_conf.pinmux_pad2 = CONF_STDIO_PINMUX_PAD2;
usart_conf.pinmux_pad3 = CONF_STDIO_PINMUX_PAD3;
usart_conf.baudrate = CONF_STDIO_BAUDRATE;
stdio_serial_init(&cdc_uart_module, CONF_STDIO_USART_MODULE, &usart_conf);
}
enum status_code usart_enable_rx_interrupt( struct usart_module *const module, uint8_t *rx_data)
{
// Sanity check arguments
Assert(module);
Assert(rx_data);
// Issue internal asynchronous read
// Get a pointer to the hardware module instance
SercomUsart *const usart_hw = &(module->hw->USART);
module->rx_buffer_ptr = rx_data;
// Enable the RX Complete Interrupt
usart_hw->INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
return STATUS_OK;
}
void configure_usart_callbacks(void)
{
usart_register_callback(&cdc_uart_module, USART_RX_callback, USART_CALLBACK_BUFFER_RECEIVED);
usart_enable_callback(&cdc_uart_module, USART_CALLBACK_BUFFER_RECEIVED);
}
В исходном коде для меги данные по uart принимались с помощью putc, для samd10 сделаем проще: пусть просто по прерыванию каждый полученный байт сваливается в определенную переменную. Это решение не претендует на правильность и безопасность, оно для простоты перехода и ускорения его.
Подробно про то, как победить порой слишком «умную» ASF для приема одного байта по прерываниям, мы писали в нашей статье на сайте we.easyelectronics.ru.
Перейдем к таймерам.
Код для меги:
void init_timer(void)
{
/*Start timer used to iterate game and seed random function*/
TIFR1 = 1 << OCF1A;
TIMSK1 = 1 << OCIE1A;
OCR1A = TIMER_TOP_VALUE;
TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);
}
ISR(TIMER1_COMPA_vect, ISR_BLOCK)
{
++tick;
iterate_game = true;
}
И соответствующий код для samd10
/** Configures TC function with the driver.
*/
static void configure_tc(void)
{
struct tc_config config_tc;
tc_get_config_defaults(&config_tc);
config_tc.counter_size = TC_COUNTER_SIZE_16BIT;
config_tc.wave_generation = TC_WAVE_GENERATION_MATCH_FREQ;
config_tc.counter_16_bit.compare_capture_channel[0] = 2000;
config_tc.clock_prescaler=TC_CLOCK_PRESCALER_DIV1024;
tc_init(&tc_instance, CONF_TC_INSTANCE, &config_tc);
tc_enable(&tc_instance);
}
/** Registers TC callback function with the driver.
*/
static void configure_tc_callbacks(void)
{
tc_register_callback(&tc_instance, tc_callback_to_counter, TC_CALLBACK_CC_CHANNEL0);
tc_enable_callback(&tc_instance, TC_CALLBACK_CC_CHANNEL0);
}
static void tc_callback_to_counter( struct tc_module *const module_inst)
{
++tick;
iterate_game = true;
}
Вот и все. Весь остальной код для обработки движения фигур и всей остальной логики остается таким же.
Полностью проект для samd 10 лежит на github.
Настройки для Tera Term:





Стоимость отладочной платы ATSAMD10-XMINI составляет 450 рублей.