Steuerung via Blackberry Trackball (Achims Blackberry Build)

Gleich vorweg: Es gibt reichlich wenig Verwendung für eine Maus im Retropie Umfeld (zumindest auf einem ZeroBoy)…aber es gibt eben auch Day oft the Tentacle.
Nach diversen Tests mit den Sensoren einer optischen Maus bzw. einer alten analogen USB Maus bin ich am Ende über den Blackberry Trackball gestolpert. Diese Anleitung beschreibt wie das ganze Realisiert wurde.

http://goo.gl/sjuYAh   (AliExpress Link)

http://www.sparkfun.com/products/13169

adapter

Als Board kommt ein TeensyLC zum Einsatz. Die bereits verwendeten 11 Pins für die Tastensteuerung sowie die benötigten 9 Pins für den Trackball  plus einen Pin für die Möglichkeit einen „Rechtsklick“ zu realisieren, haben noch 4 Pins übriggelassen, die ich zur dynamischen Beleuchtung der ABXY Tasten verwendet habe. Den teensy sollte man nicht hart verlöten, sondern per Stecker anschließen, damit man einfach Änderungen am Quellcode machen kann.

 

bbbuild

 

Hier sieht man das 5mm Loch für den Trackball und die Verdünnung des Cases um gut 1 mm, damit der Trackball etwas heraussteht.
Man kann aber auch einfach ein 7mm großes Loch verwenden.

bbbuild2

bbbuild3

Der fertig bestückte TeensyLC mit dem Trackball. Am Trackball muss man eine Ecke wegdremeln, damit er sauber in die untere linke Ecke passt.

bbbuild4

Die finale Verkabelung ist in diesem Beispiel etwas chaotisch ausgefallen. USB Hub, USB Sound, TeensyLC, Trackball, Verstärker, zwei Platinen für die Akkuanzeige (Das Steuerkreuz dient als Akkuanzeige) erzeugen leider etwas Kabelsalat.

 

Die ABXY Knöpfe werden beim Drücken für ca. 0.5 Sekunden beleuchtet.

bbbuild5

bbbuild6

 

Pin Funktion
0 Links
1 Hoch
2 Runter
3 Rechts
4 Escape à SELECT
5 Enter à START
6 X
7 Y
8 “F5” (Menü in Day of the Tentacle) à B
9 A
10 L
11 R
12 LED A Knopf
13 Blackberry Click
14 Rechte Maustaste
15 Blackberry UP
16 Blackberry DOWN
17 Blackberry VCC
18 Blackberry RIGHT
19 Blackberry UP
20 Weiße Blackberry LED
21 Grüne Blackberry LED
22 Blaue Blackberry LED
23 Rote Blackberry LED
24 LED für B Knopf
25 LED für X Knopf
26 LED für Y Knopf

Und hier der Code für den Teensy/ATMega32U4 im  “Tastatur, Maus, Joystick” Modus

 

#include <Bounce.h>

 

#define NUM_KEYS 12

const int moveDistance = 15;  // how much should the mouse move on each button press

const int redPin =  23;       // pin for red Blackberry LED

const int bluePin =  22;      // pin for blue Blackberry LED

const int greenPin =  21;     // pin for blue Blackberry LED

const int whitePin =  20;     // pin for white Blackberry LED

 

const int ledApin =  12;      // pin for A Button LED

const int ledBpin =  24;      // pin for B Button LED

const int ledXpin =  25;      // pin for X Button LED

const int ledYpin =  26;      // pin for Y Button LED

 

const int mouse_screen_X = 320;  // Screen resolution horizontal

const int mouse_screen_Y = 240;  // Screen resolution vertical

 

const int blackberry_light_duration =  25000; // how long should the Blackberry Ball glow?

const int blackberry_click_max_time = 60000;  // how long do you have time to input the clicks for lights ON/OFF

const int led_button_light_duration = 5000;   // how long should the ABXY Button LEDs glow?

 

int blackberry_light_mode = 1;                // lights ON or OFF ?

int blackberry_click_count = 0;               // counter for clicks within blackberry_click_max_time

int blackberry_click_time = 0;                // "time" counter for x clicks.

int blackberry_clicks_needed = 5;             // 5 clicks for turning lights ON/OFF

int ired = 1;                                 // time counter for RED BALL LED  

int iblue = 1;                                // time counter for BLUE BALL LED

int igreen = 1;                               // time counter for GREEN BALL LED

int iwhite = 1;                               // time counter for WHITE BALL LED

 

int ledAcounter = 0;

int ledBcounter = 0;

int ledXcounter = 0;

