mirror of
				https://github.com/eclipse/upm.git
				synced 2025-10-28 05:34:06 +03:00 
			
		
		
		
	nunchuck: C port; FTI; C++ wraps C
Some API changes were made as well, see docs/apichanges.md. Signed-off-by: Jon Trulson <jtrulson@ics.com>
This commit is contained in:
		| @@ -4,6 +4,14 @@ API Changes                       {#apichanges} | ||||
| Here's a list of other API changes made to the library that break source/binary | ||||
| compatibility between releases: | ||||
|  | ||||
|  * **nunchuck** This driver no longer supports the init() function. | ||||
|    All initialization is now done in the C nunchuck_init() function, | ||||
|    or the C++ constructor.  In addition, the *NUNCHUCK_I2C_ADDR* | ||||
|    define is no longer exposed, as it is not possible to use any other | ||||
|    I2C address than *0x52*.  The readBytes() and writeByte() functions | ||||
|    are also no longer exposed, since aside from what the driver does | ||||
|    to initialize and read data, there are no other options available. | ||||
|  | ||||
|  * **enc03r** This driver no longer supports the value() function.  In | ||||
|  addition, an update() function has been added.  This function must be | ||||
|  called prior to calling angularVelocity().  angularVelocity() no | ||||
|   | ||||
| @@ -43,16 +43,8 @@ int main(int argc, char **argv) | ||||
|   signal(SIGINT, sig_handler); | ||||
|  | ||||
| //! [Interesting] | ||||
|   // Instantiate a nunchuck controller bus 0 | ||||
|   upm::NUNCHUCK *nunchuck = new upm::NUNCHUCK(0); | ||||
|    | ||||
|   // always do this first | ||||
|   cout << "Initializing... " << endl; | ||||
|   if (!nunchuck->init()) | ||||
|     { | ||||
|       cerr << "nunchuck->init() failed." << endl; | ||||
|       return 0; | ||||
|     } | ||||
|   // Instantiate a nunchuck controller bus 3 | ||||
|   upm::NUNCHUCK *nunchuck = new upm::NUNCHUCK(3); | ||||
|  | ||||
|   while (shouldRun) | ||||
|     { | ||||
|   | ||||
| @@ -148,6 +148,7 @@ add_example (cjq4435) | ||||
| add_example (hmc5883l) | ||||
| add_example (wfs) | ||||
| add_example (enc03r) | ||||
| add_example (nunchuck) | ||||
|  | ||||
| # Custom examples | ||||
| add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) | ||||
|   | ||||
							
								
								
									
										84
									
								
								examples/c/nunchuck.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								examples/c/nunchuck.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| /* | ||||
|  * Author: Jon Trulson <jtrulson@ics.com> | ||||
|  * Copyright (c) 2015 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <unistd.h> | ||||
| #include <stdio.h> | ||||
| #include <signal.h> | ||||
|  | ||||
| #include <upm_utilities.h> | ||||
| #include "nunchuck.h" | ||||
|  | ||||
| bool shouldRun = true; | ||||
|  | ||||
| void sig_handler(int signo) | ||||
| { | ||||
|     if (signo == SIGINT) | ||||
|         shouldRun = false; | ||||
| } | ||||
|  | ||||
| int main(int argc, char **argv) | ||||
| { | ||||
|     signal(SIGINT, sig_handler); | ||||
|  | ||||
| //! [Interesting] | ||||
|     // Instantiate a nunchuck controller bus 3 | ||||
|     nunchuck_context sensor = nunchuck_init(3); | ||||
|  | ||||
|     if (!sensor) | ||||
|     { | ||||
|         printf("%s: nunchuck_init() failed\n", __FUNCTION__); | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     while (shouldRun) | ||||
|     { | ||||
|         if (nunchuck_update(sensor)) | ||||
|         { | ||||
|             printf("%s: nunchuck_update() failed\n", __FUNCTION__); | ||||
|             nunchuck_close(sensor); | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         int x, y, z; | ||||
|         nunchuck_get_stick(sensor, &x, &y); | ||||
|         printf("stickX: %d stickY: %d\n", x, y); | ||||
|  | ||||
|         nunchuck_get_acceleration(sensor, &x, &y, &z); | ||||
|         printf("accelX: %d accelY: %d accelZ: %d\n", x, y, z); | ||||
|  | ||||
|         bool bc, bz; | ||||
|         nunchuck_get_buttons(sensor, &bc, &bz); | ||||
|         printf("button C: %s\n", | ||||
|                ((bc) ? "pressed" : "not pressed")); | ||||
|         printf("button Z: %s\n\n", | ||||
|                ((bz) ? "pressed" : "not pressed")); | ||||
|  | ||||
|         upm_delay_ms(100); | ||||
|     } | ||||
|  | ||||
|     nunchuck_close(sensor); | ||||
|  | ||||
|     //! [Interesting] | ||||
|     return 0; | ||||
| } | ||||
| @@ -27,21 +27,21 @@ public class NUNCHUCKSample { | ||||
|     public static void main(String[] args) throws InterruptedException { | ||||
|         // ! [Interesting] | ||||
|         // Instantiate a nunchuck controller bus 0 | ||||
| 		upm_nunchuck.NUNCHUCK nunchuck = new upm_nunchuck.NUNCHUCK(0); | ||||
|         upm_nunchuck.NUNCHUCK nunchuck = new upm_nunchuck.NUNCHUCK(3); | ||||
|  | ||||
| 		// always do this first | ||||
| 		System.out.println("Initializing... "); | ||||
| 		if (!nunchuck.init()) { | ||||
| 			System.err.println("nunchuck->init() failed."); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		while (true) { | ||||
|         while (true) | ||||
|         { | ||||
|             nunchuck.update(); | ||||
| 			System.out.println("stickX: " + nunchuck.getStickX() + ", stickY: " | ||||
|             System.out.println("stickX: " | ||||
|                                + nunchuck.getStickX() | ||||
|                                + ", stickY: " | ||||
|                                + nunchuck.getStickY()); | ||||
| 			System.out.println("accelX: " + nunchuck.getAccelX() + ", accelY: " | ||||
| 					+ nunchuck.getAccelY() + ", accelZ: " + nunchuck.getAccelZ()); | ||||
|             System.out.println("accelX: " | ||||
|                                + nunchuck.getAccelX() | ||||
|                                + ", accelY: " | ||||
|                                + nunchuck.getAccelY() | ||||
|                                + ", accelZ: " | ||||
|                                + nunchuck.getAccelZ()); | ||||
|  | ||||
|             if (nunchuck.getButtonC()) | ||||
|                 System.out.println("Button C pressed"); | ||||
| @@ -53,7 +53,7 @@ public class NUNCHUCKSample { | ||||
|             else | ||||
|                 System.out.println("Button Z not pressed"); | ||||
|  | ||||
| 			Thread.sleep(1000); | ||||
|             Thread.sleep(100); | ||||
|         } | ||||
|         // ! [Interesting] | ||||
|     } | ||||
|   | ||||
| @@ -24,16 +24,8 @@ | ||||
|  | ||||
| var nunchuck_lib = require('jsupm_nunchuck'); | ||||
|  | ||||
| // Instantiate a nunchuck controller bus 0 | ||||
| var nunchuck_obj = new nunchuck_lib.NUNCHUCK(0); | ||||
|  | ||||
| // always do this first | ||||
| console.log("Initializing... "); | ||||
| if (!nunchuck_obj.init()) | ||||
| { | ||||
| 	console.log("nunchuck->init() failed."); | ||||
| 	process.exit(0); | ||||
| } | ||||
| // Instantiate a nunchuck controller bus 3 | ||||
| var nunchuck_obj = new nunchuck_lib.NUNCHUCK(3); | ||||
|  | ||||
| setInterval(function() | ||||
| { | ||||
|   | ||||
| @@ -26,8 +26,8 @@ import time, sys, signal, atexit | ||||
| from upm import pyupm_nunchuck as upmNunchuck | ||||
|  | ||||
| def main(): | ||||
|     # Instantiate a nunchuck controller bus 0 on I2C | ||||
|     myNunchuck = upmNunchuck.NUNCHUCK(0) | ||||
|     # Instantiate a nunchuck controller bus 3 on I2C | ||||
|     myNunchuck = upmNunchuck.NUNCHUCK(3) | ||||
|  | ||||
|     ## Exit handlers ## | ||||
|     # This function stops python from printing a stacktrace when you hit control-C | ||||
| @@ -43,12 +43,6 @@ def main(): | ||||
|     atexit.register(exitHandler) | ||||
|     signal.signal(signal.SIGINT, SIGINTHandler) | ||||
|  | ||||
|     # always do this first | ||||
|     print("Initializing... ") | ||||
|     if (not myNunchuck.init()): | ||||
|         print("nunchuck->init() failed.") | ||||
|         sys.exit(0); | ||||
|  | ||||
|     def buttonStateStr(buttonState): | ||||
|         return "pressed" if buttonState else "not pressed" | ||||
|  | ||||
|   | ||||
							
								
								
									
										46
									
								
								include/fti/upm_buttons.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								include/fti/upm_buttons.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| /* | ||||
|  * Author: Jon Trulson <jtrulson@ics.com> | ||||
|  * Copyright (c) 2017 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| #ifndef UPM_BUTTONS_H_ | ||||
| #define UPM_BUTTONS_H_ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| // Buttons function table | ||||
| typedef struct _upm_buttons_ft { | ||||
|     // This function is used to query button state.  The num_button | ||||
|     // specifies the total number of buttons present, and the values | ||||
|     // indicates each button's current value as an array of bools. | ||||
|     upm_result_t (*upm_buttons_get_num_buttons) (const void *dev, | ||||
|                                                  unsigned int *num_buttons); | ||||
|     upm_result_t (*upm_buttons_get_values) (const void *dev, | ||||
|                                             bool *values); | ||||
| } upm_buttons_ft; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* UPM_BUTTONS_H_ */ | ||||
| @@ -75,7 +75,8 @@ typedef enum { | ||||
|     UPM_STREAM, | ||||
|     UPM_ORP, | ||||
|     UPM_BINARY, | ||||
|     UPM_ROTARYENCODER | ||||
|     UPM_ROTARYENCODER, | ||||
|     UPM_BUTTONS | ||||
| } upm_sensor_t; | ||||
|  | ||||
| /* Supported IO protocols via MRAA */ | ||||
| @@ -127,6 +128,8 @@ typedef struct _upm_sensor_ft* (*func_get_upm_sensor_ft)(upm_sensor_t sensor_typ | ||||
| #include <fti/upm_pressure.h> | ||||
| #include <fti/upm_compass.h> | ||||
| #include <fti/upm_gyroscope.h> | ||||
| #include <fti/upm_buttons.h> | ||||
| #include <fti/upm_joystick.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,9 @@ | ||||
| set (libname "nunchuck") | ||||
| set (libdescription "Wii nunchuck module") | ||||
| set (module_src ${libname}.cxx) | ||||
| set (module_hpp ${libname}.hpp) | ||||
| upm_module_init() | ||||
| upm_mixed_module_init (NAME nunchuck | ||||
|     DESCRIPTION "I2C nunchuck driver" | ||||
|     C_HDR nunchuck.h | ||||
|     C_SRC nunchuck.c | ||||
|     CPP_HDR nunchuck.hpp | ||||
|     CPP_SRC nunchuck.cxx | ||||
|     FTI_SRC nunchuck_fti.c | ||||
|     CPP_WRAPS_C | ||||
|     REQUIRES mraa) | ||||
|   | ||||
							
								
								
									
										206
									
								
								src/nunchuck/nunchuck.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								src/nunchuck/nunchuck.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| /* | ||||
|  * Author: Jon Trulson <jtrulson@ics.com> | ||||
|  * Copyright (c) 2017 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <assert.h> | ||||
|  | ||||
| #include "nunchuck.h" | ||||
|  | ||||
| // This is not changeable | ||||
| #define NUNCHUCK_I2C_ADDR    0x52 | ||||
|  | ||||
| // static functions for r/w the device.  No user-serviceable parts | ||||
| // inside. | ||||
|  | ||||
| static upm_result_t nunchuck_write_byte(const nunchuck_context dev, | ||||
|                                         uint8_t reg, uint8_t byte) | ||||
| { | ||||
|     assert(dev != NULL); | ||||
|  | ||||
|     if (mraa_i2c_write_byte_data(dev->i2c, byte, reg)) | ||||
|     { | ||||
|         printf("%s: mraa_i2c_write_byte_data() failed\n", __FUNCTION__); | ||||
|         return UPM_ERROR_OPERATION_FAILED; | ||||
|     } | ||||
|  | ||||
|     return UPM_SUCCESS; | ||||
| } | ||||
|  | ||||
| static int nunchuck_read_bytes(const nunchuck_context dev, uint8_t reg, | ||||
|                                uint8_t *buffer, int len) | ||||
| { | ||||
|     assert(dev != NULL); | ||||
|  | ||||
|     if (!len || !buffer) | ||||
|         return 0; | ||||
|  | ||||
|     if (mraa_i2c_write_byte(dev->i2c, reg)) | ||||
|     { | ||||
|         printf("%s: mraa_i2c_write_byte() failed\n", __FUNCTION__); | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     return mraa_i2c_read(dev->i2c, buffer, len); | ||||
| } | ||||
|  | ||||
| // init | ||||
| nunchuck_context nunchuck_init(int bus) | ||||
| { | ||||
|     // make sure MRAA is initialized | ||||
|     int mraa_rv; | ||||
|     if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) | ||||
|     { | ||||
|         printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     nunchuck_context dev = | ||||
|         (nunchuck_context)malloc(sizeof(struct _nunchuck_context)); | ||||
|  | ||||
|     if (!dev) | ||||
|         return NULL; | ||||
|  | ||||
|     memset((void *)dev, 0, sizeof(struct _nunchuck_context)); | ||||
|  | ||||
|     // setup our i2c link | ||||
|     if ( !(dev->i2c = mraa_i2c_init(bus)) ) | ||||
|     { | ||||
|         printf("%s: mraa_i2c_init() failed\n", __FUNCTION__); | ||||
|         nunchuck_close(dev); | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     if (mraa_i2c_address(dev->i2c, NUNCHUCK_I2C_ADDR)) | ||||
|     { | ||||
|         printf("%s: mraa_i2c_address() failed\n", __FUNCTION__); | ||||
|         nunchuck_close(dev); | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     // sleep for a second to let things settle | ||||
|     upm_delay(1); | ||||
|  | ||||
|     // disable encryption | ||||
|     if (nunchuck_write_byte(dev, 0xf0, 0x55) | ||||
|         || nunchuck_write_byte(dev, 0xfb, 0x00)) | ||||
|     { | ||||
|         printf("%s: nunchuck_write_byte() failed\n", __FUNCTION__); | ||||
|         nunchuck_close(dev); | ||||
|         return NULL; | ||||
|     } | ||||
|  | ||||
|     return dev; | ||||
| } | ||||
|  | ||||
| void nunchuck_close(nunchuck_context dev) | ||||
| { | ||||
|     assert(dev != NULL); | ||||
|  | ||||
|     if (dev->i2c) | ||||
|         mraa_i2c_stop(dev->i2c); | ||||
|  | ||||
|     free(dev); | ||||
| } | ||||
|  | ||||
| upm_result_t nunchuck_update(const nunchuck_context dev) | ||||
| { | ||||
|     assert(dev != NULL); | ||||
|  | ||||
|     const int bufsize = 6; | ||||
|     uint8_t buf[bufsize]; | ||||
|     int rv; | ||||
|  | ||||
|     rv = nunchuck_read_bytes(dev, 0x00, buf, bufsize); | ||||
|  | ||||
|     if (rv != bufsize) | ||||
|     { | ||||
|         printf("%s: nunchuck_read_bytes() failed.  Expected %d, got %d.\n", | ||||
|                __FUNCTION__, bufsize, rv); | ||||
|         return UPM_ERROR_OPERATION_FAILED; | ||||
|     } | ||||
|  | ||||
|     // analog stick X | ||||
|     dev->stickX = buf[0]; | ||||
|  | ||||
|     // analog stick Y | ||||
|     dev->stickY = buf[1]; | ||||
|  | ||||
|     // accelerometer X | ||||
|     dev->accelX = ( (buf[2] << 2) | ((buf[5] & 0x0c) >> 2) ); | ||||
|  | ||||
|     // accelerometer Y | ||||
|     dev->accelY = ( (buf[3] << 2) | ((buf[5] & 0x30) >> 4) ); | ||||
|  | ||||
|     // accelerometer Z | ||||
|     dev->accelZ = ( (buf[4] << 2) | ((buf[5] & 0xc0) >> 6) ); | ||||
|  | ||||
|     // buttonC | ||||
|     if (buf[5] & 0x02) | ||||
|         dev->buttonC = false; | ||||
|     else | ||||
|         dev->buttonC = true; | ||||
|  | ||||
|     // buttonZ | ||||
|     if (buf[5] & 0x01) | ||||
|         dev->buttonZ = false; | ||||
|     else | ||||
|         dev->buttonZ = true; | ||||
|  | ||||
|     return UPM_SUCCESS; | ||||
| } | ||||
|  | ||||
| void nunchuck_get_stick(const nunchuck_context dev, int *x, int *y) | ||||
| { | ||||
|     assert(dev != NULL); | ||||
|  | ||||
|     if (x) | ||||
|         *x = dev->stickX; | ||||
|     if (y) | ||||
|         *y = dev->stickY; | ||||
| } | ||||
|  | ||||
| void nunchuck_get_acceleration(const nunchuck_context dev, | ||||
|                                int *x, int *y, int *z) | ||||
| { | ||||
|     assert(dev != NULL); | ||||
|  | ||||
|     if (x) | ||||
|         *x = dev->accelX; | ||||
|     if (y) | ||||
|         *y = dev->accelY; | ||||
|     if (z) | ||||
|         *z = dev->accelZ; | ||||
| } | ||||
|  | ||||
| void nunchuck_get_buttons(const nunchuck_context dev, bool *c, bool *z) | ||||
| { | ||||
|     assert(dev != NULL); | ||||
|  | ||||
|     if (c) | ||||
|         *c = dev->buttonC; | ||||
|     if (z) | ||||
|         *z = dev->buttonZ; | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * Author: Jon Trulson <jtrulson@ics.com> | ||||
|  * Copyright (c) 2015 Intel Corporation. | ||||
|  * Copyright (c) 2015-2017 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
| @@ -33,117 +33,27 @@ using namespace upm; | ||||
| using namespace std; | ||||
|  | ||||
|  | ||||
| NUNCHUCK::NUNCHUCK(int bus, uint8_t addr) | ||||
| NUNCHUCK::NUNCHUCK(int bus) : | ||||
|     m_nunchuck(nunchuck_init(bus)) | ||||
| { | ||||
|   stickX = 0; | ||||
|   stickY = 0; | ||||
|   accelX = 0; | ||||
|   accelY = 0; | ||||
|   accelZ = 0; | ||||
|   buttonC = false; | ||||
|   buttonZ = false; | ||||
|  | ||||
|   // setup our i2c link | ||||
|   if ( !(m_i2c = mraa_i2c_init(bus)) )  | ||||
|     { | ||||
|       throw std::invalid_argument(std::string(__FUNCTION__) + | ||||
|                                   ": mraa_i2c_init() failed"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   mraa_result_t rv; | ||||
|  | ||||
|   if ( (rv = mraa_i2c_address(m_i2c, addr)) != MRAA_SUCCESS ) | ||||
|     { | ||||
|       throw std::invalid_argument(std::string(__FUNCTION__) + | ||||
|                                   ": mraa_i2c_address() failed"); | ||||
|     } | ||||
|     if (!m_nunchuck) | ||||
|         throw std::runtime_error(string(__FUNCTION__) | ||||
|                                  + ": nunchuck_init() failed"); | ||||
| } | ||||
|  | ||||
| NUNCHUCK::~NUNCHUCK() | ||||
| { | ||||
|   mraa_i2c_stop(m_i2c); | ||||
| } | ||||
|  | ||||
| bool NUNCHUCK::writeByte(uint8_t reg, uint8_t byte) | ||||
| { | ||||
|   mraa_result_t rv; | ||||
|  | ||||
|   if ( (rv = mraa_i2c_write_byte_data(m_i2c, byte, reg)) != MRAA_SUCCESS ) | ||||
|     { | ||||
|       throw std::runtime_error(std::string(__FUNCTION__) + | ||||
|                                ": mraa_i2c_write_byte_data() failed"); | ||||
|       return false; | ||||
|     } | ||||
|  | ||||
|   return true; | ||||
| } | ||||
|  | ||||
| int NUNCHUCK::readBytes(uint8_t reg, uint8_t *buffer, int len) | ||||
| { | ||||
|   if (!len || !buffer) | ||||
|     return 0; | ||||
|  | ||||
|   mraa_i2c_address(m_i2c, NUNCHUCK_I2C_ADDR); | ||||
|   mraa_i2c_write_byte(m_i2c, reg); | ||||
|  | ||||
|   return mraa_i2c_read(m_i2c, buffer, len); | ||||
| } | ||||
|  | ||||
| bool NUNCHUCK::init() | ||||
| { | ||||
|   usleep(1000000); | ||||
|  | ||||
|   // disable encryption | ||||
|   if (!writeByte(0xf0, 0x55)) | ||||
|     return false; | ||||
|  | ||||
|   if (!writeByte(0xfb, 0x00)) | ||||
|     return false; | ||||
|  | ||||
|   return true; | ||||
|     nunchuck_close(m_nunchuck); | ||||
| } | ||||
|  | ||||
| void NUNCHUCK::update() | ||||
| { | ||||
|   const int bufsize = 6; | ||||
|   uint8_t buf[bufsize]; | ||||
|   int rv; | ||||
|     if (nunchuck_update(m_nunchuck)) | ||||
|         throw std::runtime_error(string(__FUNCTION__) | ||||
|                                  + ": nunchuck_update() failed"); | ||||
|  | ||||
|   rv = readBytes(0x00, buf, bufsize); | ||||
|  | ||||
|   if (rv != bufsize) | ||||
|     { | ||||
|       throw std::runtime_error(std::string(__FUNCTION__) + | ||||
|                                ": readBytes() failed"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   // analog stick X | ||||
|   stickX = buf[0]; | ||||
|  | ||||
|   // analog stick Y | ||||
|   stickY = buf[1]; | ||||
|  | ||||
|   // accelerometer X | ||||
|   accelX = ( (buf[2] << 2) | ((buf[5] & 0x0c) >> 2) ); | ||||
|  | ||||
|   // accelerometer Y | ||||
|   accelY = ( (buf[3] << 2) | ((buf[5] & 0x30) >> 4) ); | ||||
|  | ||||
|   // accelerometer Z | ||||
|   accelZ = ( (buf[4] << 2) | ((buf[5] & 0xc0) >> 6) ); | ||||
|  | ||||
|   // buttonC | ||||
|   if (buf[5] & 0x02) | ||||
|     buttonC = false; | ||||
|   else | ||||
|     buttonC = true; | ||||
|  | ||||
|   // buttonZ | ||||
|   if (buf[5] & 0x01) | ||||
|     buttonZ = false; | ||||
|   else | ||||
|     buttonZ = true; | ||||
|     nunchuck_get_stick(m_nunchuck, &stickX, &stickY); | ||||
|     nunchuck_get_acceleration(m_nunchuck, &accelX, &accelY, &accelZ); | ||||
|     nunchuck_get_buttons(m_nunchuck, &buttonC, &buttonZ); | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										123
									
								
								src/nunchuck/nunchuck.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								src/nunchuck/nunchuck.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| /* | ||||
|  * Author: Jon Trulson <jtrulson@ics.com> | ||||
|  * Copyright (c) 2017 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <upm.h> | ||||
|  | ||||
| #include <mraa/i2c.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
|     /** | ||||
|      * @file nunchuck.h | ||||
|      * @library nunchuck | ||||
|      * @brief C API for the nunchuck driver | ||||
|      * | ||||
|      * @include nunchuck.c | ||||
|      */ | ||||
|  | ||||
|     /** | ||||
|      * Device context | ||||
|      */ | ||||
|     typedef struct _nunchuck_context { | ||||
|         mraa_i2c_context  i2c; | ||||
|  | ||||
|         // sticks - x, y | ||||
|         int stickX; | ||||
|         int stickY; | ||||
|  | ||||
|         // accel | ||||
|         int accelX; | ||||
|         int accelY; | ||||
|         int accelZ; | ||||
|  | ||||
|         // buttons | ||||
|         bool buttonC; | ||||
|         bool buttonZ; | ||||
|  | ||||
|     } *nunchuck_context; | ||||
|  | ||||
|     /** | ||||
|      * NUNCHUCK constructor | ||||
|      * | ||||
|      * @param bus I2C bus to use | ||||
|      * @return A Device context, or NULL on error | ||||
|      */ | ||||
|     nunchuck_context nunchuck_init(int bus); | ||||
|  | ||||
|     /** | ||||
|      * Close the device and deallocate all resources. | ||||
|      * | ||||
|      * @param dev Device context | ||||
|      */ | ||||
|     void nunchuck_close(nunchuck_context dev); | ||||
|  | ||||
|     /** | ||||
|      * Reads and updates the current state of the controller. | ||||
|      * | ||||
|      * @param dev Device context | ||||
|      * @return UPM result | ||||
|      */ | ||||
|     upm_result_t nunchuck_update(const nunchuck_context dev); | ||||
|  | ||||
|     /** | ||||
|      * Returns the current analog stick X and Y positions. | ||||
|      * nunchuck_update() must have been called prior to calling this | ||||
|      * function. | ||||
|      * | ||||
|      * @param dev Device context | ||||
|      * @param x Pointer in which the X value will be stored | ||||
|      * @param y Pointer in which the Y value will be stored | ||||
|      */ | ||||
|     void nunchuck_get_stick(const nunchuck_context dev, int *x, int *y); | ||||
|  | ||||
|     /** | ||||
|      * Returns the current accelerometer values.  nunchuck_update() | ||||
|      * must have been called prior to calling this function. | ||||
|      * | ||||
|      * @param dev Device context | ||||
|      * @param x Pointer in which the X value will be stored | ||||
|      * @param y Pointer in which the Y value will be stored | ||||
|      * @param z Pointer in which the Z value will be stored | ||||
|      */ | ||||
|     void nunchuck_get_acceleration(const nunchuck_context dev, | ||||
|                                    int *x, int *y, int *z); | ||||
|  | ||||
|     /** | ||||
|      * Returns the current button values values.  nunchuck_update() | ||||
|      * must have been called prior to calling this function. | ||||
|      * | ||||
|      * @param dev Device context | ||||
|      * @param c Pointer in which the C button value will be stored | ||||
|      * @param z Pointer in which the Z button value will be stored | ||||
|      */ | ||||
|     void nunchuck_get_buttons(const nunchuck_context dev, bool *c, bool *z); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * Author: Jon Trulson <jtrulson@ics.com> | ||||
|  * Copyright (c) 2015 Intel Corporation. | ||||
|  * Copyright (c) 2015-2017 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
| @@ -24,9 +24,8 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <string> | ||||
| #include <mraa/i2c.h> | ||||
| #include "nunchuck.h" | ||||
|  | ||||
| #define NUNCHUCK_I2C_ADDR    0x52 | ||||
|  | ||||
| namespace upm { | ||||
|  | ||||
| @@ -48,17 +47,16 @@ namespace upm { | ||||
|    * @brief API for the Wii* Nunchuk controller | ||||
|    * | ||||
|    * UPM module for the Wii Nunchuk controller. This module was tested with | ||||
|    * Wii Nunchuk connected to I2C via a Grove Wii Nunchuk adapter. | ||||
|    * Wii Nunchuck connected to I2C via a Grove Wii Nunchuck adapter. | ||||
|    * | ||||
|    * See http://wiibrew.org/wiki/Wiimote/Extension_Controllers and | ||||
|    * http://wiibrew.org/wiki/Wiimote/Extension_Controllers/Nunchuck | ||||
|    * for more details on the controller and its protocol. | ||||
|    * | ||||
|    * A warning for the Grove Wii Nunchuk adapter: it has 2 traces on one | ||||
|    * side, and 3 traces on the other.  Do not match these up with the | ||||
|    * Nunchuk connector's traces. The connector's 'Grove' | ||||
|    * should be on the same side as the Grove interface socket on the | ||||
|    * adapter. | ||||
|    * A warning for the Grove Wii Nunchuk adapter: it has 2 traces on | ||||
|    * one side, and 3 traces on the other.  Do not match these up with | ||||
|    * the Nunchuk connector's traces. The connector's 'groove' should | ||||
|    * be on the same side as the Grove interface socket on the adapter. | ||||
|    * | ||||
|    * @image html nunchuck.jpg | ||||
|    * @snippet nunchuck.cxx Interesting | ||||
| @@ -71,39 +69,12 @@ namespace upm { | ||||
|      * @param bus I2C bus to use | ||||
|      * @param addr I2C address to use | ||||
|      */ | ||||
|     NUNCHUCK(int bus, uint8_t addr=NUNCHUCK_I2C_ADDR); | ||||
|     NUNCHUCK(int bus); | ||||
|  | ||||
|     /** | ||||
|      * NUNCHUCK destructor | ||||
|      */ | ||||
|     ~NUNCHUCK(); | ||||
|  | ||||
|     /** | ||||
|      * Writes value(s) into registers | ||||
|      * | ||||
|      * @param reg Register location to start writing into | ||||
|      * @param byte Byte to write | ||||
|      * @return True if successful | ||||
|      */ | ||||
|     bool writeByte(uint8_t reg, uint8_t byte); | ||||
|  | ||||
|     /** | ||||
|      * Reads value(s) from registers | ||||
|      * | ||||
|      * @param reg Register location to start reading from | ||||
|      * @param buffer Buffer for data storage | ||||
|      * @param len Number of bytes to read | ||||
|      * @return Number of bytes read | ||||
|      */ | ||||
|     int readBytes(uint8_t reg, uint8_t *buffer, int len); | ||||
|  | ||||
|     /** | ||||
|      * Initializes the controller. Here, we disable encryption after | ||||
|      * delaying for a time to ensure the controller is ready. | ||||
|      * | ||||
|      * @return True if initialization is successful | ||||
|      */ | ||||
|     bool init(); | ||||
|     virtual ~NUNCHUCK(); | ||||
|  | ||||
|     /** | ||||
|      * Reads and updates the current state of the controller. | ||||
| @@ -153,8 +124,10 @@ namespace upm { | ||||
|      */ | ||||
|     bool buttonZ; | ||||
|  | ||||
|   protected: | ||||
|       nunchuck_context m_nunchuck; | ||||
|  | ||||
|   private: | ||||
|     mraa_i2c_context m_i2c; | ||||
|   }; | ||||
| } | ||||
|  | ||||
|   | ||||
							
								
								
									
										190
									
								
								src/nunchuck/nunchuck_fti.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								src/nunchuck/nunchuck_fti.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,190 @@ | ||||
| /* | ||||
|  * Author: Jon Trulson <jtrulson@ics.com> | ||||
|  * Copyright (c) 2017 Intel Corporation. | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining | ||||
|  * a copy of this software and associated documentation files (the | ||||
|  * "Software"), to deal in the Software without restriction, including | ||||
|  * without limitation the rights to use, copy, modify, merge, publish, | ||||
|  * distribute, sublicense, and/or sell copies of the Software, and to | ||||
|  * permit persons to whom the Software is furnished to do so, subject to | ||||
|  * the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be | ||||
|  * included in all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
|  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
|  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
|  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
|  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
|  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
|  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| #include "nunchuck.h" | ||||
|  | ||||
| #include "upm_fti.h" | ||||
|  | ||||
| /** | ||||
|  * This file implements the Function Table Interface (FTI) for this sensor | ||||
|  */ | ||||
|  | ||||
| const char upm_nunchuck_name[] = "NUNCHUCK"; | ||||
| const char upm_nunchuck_description[] = "Nunchuck controller"; | ||||
| const upm_protocol_t upm_nunchuck_protocol[] = {UPM_I2C}; | ||||
| const upm_sensor_t upm_nunchuck_category[] = | ||||
| { UPM_ACCELEROMETER, UPM_JOYSTICK, UPM_BUTTONS}; | ||||
|  | ||||
| // forward declarations | ||||
| const void* upm_nunchuck_get_ft(upm_sensor_t sensor_type); | ||||
| void* upm_nunchuck_init_name(); | ||||
| void upm_nunchuck_close(void *dev); | ||||
| upm_result_t upm_nunchuck_get_accel_values(void *dev, float *value, upm_acceleration_u unit); | ||||
| upm_result_t upm_nunchuck_get_joystick_value_x(const void *dev, float *value); | ||||
| upm_result_t upm_nunchuck_get_joystick_value_y(const void *dev, float *value); | ||||
| upm_result_t upm_nunchuck_get_num_buttons(const void *dev, | ||||
|                                           unsigned int *num_buttons); | ||||
| upm_result_t upm_nunchuck_get_button_values(const void *dev, | ||||
|                                             bool *values); | ||||
|  | ||||
| const upm_sensor_descriptor_t upm_nunchuck_get_descriptor() | ||||
| { | ||||
|     upm_sensor_descriptor_t usd; | ||||
|     usd.name = upm_nunchuck_name; | ||||
|     usd.description = upm_nunchuck_description; | ||||
|     usd.protocol_size = 1; | ||||
|     usd.protocol = upm_nunchuck_protocol; | ||||
|     usd.category_size = 3; | ||||
|     usd.category = upm_nunchuck_category; | ||||
|     return usd; | ||||
| } | ||||
|  | ||||
| static const upm_sensor_ft ft = | ||||
| { | ||||
|     .upm_sensor_init_name = upm_nunchuck_init_name, | ||||
|     .upm_sensor_close = upm_nunchuck_close, | ||||
| }; | ||||
|  | ||||
| static const upm_acceleration_ft aft = | ||||
| { | ||||
|     .upm_acceleration_get_value = upm_nunchuck_get_accel_values | ||||
| }; | ||||
|  | ||||
| static const upm_joystick_ft jft = | ||||
| { | ||||
|     .upm_joystick_get_value_x = upm_nunchuck_get_joystick_value_x, | ||||
|     .upm_joystick_get_value_y = upm_nunchuck_get_joystick_value_y | ||||
| }; | ||||
|  | ||||
| static const upm_buttons_ft bft = | ||||
| { | ||||
|     .upm_buttons_get_num_buttons = upm_nunchuck_get_num_buttons, | ||||
|     .upm_buttons_get_values = upm_nunchuck_get_button_values | ||||
| }; | ||||
|  | ||||
| const void* upm_nunchuck_get_ft(upm_sensor_t sensor_type) | ||||
| { | ||||
|   switch(sensor_type) | ||||
|     { | ||||
|     case UPM_SENSOR: | ||||
|       return &ft; | ||||
|  | ||||
|     case UPM_ACCELEROMETER: | ||||
|       return &aft; | ||||
|  | ||||
|     case UPM_JOYSTICK: | ||||
|       return &jft; | ||||
|  | ||||
|     case UPM_BUTTONS: | ||||
|       return &bft; | ||||
|  | ||||
|     default: | ||||
|       return NULL; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void* upm_nunchuck_init_name() | ||||
| { | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| void upm_nunchuck_close(void *dev) | ||||
| { | ||||
|     nunchuck_close((nunchuck_context)dev); | ||||
| } | ||||
|  | ||||
| upm_result_t upm_nunchuck_get_accel_values(void *dev, | ||||
|                                            float *value, | ||||
|                                            upm_acceleration_u unit) | ||||
| { | ||||
|     if (nunchuck_update((nunchuck_context)dev)) | ||||
|         return UPM_ERROR_OPERATION_FAILED; | ||||
|  | ||||
|     int x, y, z; | ||||
|     nunchuck_get_acceleration((nunchuck_context)dev, &x, &y, &z); | ||||
|     value[0] = (float)x; | ||||
|     value[1] = (float)y; | ||||
|     value[2] = (float)z; | ||||
|  | ||||
|     return UPM_SUCCESS; | ||||
| } | ||||
|  | ||||
| upm_result_t upm_nunchuck_get_joystick_value_x(const void *dev, float *value) | ||||
| { | ||||
|     // This is bad - separating getting X and Y stick values... You | ||||
|     // can't be sure when updating for one axis whether the other | ||||
|     // changed... Should be fixed by having a single function return | ||||
|     // both values from the same sampletime.  Same goes for the rest | ||||
|     // of the values reported. | ||||
|     if (nunchuck_update((nunchuck_context)dev)) | ||||
|         return UPM_ERROR_OPERATION_FAILED; | ||||
|  | ||||
|     int x; | ||||
|     nunchuck_get_stick((nunchuck_context)dev, &x, NULL); | ||||
|     *value = (float)x; | ||||
|  | ||||
|     return UPM_SUCCESS; | ||||
| } | ||||
|  | ||||
| upm_result_t upm_nunchuck_get_joystick_value_y(const void *dev, float *value) | ||||
| { | ||||
|     // This is bad - separating getting X and Y stick values... You | ||||
|     // can't be sure when updating for one axis whether the other | ||||
|     // changed... Should be fixed by having a single function return | ||||
|     // both values from the same sampletime.  Same goes for the rest | ||||
|     // of the values reported. | ||||
|     if (nunchuck_update((nunchuck_context)dev)) | ||||
|         return UPM_ERROR_OPERATION_FAILED; | ||||
|  | ||||
|     int y; | ||||
|     nunchuck_get_stick((nunchuck_context)dev, NULL, &y); | ||||
|     *value = (float)y; | ||||
|  | ||||
|     return UPM_SUCCESS; | ||||
| } | ||||
|  | ||||
| upm_result_t upm_nunchuck_get_num_buttons(const void *dev, | ||||
|                                           unsigned int *num_buttons) | ||||
| { | ||||
|     // always 2 buttons (C and Z) | ||||
|  | ||||
|     *num_buttons = 2; | ||||
|  | ||||
|     return UPM_SUCCESS; | ||||
| } | ||||
|  | ||||
| upm_result_t upm_nunchuck_get_button_values(const void *dev, | ||||
|                                             bool *values) | ||||
| { | ||||
|     if (nunchuck_update((nunchuck_context)dev)) | ||||
|         return UPM_ERROR_OPERATION_FAILED; | ||||
|  | ||||
|     bool bc, bz; | ||||
|     nunchuck_get_buttons((nunchuck_context)dev, &bc, &bz); | ||||
|     // hope they passed a bool[2].... | ||||
|     values[0] = bc; | ||||
|     values[1] = bz; | ||||
|  | ||||
|     return UPM_SUCCESS; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user
	 Jon Trulson
					Jon Trulson