一、动机
自从2002年拥有第一台GBA开始到2006年买的NDS,除了在两上掌机上开发程序之外,一直希望能扩展硬件做一个小车机器人。但由于当时软硬件知识的匮乏以及动手能力有限,一直没有进展。
最近无意搜到一款几年前发布的开源硬件DS brut,这是我目前了解的第二个开源NDS扩展硬件。第一个是DSerial。当时差不多2009年左右非常想买一块DSerial,可惜人在国内不方便国际邮购。如今这两个产品都已售罄,而自己感觉DIY的能力应该可以自己做一个以DS brut为基础的扩展,于是有了本篇博文。
二、背景
NDS硬件扩展主要有两种方式:(1) slot 1接口扩展 (2) slot 2接口扩展。前者为NDS卡接口,后者为GBA卡接口。slot 1接口只有17根线,而GBA接口则有32根线。两种方式扩展都有人做。
2.1、Slot 1接口扩展
Slot 1接口扩展主要有DS brut和DSerial。
通过查看DS brut和DSerial的电路图,可以了解到以下几个主要信息:
(1)DS brut用的atmega168 8位单片机,
(2)DSerial用的是51系列8位单片机,
(3)两者都使用NDS的slot 1接口(NDS游戏卡接口),
(4)两者都使用SPI接口实现单片机和NDS主机的通信,
(5)两者都没有使用slot 1接口中的D0至D5数据线作为数据交换(D6,D7为SPI总线上的数据线,即MISO, MOSI),
(6)两者均使用slot 1接口的3.3V的VCC作为单片机电源,无需额外供电,
(7)两者均使用CPU内部晶振作为时钟来源,即都没使用外部晶振。
2.2、Slot 2接口扩展
在youtube上还有一个人将NDS通过slot 2接口以最简单的方式接上了Arduino,并实现通信,文章请点击这里。该方案只使用3根信号线完成通信,方案比较简单,但功能扩展也相对有限。
另一个扩展方案请点这里。该方案相对复杂,从标题来看,应该是从slot 2接口引出线后通过FTDI,即TTL串口转USB联接电脑进行通信。其实方案中只要用了TTL串口,和单片机或嵌入式板子通信就无障碍了,除了通信速率问题外。
三、方案设计
以上这些信息已基本给出NDS硬件扩展的大致方案。从容易性和扩展功能是否强大来看,Slot 2的三线扩展最容易,但功能最弱。DSerial的功能相对强大,但除了购买现成板子外,自己动手制做难度太大,而且51系列CPU开发难度相对Arduino更高。
3.1、基于DS brut的扩展
DS brut由于CPU采用Atmega168,并且提供了兼容Arduino的bootloader(从Lilypad版改良),因此单片机侧的软件开发将会非常容易,IDE和库以及文档也非常全面。再加上Atmega AVR系列单片机的最小系统非常简单,几乎只需要通电就行。因此,本方案将基于DS brut进行扩展,但不限制NDS卡带的宽度,可以将单片机外接,因此可以比DS brut有更多的GPIO和其它接口。
以下是DS brut的扩展电路:
从图1中看以清楚看到除了220欧的R1电阻,发光二极管LED1,以及电源滤波的C1(100nf),没有别的电子元件。而其中R1和LED1对扩展来说不是必须,也可以去掉。因此,电路非常简单,外行都可以DIY实现。
原始的DS brut为NDS卡大小,如图2所示:
3.2、扩展卡制做
考虑到单独开板的成本,硬件打算简易DIY。采用现成的NDS卡,但只使用引脚部分,将引脚和上部电路(卡套盖住部分)用美工刀切断电路连接,然后分别从每个引脚焊接引线,并从卡的上部引出。如果引线后卡套盖不住,可考虑将原卡电路板上的芯片去掉(用电烙铁和吸锡器)。
3.3、Arduino部分制做
由于为了电路简单,Arduino部分电源将直接引线到NDS Slot 1的3.3V VCC。CPU理论上可以采用Atmega 48/88/168/328 系列。DS brut采用了Atmega168。采用不同的CPU在后续烧写Arduino前需要改一下Arduino IDE对应的board.txt文件,这主要是因为设置不同的CPU的Operating电压(CPU的实际运行电压)需要设置CPU内不同的fuse bit。要实现fuse bit的设置有两个方法:(1)如果使用Arduino IDE进行bootloader和程序的烧写,需要改写Arduino安装路径下的board.txt文件,添加相应的profile。(2)如果使用avrdude进行命令行烧写bootloadert和程序的烧写则可在命令行添加fuse bit的参数。但不管采用这两种方法的哪一种,fuse bit的设置参数都应是一致的。而具体设置可以参考Atmega48/88/168/328 的DataSheet文档查到。
而传统大部分Arduino开发板采用的是5V电源,本质上Atmega的大部分AVR单片机可支持1.8V至5.5V输入(具体请参考官网,点这里)。不过输入电压和CPU的工作频率是有一定相关性的,有一篇文章关于这个问题有较详细的说明(请点这里)。Any way, 只要我们的Atmega单片机能够用3.3V驱动就可以了。
这里有一篇文章清楚介绍了如何设置Atmega328的fuse bits以运行电压在3.3V上工作,给出了具体实现过程:ATmega328 Fuse Bit Setting for 3.3V Vcc。
电压问题解决后,接下来就是Arduino的bootloader。DS brut定制了一个bootloader。跟据其readme文件说明,应该相对于Arduino的bootloader只是更改了一下WatchDog部分代码而以。另外DS brut是采用CPU内部晶振作为振荡源,和Lilypad一样。因此怀疑bootloader也是按Lilypad的版本改的,这部分我未验证。
关于Arduino环境中boards.txt文件(路径为:arduino版本号/hardware/arduino/boards.txt)的各个部分的解释可以参考这个官方文档:Bootloader Development。
avrdude不像Arduino先烧bootloader,然后通过bootloader用串口烧写应用程序。avrdude是个全功能的AVR烧写软件,可以烧写所有程序,包括bootloader,不过需要一个烧写硬件,如STK500或Smart ISP programmer。两种方式各有优缺点,具体可以跟据自己手上的现成硬件进行选择。avrdude的使用可以参考这篇官方教程:AVR Tutorial。
烧写bootloader的方式,DS brut给出的是采用avrdude。而本方案将采用更方便的Arduino对烧,即需要另一个Arduino成品烧写无bootloader的Atmega单片机CPU。这篇From Arduino to a Microcontroller on a Breadboard 给出了具体方案,同时这篇文章也给出了如何用另一个Arduino上传编译好的程序到独立的CPU的方法。当然如果你有ISP烧写工具,也可以直接烧写,可参考这篇文章:Minimal Arduino with ATmega8,两篇文章都给出了修改Arduino IDE的boards.txt文件的相关信息。用Arduino给CPU烧写bootloader和上传程序的接线图请见图3和图4。
3.4、Arduino和NDS通信设计
Arduino和NDS通信通过SPI接口完成。Arduino部分对SPI编程实现非常方便,IDE内部的有库直接支持,直接使用即可。示例代码可以参考DS brut的dsbrut_arduino.txt文件。
NDS部分则相对复杂一些,需要写驱动代码。当然DS brut也已经提供了,分别为uart, spi, brut部分。也可以参考源码。NDS部分的编译好的程序需要放到Slot 2接口的烧录卡上运行,因为Slot 1已用来扩展。NDS部分的程序开发可采用DevkitPro。libnds等库也都非常实用,可以快速开发实现功能。另外,如果NDS程序涉及到FAT文件读写别忘了打DLDI补丁就行。
NDS端的驱动部分代码可以预先编译成库,并将头文件和库文件分别放到devkitARM对应的目录里,方便以后使用。
另外DS brut提供了Demo Project。这个section的详细内容需要到实现方案后再能详述。至此先这样。
四、应用
采用本方案实现NDS扩展,对于扩展出来的单片机端更新程序也方便,对于NDS端的开发和以往一样。应用实例基本上所有单片机能做的这个方案都可以实现。另外还有以下几个主要优点:
(1)NDS的主CPU为32位68MHz的ARM 9,处理能力比单片机更强,可以处理一些由单片机传回来的较为复杂的数据和运算,
(2)NDS端的程序在Slot 2,可以使用大容量的SD卡作为数据存储,
(3)NDS拥有WiFi,可以联网,有更多开发的可能性,比如远程控制,无线数据传输,
(4)NDS拥有两个LCD,可以显示很多信息,其中一个可触摸,
可以实现以下几个应用:
(1)把NDS当作电脑的游戏手柄,或电脑键盘
(2)带LCD状态显示的智能小车,可无线遥控
(3)通过NDS控制各种外设,如用触摸屏控制4*4*4,或8*8*8的LED立方显示任意图案
(4)太多了...
有空我将实现本方案,敬请期待!