source: rtems/c/src/lib/libbsp/arm/nds/libnds/source/arm9/ndsmotion.c @ 9a85541

4.104.114.95
Last change on this file since 9a85541 was 9a85541, checked in by Joel Sherrill <joel.sherrill@…>, on 08/20/08 at 16:31:41

2008-08-20 Joel Sherrill <joel.sherrill@…>

  • block/block.c, console/console.c, dswifi/arm9/source/sgIP.h, dswifi/arm9/source/sgIP_ARP.h, dswifi/arm9/source/sgIP_Config.h, dswifi/arm9/source/sgIP_DHCP.h, dswifi/arm9/source/sgIP_DNS.h, dswifi/arm9/source/sgIP_Hub.h, dswifi/arm9/source/sgIP_ICMP.h, dswifi/arm9/source/sgIP_IP.h, dswifi/arm9/source/sgIP_TCP.h, dswifi/arm9/source/sgIP_UDP.h, dswifi/arm9/source/sgIP_memblock.h, dswifi/arm9/source/wifi_arm9.c, dswifi/arm9/source/wifi_arm9.h, dswifi/include/dswifi7.h, dswifi/include/dswifi9.h, fb/fb.c, include/my_ipc.h, libfat/source/disc_io/disc_io.h, libfat/source/disc_io/io_nmmc.c, libnds/include/nds/arm9/exceptions.h, libnds/include/nds/arm9/input.h, libnds/include/nds/arm9/ndsmotion.h, libnds/include/nds/arm9/videoGL.h, libnds/source/arm9/console.c, libnds/source/arm9/gurumeditation.c, libnds/source/arm9/ndsmotion.c, libnds/source/common/card.c, libnds/source/common/interrupts.c, sound/sound.c, startup/start.c, touchscreen/reco.h, wifi/compat.c, wifi/compat.h: Fix most warnings.
  • Property mode set to 100644