int ledYcounter = 0;

 

 

struct Key {

  int keycode;

  Bounce* bounce;

};

 

 

// 2 mousebuttons

Bounce mbuttonl = Bounce(13, 50); // pin 13 left click

Bounce mbuttonr = Bounce(14, 50); // pin 14 right click

 

// 4 directions for mouse

Bounce mup = Bounce(19, 20);  // UP

Bounce mdown = Bounce(16, 20); // DOWN

Bounce mleft = Bounce(15, 20); // LEFT

Bounce mright = Bounce(18, 20); // RIGHT

 

 

Key keys[NUM_KEYS];

 

Key key(int keycode, int pin) {

  Key *ret = new Key;

  ret->keycode = keycode;

  ret->bounce = new Bounce(pin, 50);

  pinMode(pin, INPUT_PULLUP);

  return *ret;

}

 

void setupKeys() {

  keys[0] = key(KEY_LEFT_ARROW, 0);   // left

  keys[1] = key(KEY_UP_ARROW, 1);     // up

  keys[2] = key(KEY_DOWN_ARROW, 2);   // down

  keys[3] = key(KEY_RIGHT_ARROW, 3);  // right

  keys[4] = key(KEY_ESC, 4);     // select

  keys[5] = key(KEY_RETURN, 5);  //start

  keys[6] = key('x', 6);         // using ESC for retropie menu

  keys[7] = key('y', 7);         // using for retropie menu

  keys[8] = key(KEY_F5, 8);      // B - workaround for Day of Tentacle F5 for Menu

  keys[9] = key('a', 9);         // A

  keys[10] = key('l',10);        // left button

  keys[11] = key('r',11);        // right button

  }

 

void setup() {

  setupKeys();

   // mouse setup

  pinMode(13, INPUT_PULLUP);

  pinMode(14, INPUT_PULLUP);

  pinMode(15, INPUT_PULLUP);

  pinMode(16, INPUT_PULLUP);

  pinMode(18, INPUT_PULLUP);

  pinMode(19, INPUT_PULLUP);

  pinMode(redPin, OUTPUT);

  pinMode(bluePin, OUTPUT);

  pinMode(greenPin, OUTPUT);

  pinMode(whitePin, OUTPUT);

  pinMode(ledApin, OUTPUT);

  pinMode(ledBpin, OUTPUT);

  pinMode(ledXpin, OUTPUT);

  pinMode(ledYpin, OUTPUT);

 

  //Mouse.screenSize(1920, 1080);

  Mouse.screenSize(mouse_screen_X, mouse_screen_Y);

 

  Keyboard.begin();

}

 

