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/wificamera_demo@haas100.bin
-
./platform/mcu/haas1000/release/write_flash_gui/ota_bin/littlefs.bin
5、小结
到此为止,俄罗斯方块玩起来了,如果觉得还不过瘾,一起来尝试移植其他的SDL游戏,找找童年的感觉,是不是很有意义呀,期待您的杰作。
如需更多技术支持,可加入钉钉开发者群,或者关注微信公众号
更多技术与解决方案介绍,请访问阿里云AIoT首页https://iot.aliyun.com/
转载:https://blog.csdn.net/HaaSTech/article/details/112050719