File size: 14.6 KB
Line 
1/*---------------------------------------------------------------------------------
2        $Id$
3
4        DS Motion Card/DS Motion Pak functionality
5       
6        Copyright (C) 2007
7                Michael Noland (joat)
8                Jason Rogers (dovoto)
9                Dave Murphy (WinterMute)
10                Keith Epstein (KeithE)
11
12        This software is provided 'as-is', without any express or implied
13        warranty.  In no event will the authors be held liable for any
14        damages arising from the use of this software.
15
16        Permission is granted to anyone to use this software for any
17        purpose, including commercial applications, and to alter it and
18        redistribute it freely, subject to the following restrictions:
19
20        1.      The origin of this software must not be misrepresented; you
21                must not claim that you wrote the original software. If you use
22                this software in a product, an acknowledgment in the product
23                documentation would be appreciated but is not required.
24        2.      Altered source versions must be plainly marked as such, and
25                must not be misrepresented as being the original software.
26        3.      This notice may not be removed or altered from any source
27                distribution.
28
29---------------------------------------------------------------------------------*/
30
31#include <nds/card.h>
32#include <nds/system.h>
33#include <nds/memory.h>
34#include <nds/bios.h>
35#include <nds/arm9/ndsmotion.h>
36
37#define WAIT_CYCLES 185
38
39#define CARD_WaitBusy()   while (CARD_CR1 & /*BUSY*/0x80);
40
41// enables SPI bus at 4.19 MHz
42#define SPI_On() CARD_CR1 = /*E*/0x8000 | /*SEL*/0x2000 | /*MODE*/0x40 | 0;
43
44// disables SPI bus
45#define SPI_Off() CARD_CR1 = 0;
46
47// Volatile GBA bus SRAM for reading from DS Motion Pak
48#define V_SRAM ((volatile unsigned char*)0x0A000000)
49
50
51int card_type = -1;
52
53//these are the default calibration values for sensitivity and offset
54MotionCalibration calibration = {2048, 2048, 2048, 1680, 819, 819, 819, 825};
55
56// sends and receives 1 byte on the SPI bus
57unsigned char motion_spi(unsigned char in_byte){
58
59        unsigned char out_byte;
60        CARD_EEPDATA = in_byte; // send the output byte to the SPI bus
61        CARD_WaitBusy(); // wait for transmission to complete
62        out_byte=CARD_EEPDATA; // read the input byte from the SPI bus
63        return out_byte;
64}
65
66
67void motion_MK6_sensor_mode(void) {
68        // send some commands on the SPI bus
69        SPI_On()
70        motion_spi(0xFE);
71        SPI_Off()
72        SPI_On()
73        motion_spi(0xFD);
74        SPI_Off()
75        SPI_On()
76        motion_spi(0xFB);
77        SPI_Off()
78        SPI_On()
79        motion_spi(0xF8);
80        SPI_Off()
81}
82
83void motion_MK6_EEPROM_mode(void) {
84        // send some commands on the SPI bus
85        SPI_On()
86        motion_spi(0xFE);
87        SPI_Off()
88        SPI_On()
89        motion_spi(0xFD);
90        SPI_Off()
91        SPI_On()
92        motion_spi(0xFB);
93        SPI_Off()
94        SPI_On()
95        motion_spi(0xF9);
96        SPI_Off()
97}
98
99// checks whether a DS Motion Pak is plugged in
100int motion_pak_is_inserted(void){
101    int motion_pak = 0;
102        unsigned char return_byte = V_SRAM[10]; // read first byte of DS Motion Pak check
103        swiDelay(WAIT_CYCLES);
104        return_byte = V_SRAM[0];
105        swiDelay(WAIT_CYCLES);
106        if (return_byte==0xF0) { // DS Motion Pak returns 0xF0
107                return_byte = V_SRAM[0]; // read second byte of DS Motion Pak check
108                swiDelay(WAIT_CYCLES);
109                if(return_byte==0x0F) { // DS Motion Pak returns 0x0F
110                        motion_pak = 1;
111                }
112        }
113    return motion_pak;
114}
115
116// checks whether a DS Motion Card is plugged in
117// this only works after motion_init()
118// it will return false if it is run before motion_init()
119int motion_card_is_inserted(void){
120        // send 0x03 to read from DS Motion Card control register
121        SPI_On()
122        motion_spi(0x03); // command to read from control register
123        // if the control register is 0x04 then the enable was successful
124        if( motion_spi(0x00) == 0x04)
125        {
126                SPI_Off()
127                return 1;
128        }
129        SPI_Off();
130        return 0;
131}
132
133// turn on the DS Motion Sensor (DS Motion Pak or DS Motion Card)
134// Requires knowing which type is present (can be found by using motion_init)
135int motion_enable(int card_type) {
136        switch (card_type)
137        {
138                case 1: // DS Motion Pak - automatically enabled on powerup
139                        // check to see whether Motion Pak is alive
140                        return motion_pak_is_inserted();
141                        break;
142                case 2: // DS Motion Card
143                        // send 0x04, 0x04 to enable
144                        SPI_On()
145                        motion_spi(0x04); // command to write to control register
146                        motion_spi(0x04); // enable
147                        SPI_Off()
148                        // check to see whether Motion Card is alive
149                        return motion_card_is_inserted();
150                        break;
151                case 3: // MK6 - same command as DS Motion Card
152                        // send 0x04, 0x04 to enable
153                        SPI_On()
154                        motion_spi(0x04); // command to write to control register
155                        motion_spi(0x04); // enable
156                        SPI_Off()
157                        // check to see whether Motion Card is alive
158                        return motion_card_is_inserted();
159                        break;
160                default: // if input parameter is not recognized, return 0
161                        return 0;
162                        break;
163        }
164}
165
166// Initialize the DS Motion Sensor
167// Determines which DS Motion Sensor is present
168// Turns it on
169// Does not require knowing which type is present
170int motion_init(void) {
171        sysSetBusOwners(true, true);
172        // first, check for the DS Motion Pak - type 1
173        if( motion_pak_is_inserted() == 1 )
174    {
175        card_type = 1;
176        return 1;
177        }// next, check for DS Motion Card - type 2
178        if( motion_enable(2) == 1 )
179    {
180         card_type = 2;
181         return 2;
182        }
183   
184    motion_MK6_sensor_mode(); // send command to switch MK6 to sensor mode
185       
186    if( motion_enable(3) == 1 )
187    {
188        card_type = 3;
189        return 3;
190        }// if neither cases are true, then return 0 to indicate no DS Motion Sensor
191        return 0;
192}
193
194// Deinitialize the DS Motion Sensor
195// In the case of a DS Motion Pak, do nothing - there is nothing to de-init
196// In the case of a DS Motion Card, turns off the accelerometer
197// In the case of an MK6, turns off accelerometer and switches out of sensor mode into EEPROM mode
198void motion_deinit(void) {
199        // DS Motion Card - turn off accelerometer
200        SPI_On()
201        motion_spi(0x04); // command to write to control register
202        motion_spi(0x00); // turn it off
203        SPI_Off()
204        // MK6 - switch to EEPROM mode
205        motion_MK6_EEPROM_mode(); // switch MK6 to EEPROM mode
206}
207
208// read the X acceleration
209signed int motion_read_x(void) {
210        unsigned char High_byte = 0;
211        unsigned char Low_byte = 0;
212        signed int output = 0;
213        switch(card_type)
214        {
215                case 1: // DS Motion Pak
216                        High_byte = V_SRAM[2]; // Command to load X High onto bus
217                        swiDelay(WAIT_CYCLES); // wait for data ready
218                        High_byte = V_SRAM[0]; // get the high byte
219                        swiDelay(WAIT_CYCLES); // wait for data ready
220                        Low_byte = V_SRAM[0]; // get the low byte
221                        swiDelay(WAIT_CYCLES); // wait after for Motion Pak to be ready for next command
222                        output = (signed int)( (High_byte<<8 | Low_byte)>>4);
223                        return output;
224                        break;
225                case 2: // DS Motion Card
226                        SPI_On()
227                        motion_spi(0x00); // command to convert X axis
228                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
229                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
230                        SPI_Off()
231                        return output;
232                        break;
233                case 3: // MK6 - same command as DS Motion Card
234                        SPI_On()
235                        motion_spi(0x00); // command to convert X axis
236                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
237                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
238                        SPI_Off()
239                        return output;
240                        break;                 
241                default:
242                        return 0;
243                        break;
244        }
245}
246
247// read the Y acceleration
248signed int motion_read_y(void) {
249        unsigned char High_byte = 0;
250        unsigned char Low_byte = 0;
251        signed int output = 0;
252        switch (card_type)
253        {
254                case 1: // DS Motion Pak
255                        High_byte = V_SRAM[4]; // Command to load Y High onto bus
256                        swiDelay(WAIT_CYCLES); // wait for data ready
257                        High_byte = V_SRAM[0]; // get the high byte
258                        swiDelay(WAIT_CYCLES); // wait for data ready
259                        Low_byte = V_SRAM[0]; // get the low byte
260                        swiDelay(WAIT_CYCLES); // wait after for Motion Pak to be ready for next command
261                        output = (signed int)( (High_byte<<8 | Low_byte)>>4);
262                        return output;
263                        break;
264                case 2: // DS Motion Card
265                        SPI_On()
266                        motion_spi(0x02); // command to convert Y axis
267                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
268                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
269                        SPI_Off()
270                        return output;
271                        break;
272                case 3: // MK6 - same command as DS Motion Card
273                        SPI_On()
274                        motion_spi(0x02); // command to convert Y axis
275                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
276                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
277                        SPI_Off()
278                        return output;
279                        break;                         
280                default:
281                        return 0;
282                        break;
283        }
284}
285
286// read the Z acceleration
287signed int motion_read_z(void) {
288        unsigned char High_byte = 0;
289        unsigned char Low_byte = 0;
290        signed int output = 0;
291        switch (card_type)
292        {
293                case 1: // DS Motion Pak
294                        High_byte = V_SRAM[6]; // Command to load Z High onto bus
295                        swiDelay(WAIT_CYCLES); // wait for data ready
296                        High_byte = V_SRAM[0]; // get the high byte
297                        swiDelay(WAIT_CYCLES); // wait for data ready
298                        Low_byte = V_SRAM[0]; // get the low byte
299                        swiDelay(WAIT_CYCLES); // wait after for Motion Pak to be ready for next command
300                        output = (signed int)( (High_byte<<8 | Low_byte)>>4);
301                        return output;
302                        break;
303                case 2: // DS Motion Card
304                        SPI_On()
305                        motion_spi(0x01); // command to convert Z axis
306                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
307                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
308                        SPI_Off()
309                        return output;
310                        break;
311                case 3: // MK6 - same command as DS Motion Card
312                        SPI_On()
313                        motion_spi(0x01); // command to convert Z axis
314                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
315                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
316                        SPI_Off()
317                        return output;
318                        break;                         
319                default:
320                        return 0;
321                        break;
322        }
323}
324
325// read the Z rotation (gyro)
326signed int motion_read_gyro(void) {
327        unsigned char High_byte = 0;
328        unsigned char Low_byte = 0;
329        signed int output = 0;
330        switch (card_type)
331        {
332                case 1: // DS Motion Pak
333                        High_byte = V_SRAM[8]; // Command to load Gyro High onto bus
334                        swiDelay(WAIT_CYCLES); // wait for data ready
335                        High_byte = V_SRAM[0]; // get the high byte
336                        swiDelay(WAIT_CYCLES); // wait for data ready
337                        Low_byte = V_SRAM[0]; // get the low byte
338                        swiDelay(WAIT_CYCLES); // wait after for Motion Pak to be ready for next command
339                        output = (signed int)( (High_byte<<8 | Low_byte)>>4);
340                        return output;
341                        break;
342                case 2: // DS Motion Card
343                        SPI_On()
344                        motion_spi(0x07); // command to convert Gyro axis
345                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
346                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
347                        SPI_Off()
348                        return output;
349                        break;
350                case 3: // MK6 - same command as DS Motion Card
351                        SPI_On()
352                        motion_spi(0x07); // command to convert Gyro axis
353                        swiDelay(625); // wait at least 40 microseconds for the A-D conversion
354                        output = ( (motion_spi(0x00)<<8)|motion_spi(0x00) )>>4; // read 16 bits and store as a 12 bit number
355                        SPI_Off()
356                        return output;
357                        break;                         
358                default:
359                        return 0;
360                        break;
361        }
362}
363
364//gets acceleration value in mili G (where g is 9.8 m/s*s)
365int motion_acceleration_x(void){
366        int accel = motion_read_x();
367        return (accel - calibration.xoff) * 1000 / calibration.xsens;
368}
369
370//gets acceleration value in mili G (where g is 9.8 m/s*s)
371int motion_acceleration_y(void){
372        int accel = motion_read_y();
373        return (accel - calibration.yoff) * 1000 / calibration.ysens;
374}
375//gets acceleration value in mili G (where g is 9.8 m/s*s)
376int motion_acceleration_z(void){
377        int accel = motion_read_z();
378        return (accel - calibration.zoff) * 1000 / calibration.zsens;
379}
380
381//converts raw rotation value to degrees per second
382int motion_rotation(void){
383        int rotation = motion_read_gyro();
384        return (rotation - calibration.goff) * 1000 / calibration.gsens;
385}
386
387//this should be passed the raw reading at 1g for accurate
388//acceleration calculations.  Default is 819
389void motion_set_sens_x(int sens){
390        calibration.xsens = sens - calibration.xoff;
391}
392
393//this should be passed the raw reading at 1g for accurate
394//acceleration calculations.  Default is 819
395void motion_set_sens_y(int sens){
396        calibration.ysens = sens - calibration.yoff;
397}
398
399//this should be passed the raw reading at 1g for accurate
400//acceleration calculations.  Default is 819
401void motion_set_sens_z(int sens){
402        calibration.zsens = sens - calibration.zoff;
403}
404
405//this should be passed the raw reading at 1g for accurate
406//acceleration calculations.  Default is 825
407void motion_set_sens_gyro(int sens){
408        calibration.gsens = sens;
409}
410
411//this should be called when the axis is under no acceleration
412//default is 2048
413void motion_set_offs_x(void){
414        calibration.xoff = motion_read_x();
415}
416
417//this should be called when the axis is under no acceleration
418//default is 2048
419void motion_set_offs_y(void){
420        calibration.yoff = motion_read_y();
421}
422
423//this should be called when the axis is under no acceleration
424//default is 2048
425void motion_set_offs_z(void){
426        calibration.zoff = motion_read_z();
427}
428
429//this should be called when the axis is under no acceleration
430//default is 1680
431void motion_set_offs_gyro(void){
432        calibration.goff = motion_read_gyro();
433}
434
435MotionCalibration* motion_get_calibration(void){
436        return &calibration;
437}
438
439void motion_set_calibration(MotionCalibration* cal){
440        calibration.xsens = cal->xsens;
441        calibration.ysens = cal->ysens;
442        calibration.zsens = cal->zsens;
443        calibration.gsens = cal->gsens;
444        calibration.xoff = cal->xoff;
445        calibration.yoff = cal->yoff;
446        calibration.zoff = cal->zoff;
447        calibration.goff = cal->goff;
448}
449
450// enable analog input number 1 (ain_1)
451void motion_enable_ain_1(void){
452        unsigned char return_byte;
453    return_byte = V_SRAM[16];
454        swiDelay(WAIT_CYCLES);
455}
456
457// enable analog input number 2 (ain_2)
458void motion_enable_ain_2(void){
459        unsigned char return_byte;
460    return_byte = V_SRAM[18];
461        swiDelay(WAIT_CYCLES);
462}
463
464// read from the analog input number 1 - requires enabling ain_1 first
465int motion_read_ain_1(void){
466        unsigned char High_byte = V_SRAM[12]; // Command to load AIN_1 High onto bus
467        swiDelay(WAIT_CYCLES); // wait for data ready
468        High_byte = V_SRAM[0]; // get the high byte
469        swiDelay(WAIT_CYCLES); // wait for data ready
470        unsigned char Low_byte = V_SRAM[0]; // get the low byte
471        swiDelay(WAIT_CYCLES); // wait after for Motion Pak to be ready for next command
472        signed int output = (signed int)( (High_byte<<8 | Low_byte)>>4);
473        return output;
474}
475
476// read from the analog input number 2 - requires enabling ain_2 first
477int motion_read_ain_2(void){
478        unsigned char High_byte = V_SRAM[14]; // Command to load AIN_1 High onto bus
479        swiDelay(WAIT_CYCLES); // wait for data ready
480        High_byte = V_SRAM[0]; // get the high byte
481        swiDelay(WAIT_CYCLES); // wait for data ready
482        unsigned char Low_byte = V_SRAM[0]; // get the low byte
483        swiDelay(WAIT_CYCLES); // wait after for Motion Pak to be ready for next command
484        signed int output = (signed int)( (High_byte<<8 | Low_byte)>>4);
485        return output;
486}       
487
488
Note: See TracBrowser for help on using the repository browser.