うおーるぼっとをWiiリモコンでコントロールする新しいプログラムです。 以前のものより、Wiiリモコンが早く繋がる様になりました。 It is a program which controls A with the Wii remote. ※ A Bluetooth dongle and a Wii remote control are needed.

Dependencies:   USBHost mbed FATFileSystem mbed-rtos

Revision:
0:fccb789424fc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jun 10 16:01:50 2013 +0000
@@ -0,0 +1,382 @@
+
+#include "mbed.h"
+#include <btstack/hci_cmds.h>
+#include <btstack/run_loop.h>
+#include <btstack/sdp_util.h>
+#include "hci.h"
+#include "l2cap.h"
+#include "btstack_memory.h"
+#include "remote_device_db.h"
+#include "rfcomm.h"
+extern "C" {
+#include "sdp.h"
+}
+#include "config.h"
+#include "debug.h"
+#include "bd_addr.h"  // class bd_addr
+
+#include "Wiimote.h"
+#include "TB6612.h"
+
+// ----- Wallbot I/O Setting ----- 
+// Motor
+TB6612 right(p21,p12,p11);
+TB6612 left(p22,p14,p13);
+
+#define WII_REMOTE_CONNECTION_SYNC    0        // 0:old Wii Remote 1:New Wii Remote
+#define REPORTMODE_TT_BIT           0x00
+#define WII_REMOTE_REPORT_MODE       0x31
+#define MAX_SPEED 100
+
+#define HEARTBEAT_PERIOD_MS     1000
+#define INQUIRY_INTERVAL          15
+
+Serial pc(USBTX, USBRX);
+DigitalOut ActLED(LED1);
+
+
+
+static bd_addr_t keyboard;
+static int haveKeyboard = 0;
+static char                     lineBuffer[80];
+static short wii_remocon_channel_id=0;
+
+int DirectMode( Wiimote* wii, int stat )
+{
+    
+    if( wii->left )
+    {
+        right = -MAX_SPEED;
+        left = MAX_SPEED;
+    }
+    else if( wii->right )
+    {
+        right = MAX_SPEED;
+        left = -MAX_SPEED;
+    }    
+    else if( wii->up )
+    {
+        right = MAX_SPEED;
+        left = MAX_SPEED;
+    }
+    else if( wii->down )
+    {
+        right = -MAX_SPEED;
+        left = -MAX_SPEED;
+    }
+    else
+    {
+        right = 0;
+        left = 0;
+    }
+    
+    float factor = wii->wheel * 1.5f;
+    
+    if(factor > 100.0f )    factor = 100.0f; 
+    if(factor < -100.0f )    factor = -100.0f;
+    
+    printf("%f\t%f\r\n",wii->wheel,factor);
+    
+    int left_factor = (int)((factor <= 0.0) ? 100.0 : 100.0 - factor);
+    int right_factor = (int)((factor >= 0.0) ? 100.0 : 100.0 - (-factor));
+    
+    if( wii->one )
+    {
+        right = right_factor;
+        left = left_factor;
+    }
+    if( wii->two )
+    {
+        right = -left_factor;
+        left = -right_factor;
+    }
+    
+    return(stat);
+}
+
+int wall_bot_remote(char *c)
+{
+    Wiimote wii;
+    int ret = 0;
+    
+    wii.decode(c);
+    
+    ret = DirectMode( &wii ,ret );
+    
+    return(ret);
+}
+
+void wii_remote_report_mode(uint16_t channel,uint8_t tt,uint8_t mm)
+{
+    lineBuffer[0]=0xa2;
+    lineBuffer[1]=0x12;
+    lineBuffer[2]=tt;
+    lineBuffer[3]=mm;
+    l2cap_send_internal(channel,(uint8_t*)lineBuffer,4);
+}
+
+void wii_remote_request_status_report(uint16_t channel)
+{
+    lineBuffer[0]=0xa2;
+    lineBuffer[1]=0x15;
+    lineBuffer[2]=0x00;
+    l2cap_send_internal(channel,(uint8_t*)lineBuffer,3);
+}
+
+void hid_process_packet(uint16_t channel,unsigned char *hid_report,uint16_t size)
+{
+    if(hid_report[0]!=0xa1){
+        return;
+    }
+
+    if(hid_report[1]==0x30){
+        wii_remote_report_mode(channel,REPORTMODE_TT_BIT,WII_REMOTE_REPORT_MODE);
+        wii_remote_request_status_report(channel);
+    }
+
+    switch(hid_report[1]){
+    case    0x30:                                    //0x30:Core Buttons
+    case    0x31:                                    //0x31:Core Buttons and Accelerometer
+    case    0x35:                                    //0x35:Core Buttons and Accelerometer with 16 Extension Bytes
+        wall_bot_remote( (char*)&hid_report[2] );
+        break;
+    default:
+        break;
+    }
+    return;
+}
+
+static void l2cap_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
+{
+    if (packet_type == HCI_EVENT_PACKET){
+        switch(packet[0]){
+        case L2CAP_EVENT_INCOMING_CONNECTION:
+            log_info("L2CAP_EVENT_INCOMING_CONNECTION\n");
+            l2cap_accept_connection_internal(channel);
+            break;
+        case L2CAP_EVENT_CHANNEL_OPENED:
+            if (packet[2]) {
+                log_info("Connection failed\n");
+                return;
+            }
+            log_info("interrupt channel connected\n");
+            wii_remocon_channel_id=channel;
+             break;
+        case L2CAP_EVENT_CHANNEL_CLOSED:
+            wii_remocon_channel_id=0;
+        //    use_extension=0;
+            haveKeyboard = 0;
+            hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
+            break;
+        default:
+            break;
+        }    
+    }
+    if (packet_type == L2CAP_DATA_PACKET){
+        hid_process_packet(channel,packet,size);
+    }
+}
+
+//static uint16_t control_channel=0;
+static void l2cap_control_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
+{
+    if (packet_type == HCI_EVENT_PACKET){
+        switch(packet[0]){
+        case L2CAP_EVENT_INCOMING_CONNECTION:
+            log_info("L2CAP_EVENT_INCOMING_CONNECTION\n");
+            l2cap_accept_connection_internal(channel);
+            break;
+        case L2CAP_EVENT_CHANNEL_OPENED:
+            if (packet[2]) {
+               // xputs("control Connection failed\n");
+                return;
+            }
+          //  xputs("control channel connected\n");
+            l2cap_create_channel_internal(NULL, l2cap_packet_handler, keyboard, PSM_HID_INTERRUPT, 150);
+            //control_channel=channel;
+            break;
+        case L2CAP_EVENT_CHANNEL_CLOSED:
+            log_info("L2CAP_CHANNEL_CLOSED\n");
+            //control_channel=0;
+            break;
+        case L2CAP_EVENT_CREDITS:
+            break;
+        default:
+            log_info("l2cap:unknown(%02x)\n",packet[0]);
+            break;
+        }    
+    }
+}
+
+// Bluetooth logic
+static void packet_handler (void * connection, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
+    bd_addr_t event_addr;
+    
+    switch (packet_type) {
+        case HCI_EVENT_PACKET:
+            switch (packet[0]) {
+                case BTSTACK_EVENT_STATE:
+                    // bt stack activated, get started - set local name
+                    if (packet[2] == HCI_STATE_WORKING) {
+                        hci_send_cmd(&hci_write_local_name, "mbed");
+                    }
+                    break;
+                
+                case HCI_EVENT_COMMAND_COMPLETE:
+                    if (COMMAND_COMPLETE_EVENT(packet, hci_read_bd_addr)){
+                        bt_flip_addr(event_addr, &packet[6]);
+                        log_info("BD-ADDR: %s\n", bd_addr_to_str(event_addr));
+                        break;
+                    }
+                    if (COMMAND_COMPLETE_EVENT(packet, hci_write_local_name)){
+//                        hci_discoverable_control(1);
+//                        hci_send_cmd(&hci_write_authentication_enable, 1);
+                        hci_send_cmd(&hci_write_authentication_enable, 0);
+                        break;
+                    }
+                    if (COMMAND_COMPLETE_EVENT(packet, hci_write_authentication_enable)){
+                    inquiry:
+
+                        log_info("Inquiry\n");
+                        hci_send_cmd(&hci_inquiry, HCI_INQUIRY_LAP, INQUIRY_INTERVAL, 0);
+
+                        break;
+                    }
+                    if (COMMAND_COMPLETE_EVENT(packet, hci_inquiry_cancel) ) {
+                        //l2cap_create_channel_internal(NULL, l2cap_packet_handler, keyboard, PSM_HID_INTERRUPT, 150);
+                        l2cap_create_channel_internal(NULL, l2cap_control_packet_handler, keyboard, PSM_HID_CONTROL, 150);
+                        break;
+                    }
+                    break;
+                case HCI_EVENT_INQUIRY_RESULT:
+                    
+                    // ignore further results
+                    if (haveKeyboard) break;
+                    
+                    // ignore none wii remocon
+                    if(
+                        !(packet[12]==0x04 && packet[13]==0x25 && packet[14]==0x00)
+                    &&    !(packet[12]==0x08 && packet[13]==0x05 && packet[14]==0x00)    //RVL-CNT-01-TR
+                    ){
+                        break;
+                    }
+
+                    // flip addr
+                    bt_flip_addr(keyboard, &packet[3]);
+                    
+                    // show
+                    log_info("found wii remocon:%s\n",bd_addr_to_str(keyboard));
+
+                    haveKeyboard = 1;
+                    hci_send_cmd(&hci_inquiry_cancel);
+                    break;
+                    
+                case HCI_EVENT_INQUIRY_COMPLETE:
+                    log_info("No wii remocon\n");
+                    goto inquiry;
+                    //break;
+                case HCI_EVENT_LINK_KEY_REQUEST:
+                    // deny link key request
+                    log_info("Link key request\n");
+                    bt_flip_addr(event_addr, &packet[2]);
+                    hci_send_cmd(&hci_link_key_request_negative_reply, &event_addr);
+                    break;
+                    
+                case HCI_EVENT_PIN_CODE_REQUEST:
+                    // inform about pin code request
+                    bt_flip_addr(event_addr, &packet[2]);
+                    //wii remocon
+#if    WII_REMOTE_CONNECTION_SYNC
+                    bt_flip_addr(packet+2, addr_global);
+#endif
+                    log_info("Pin code request - using %02x%02x%02x%02x%02x%02x\n",packet[2],packet[3],packet[4],packet[5],packet[6],packet[7]);
+                    memset(packet+2+6,0x00,10);
+                    hci_send_cmd(&hci_pin_code_request_reply, &event_addr, 6, &packet[2]);
+                    break;
+                case HCI_EVENT_CONNECTION_COMPLETE:
+                    //log_info("connection complete: status=%d\n",packet[2]);
+                    if(packet[2]){
+                        haveKeyboard=0;
+                        goto inquiry;
+                    }
+                    break;
+                default:
+                    break;
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+static void  heartbeat_handler(struct timer *ts){
+    static int counter = 0;
+    counter++;
+
+    if(wii_remocon_channel_id){
+        lineBuffer[0]=0xa2;
+        lineBuffer[1]=0x11;
+        lineBuffer[2]=0x10<<(counter%4);        //LED Player1
+        if(l2cap_send_internal(wii_remocon_channel_id,(uint8_t*)lineBuffer,3)<0){
+            //error control init
+        }
+       ActLED = !ActLED;
+    }
+    run_loop_set_timer(ts, HEARTBEAT_PERIOD_MS);
+    run_loop_add_timer(ts);
+} 
+
+// main
+int main(void)
+{
+    pc.baud(921600);
+    log_info("%s\n", __FILE__);
+
+    // init LEDs
+    ActLED = 0;
+    
+    /// GET STARTED with BTstack ///
+    btstack_memory_init();
+    run_loop_init(RUN_LOOP_EMBEDDED);
+    
+    // init HCI
+    hci_transport_t* transport = hci_transport_usb_instance();
+    remote_device_db_t * remote_db = (remote_device_db_t *) &remote_device_db_memory;
+    hci_init(transport, NULL, NULL, remote_db);
+    
+    // init L2CAP
+    l2cap_init();
+    l2cap_register_packet_handler(packet_handler);
+    
+#if 0
+    // init RFCOMM
+    rfcomm_init();
+    rfcomm_register_packet_handler(packet_handler);
+    rfcomm_register_service_internal(NULL, rfcomm_channel_nr, 100);  // reserved channel, mtu=100
+
+
+    // init SDP, create record for SPP and register with SDP
+    sdp_init();
+    memset(spp_service_buffer, 0, sizeof(spp_service_buffer));
+    service_record_item_t * service_record_item = (service_record_item_t *) spp_service_buffer;
+    sdp_create_spp_service( (uint8_t*) &service_record_item->service_record, 1, "loopback");
+    log_info("SDP service buffer size: %u\n\r", (uint16_t) (sizeof(service_record_item_t) + de_get_len((uint8_t*) &service_record_item->service_record)));
+    sdp_register_service_internal(NULL, service_record_item);
+#endif
+    
+    // set one-shot timer
+    timer_source_t heartbeat;
+    heartbeat.process = &heartbeat_handler;
+    run_loop_set_timer(&heartbeat, HEARTBEAT_PERIOD_MS);
+    run_loop_add_timer(&heartbeat);
+    
+    log_info("SPP loopback demo...\n\r");
+
+     // turn on!
+    hci_power_control(HCI_POWER_ON);
+
+    // go!
+    run_loop_execute();    
+
+    return 0;
+}