デバッグが私たちの手に渡ったとき、私は新年が近づいていることに敬意を表して「深刻な」デモンストレーション作業の代わりに、面白くて創造的な何かをしたかったのです。 私たちは勇気を捨てて、古い突起を発見しました-ターミナルを通してMEGA168のテトリスは新しい石に移植し、それを一般に紹介することにしました。 これには実用的な意味はありません。これは「楽しみのために」と呼ばれています。 詳細に興味のある方は、猫の下でお願いします。
新しいマイクロコントローラーについて簡単に
- SAM D09はSAM Dファミリーの最年少のメンバーで、8Kまたは16Kフラッシュと4K SRAMを搭載しています。 ハウジングオプションQFN-24およびSOIC-14。 オンボードDMAおよびイベントシステム。 2 SERCOM-USART、SPI、またはI2Cとして構成できるユニバーサル通信モジュール。 5または10チャネルの12ビットADC。
- SAM D10は、タイマー、アナログコンパレータ、DAC、タッチボタンコントローラーの追加、およびいくつかの変更のためのSERCOMの追加という点で、D09のアップグレードです。 ハウジングオプションQFN-24、SOIC-14、SOIC-20。
- SAM D11は同じD10ですが、フルスピードUSBデバイスが追加されています。
デバッグボードの外観。 オンボードプログラマは、Micro USBコネクタを介して接続します。
テトリス自身について
テトリスの仕事は、いくつかの基本原則に基づいています。
- 端末との通信は、VT100プロトコルに従って実行されます。
- 画像はタイマーによって更新され、
- 任意の図は、特定のサイズ(4 x 4文字)の正方形に収まります。
Tetrisは、 VT100プロトコルからの3つのコマンドを使用します。画面をクリアし、カーソルを先頭に移動して、カーソルを非表示にします。
このプロトコルで作業するには、たとえば、Tera用語ターミナルを使用できます。
制御のために、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ポイントが加算されます。 最初のポイントと同時に「消失」した場合、前のポイントの2倍のポイントが追加されます。
megaからsamd10への移植
コントローラーの周辺から、図形や画像を直接転送するためにUARTモードのSERCOMと、画像が更新された時間をカウントするためのタイマーが必要です。
プログラマーの中心であるプログラマーの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); }
キャラクターを受信するための割り込みとコールバックを許可することを忘れずに、uartモードで動作するようにsercomを構成します。
UARTモードでのSercom構成
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); }
megaのソースコードでは、uartのデータはputcを使用して受信されました。samd10の場合は、より簡単になります。受信したすべてのバイトを特定の変数に割り込むだけです。 このソリューションは、正確で安全であると主張するものではなく、移行を容易にし、加速するためのものです。
割り込みによって1バイトを受信するために時々「スマート」な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ルーブルです。