📜 ⬆️ ⬇️

Tetris on a microcontroller in Tera Term

This year, Atmel announced a line of "younger" M0 + cortexes of the SAM D09, SAM D10, SAM D11 families. These not very "tricked out" controllers have a low price and small enclosures. And in the lineup there are stones in the easily soldered SOIC-14 and SOIC-20 packages. Very cheap debugs from the Xplained mini series, which are compatible with Arduino shields, are available to familiarize yourself with the capabilities of the controller. These features may cause interest not only among professional developers, but also among radio amateurs.

When the debugs fell into our hands, I wanted to do something fun and creative instead of a “serious” demonstration task in honor of the approaching New Year. We scratched the bottom of the barrel and found an old design project - Tetris on MEGA168 through the terminalka and decided to port it to a new stone and present it to the public. There is no practical sense in this that is called Just for fun. Who are interested in the details, please under the cat.



Briefly about new microcontrollers




Appearance of the debug board. Programmer on board, connect via Micro USB connector.
')

Now about Tetris itself


Tetris work is based on several basic principles:

Tetris uses three commands from the VT100 protocol: clear the screen, move the cursor to the beginning, and make the cursor invisible.
To work under this protocol, you can use Terrakke Tera term, for example.
To control, 5 keyboard letters are used:

In the code, you can easily reassign control keys to other
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(); } 



The game speed is set by the timer. For more experienced players, you can set “ticking” faster, then the figures will fall faster.

Of course, points are calculated: for each disappeared line, 100 points are added. For each following "disappeared" simultaneously with the first one, two times more points are added than for the previous one.

Porting from mega to samd10


From the periphery of the controller, we need SERCOM in UART mode for the direct transfer of figures and pictures, and a timer for counting the time for updating the picture.

Instead of the 8-bit controllers of the UART setting, dear to the heart of any programmer, bits in registers
 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); } 

configure sercom to work in uart mode, not forgetting to enable interrupts and callback on receiving a character.
Sercom uart configuration
 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); } 



In the source code for mega, the data on uart were received using putc, for samd10 we will make it easier: let each intervening byte be dropped into a specific variable just by interruption. This decision does not pretend to accuracy and security, it is for ease of transition and speeding it up.
Details about how to win sometimes too “smart” ASF for receiving one byte on interrupts, we wrote in our article on the site we.easyelectronics.ru.

Let's go to the timers.
Code for mega:
 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; } 


And the corresponding code for 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; } 


That's all. The rest of the code for processing the movement of the figures and the rest of the logic remains the same.
Completely the project for samd 10 lies on github .

Settings for Tera Term:






The cost of the debug board ATSAMD10-XMINI is 450 rubles.

Source: https://habr.com/ru/post/275401/


All Articles