HaaS100除了在物聯網領域可以大顯身手外,還有哪些可能的玩法呢?今天就帶大家一起尋找童年的記憶,打造一臺復古街機。最終完工圖如下圖:
接下來我們分三個步驟來進行打造:
- LCD及遊戲手柄硬件接線
- 驅動開發
- 遊戲開發
1、接線配置
1.1、LCD模塊
我們採用了2.4寸彩色LCD屏幕,分辨率320*240,該屏幕使用SPI串口總線,因此使用較小的引腳數量就可以實現驅動。
具體的接線配置如下,大家可以參考LCD模塊上的絲印以及HaaS100開發板的引腳配置來完成接線。如果想要修改該引腳配置,請記得在代碼中也進行更改嗷。
更多HaaS100的硬件規格請參考 https://help.aliyun.com/document_detail/184186.html?spm=a2c4g.11186623.6.642.7fd815815Xe5iP
1.2、🎮模塊
遊戲拓展模塊採用的是Arduino的硬件生態,該遊戲模塊具備了一個搖桿以及4顆按鍵,足夠適配大量街機遊戲(街機經典配置)。由於該模塊沒有具體的絲印,所以請開發者們參考下圖的接線方式,使用標註的引腳進行連接。這麼有意思的一款模塊在以下地址購買:https://item.taobao.com/item.htm?spm=a1z09.2.0.0.3e082e8ddu5BB8&id=35422379433&_u=f1tg6s600889
2、驅動開發
2.1、 LCD模塊
LCD模塊與HaaS100的通訊方式爲SPI,因此這裏採用SPI0進行通訊。對於SPI0及相關GPIO的配置如下:
// 硬件SPI0 最高通訊速度26MHz
spi_ili9341.port = 0;
spi_ili9341.config.mode = SPI_WORK_MODE_3; // CPOL = 1; CPHA = 1
spi_ili9341.config.freq = 26000000;
spi_ili9341.config.role = SPI_ROLE_MASTER;
spi_ili9341.config.firstbit = SPI_FIRSTBIT_MSB;
spi_ili9341.config.t_mode = SPI_TRANSFER_NORMAL;
spi_ili9341.config.serial_len = 8;
spi_ili9341.config.data_size = SPI_DATA_SIZE_8BIT;
spi_ili9341.config.cs = SPI_CS_EN;
// Data/Cmd引腳 用於切換髮送指令或是數據
gpio_ili9341_dc.port = ILI9341_DC_PIN;
gpio_ili9341_dc.config = OUTPUT_PUSH_PULL;
gpio_ili9341_dc.priv = NULL;
// 復位引腳
gpio_ili9341_reset.port = ILI9341_RESET_PIN;
gpio_ili9341_reset.config = OUTPUT_PUSH_PULL;
gpio_ili9341_reset.priv = NULL;
我們在驅動文件中已經實現了多種繪圖函數,開發者可以直接使用這些繪圖函數來進行更多有意思的開發。
void (*lcd_frame_draw)(uint32_t *frame);
void (*lcd_area_draw)(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint32_t *frame, uint32_t areaSize);
void (*lcd_line_draw)(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t color);
void (*lcd_rect_draw)(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t borderWidth, uint32_t color);
void (*lcd_fill_rect_draw)(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint32_t color);
void (*lcd_circle_draw)(uint16_t x, uint16_t y, uint16_t r, uint16_t borderWidth, uint32_t color);
void (*lcd_fill_circle_draw)(uint16_t x, uint16_t y, uint16_t r, uint32_t color);
2.2、🎮模塊
該模塊包含 搖桿 及 按鍵 兩部分。
搖桿的結構是兩個相互垂直的彈性電位器。當用戶操作搖桿時,即引發電位器的阻值變動,進而改變觀測點輸出的電壓。因此只需要使用ADC採集觀測點的電壓值,便能夠得到搖桿的位置信息。
ADC的讀取方法如下,需要注意的是,在每次 hal_adc_value_get 之前, 都需要進行 hal_adc_init ,才能進行有效地數據讀取。
hal_adc_init(&roll_X);
hal_adc_init(&roll_Y);
hal_adc_value_get(&roll_X, &roll_X_value, 5);
hal_adc_value_get(&roll_Y, &roll_Y_value, 5);
按鍵採用中斷檢測的方式,對於每個按鍵設置上升沿觸發中斷,並在中斷函數中完成鍵值的變換。
int game_key_init()
{
int ret = 0;
int key_num = straight; // 在這裏填鍵值
key_Y.port = 33;
key_Y.config = IRQ_MODE;
ret |= hal_gpio_init(&key_Y);
// 上升沿觸發中斷函數 game_key_irq_fun, 同時傳入鍵值
ret |= hal_gpio_enable_irq(&key_Y, IRQ_TRIGGER_RISING_EDGE, game_key_irq_fun, key_num);
return ret;
}
void game_key_irq_fun(int key_num)
{
// do your things here
printf("key %d down\n", key_num);
}
3、遊戲開發
3.1、SDL多媒體庫移植
單獨寫一個遊戲很麻煩,怎麼樣可以玩更多的遊戲呢?這裏就給大家介紹一個多媒體庫SDL。Why use SDL?用官方的話來講——“因爲它是一個跨平臺的多媒體庫,提供了多種控制圖像、聲音、和輸入設備的函數,可以讓遊戲開發者專注於遊戲本身”。這裏爲了幫你找回童年記憶,AliOS Things已經將SDL移植進來。
SDL移植後的代碼在:
./components/utility/SDL。
將底層LCD驅動和遙杆驅動適配到SDL,驅動適配的邏輯參考:
./components/utility/SDL2/src/video/alios/SDL_AliOS_framebuffer.c
./components/utility/SDL2/src/video/alios/SDL_AliOS_video.c
AOS_APP_GAME_DEMO宏定義相關代碼。
3.2、俄羅斯方塊遊戲移植
基於SDL的開源遊戲在市面上已經非常多,在github上搜一搜一大把。當然我們先來一個經典俄羅斯方塊試試水https://github.com/andwn/sdl2-tetris。代碼已經移植好,你可以在AliOS Things的github倉庫中找到遊戲demo。
4、遊戲燒錄
遊戲中涉及到字體,在編譯代碼前先將字體文件拷貝到預編譯目錄:
$cp application/example/game_demo/sdl2-tetris/data/DejaVuSerif.ttf ./platform/mcu/haas1000/prebuild/data/
編譯game demo:
$aos make game_demo@haas100 -c config
$aos make
燒錄以下兩個文件:
參考燒錄方法鏈接
./out/wificamera_demo@haas100/binary/[email protected]
./platform/mcu/haas1000/release/write_flash_gui/ota_bin/littlefs.bin
5、小結
到此爲止,俄羅斯方塊玩起來了,如果覺得還不過癮,一起來嘗試移植其他的SDL遊戲,找找童年的感覺,是不是很有意義呀,期待您的傑作。
如需更多技術支持,可加入釘釘開發者羣
更多技術與解決方案介紹,請訪問阿里雲AIoT首頁https://iot.aliyun.com/