void loop() {

  for (int i = 0; i < NUM_KEYS; i++) {

    keys[i].bounce->update();

    if (keys[i].bounce->fallingEdge()) {

      Keyboard.press(keys[i].keycode);

      // hard-coded ABXY Buttons for LEDs

      if ( i == 6 && blackberry_light_mode > 0 ) { digitalWrite(ledXpin, HIGH); } // X button pressed --> turn on button LED

      if ( i == 7 && blackberry_light_mode > 0 ) { digitalWrite(ledYpin, HIGH); } // Y button pressed --> turn on button LED

      if ( i == 8 && blackberry_light_mode > 0 ) { digitalWrite(ledBpin, HIGH); } // B button pressed --> turn on button LED

      if ( i == 9 && blackberry_light_mode > 0 ) { digitalWrite(ledApin, HIGH); } // A button pressed --> turn on button LED

     } else if (keys[i].bounce->risingEdge()) {

      Keyboard.release(keys[i].keycode);

    }

  }

 

 

  // ++++++++++++++mouse++++++++++++++

 

  // #################################

  // # turn off red Blackberry LEDs  #

  // #################################

  if (ired >=2 ){ired = ired + 1;}  // if led is on "count time"

  if (ired >= blackberry_light_duration){  // if max_time is reached -> counter reset, turn LED OFF

     ired = 1;                             // reset counter

     digitalWrite(redPin, LOW);            // switch off

     }

  // turn off blue Blackberry LED   

  if (iblue >=2 ){iblue = iblue + 1;} 

  if (iblue >= blackberry_light_duration){

     iblue = 1;                      // switch off

     digitalWrite(bluePin, LOW);

     }

  if (igreen >=2 ){igreen = igreen + 1;}  // if led is on "count time"

  if (igreen >= blackberry_light_duration){

     igreen = 1;                      // switch off

     digitalWrite(greenPin, LOW);

     }

  if (iwhite >=2 ){iwhite = iwhite + 1;}  // if led is on "count time"

  if (iwhite >= blackberry_light_duration){

     iwhite = 1;                      // switch off

     digitalWrite(whitePin, LOW);

     }

 

  // #################################

  // # turn off ABXY Button LEDs    #

  // #################################

   if ( ledAcounter > led_button_light_duration || blackberry_light_mode < 0 ){

        digitalWrite(ledApin, LOW);   // turn off A pin

   }

   if ( ledBcounter > led_button_light_duration || blackberry_light_mode < 0 ){

        digitalWrite(ledBpin, LOW);   // turn off B pin

   }

   if ( ledXcounter > led_button_light_duration || blackberry_light_mode < 0 ){

        digitalWrite(ledXpin, LOW);   // turn off X pin

   }

   if ( ledYcounter > led_button_light_duration || blackberry_light_mode < 0 ){

        digitalWrite(ledYpin, LOW);   // turn off Y pin

   }

 

  // ####### READ MOUSE BUTTONS ###########  

  mup.update();

  mdown.update();

  mleft.update();

  mright.update();

  mbuttonl.update();

  mbuttonr.update();

 

   if (mleft.fallingEdge()) {

    Mouse.move(-moveDistance, 0); // move Left

    if (blackberry_light_mode > 0) { digitalWrite(redPin, HIGH); }

    ired = 2;

  }

  if (mright.fallingEdge()) {

    Mouse.move(moveDistance, 0);  // move Right

    if (blackberry_light_mode > 0) { digitalWrite(greenPin, HIGH); }

    igreen = 2;

  }

  if (mup.fallingEdge()) {

    Mouse.move(0, -moveDistance); // move Up

    if (blackberry_light_mode > 0) { digitalWrite(bluePin, HIGH); }

    iblue = 2;

  }

  if (mdown.fallingEdge()) {

    Mouse.move(0, moveDistance);  // move Down

    if (blackberry_light_mode > 0) { digitalWrite(whitePin, HIGH); }

    iwhite = 2;

  }

 

 

 // For the mouse buttons, we must detect both the falling and rising edges,

  // to press the mouse button when the button on our digital pin is pressed,

  // and to later release it when the physical button releases (the pin rises

  // from low back to high, thanks to INPUT_PULLUP).

 

 if (mbuttonl.fallingEdge()) {

    Mouse.press(MOUSE_LEFT);

 

    delay(100); // reduce bouncing as primitive solution.

    blackberry_click_count = blackberry_click_count + 1;

    if (blackberry_click_count == 1) {

       blackberry_click_time = 1;  // start timer on first click.

       }

     if (blackberry_click_count >= 5) { // now turn off / on the lights

      blackberry_light_mode = blackberry_light_mode * -1;

      } 

 

  }

  if (mbuttonl.risingEdge()) {

    Mouse.release(MOUSE_LEFT);

  }

 

 if (mbuttonr.fallingEdge()) {

    Mouse.press(MOUSE_RIGHT);

  }

  if (mbuttonr.risingEdge()) {

    Mouse.release(MOUSE_RIGHT);

  }

  // check the click count time for x clicks to activate LIGHT

  if ( blackberry_click_time >= 1){                            // timer is started on first click

    blackberry_click_time = blackberry_click_time + 1;         // add 1 cycle

    if (blackberry_click_time > blackberry_click_max_time) {   // if max duration is reached --> reset timer and clicks

      blackberry_click_time = 0;                               // reset timer for x clicks.

      blackberry_click_count = 0;                              // reset click counter

      }

    }

 

   // LED fuer Buttons schalten

 if (blackberry_light_mode > 0) {

        digitalWrite(ledApin, HIGH);   // hier A

        digitalWrite(ledBpin, HIGH);   // hier B

           // hier X

        digitalWrite(ledYpin, HIGH);   // hier Y

 

    }

 

}

bbbuildtitle
Letzte Worte:

Zur Zeit ist der Teensy mit “f5” noch speziell für Day of Tentacle eingerichtet, hier muss ich noch schauen, wie man in SCRUMMVM eine halbwegs einheitliche Steuerung hinterlegen kann. Damit man den teensy jederzeit umprogrammieren kann, sollte man USB nicht fest verlöten, sondern mit einem Stecker versehen!

Die Maus wird sehr gut erkannt und funktioniert auch unter PIXEL. Auf einem 640er bzw HDMI screen kann man sogar bequem surfen und die Desktop Oberfläche nutzen!

Vielen Dank an Achim für die tolle Anleitung!

Diese Seite verwendet Cookies für ein besseres Surferlebnis. Durch das Browsen auf dieser Website stimmst du der Verwendung von Cookies zu.