[EN COURS]Attractmode & Bluetooth

Ici se règle les problèmes concernant les problèmes concernant les logiciels annexes et le matériel informatique utilisés dans votre MameBox.

Modérateurs : Porko, Modérateurs

Avatar de l’utilisateur
kaboume
noob
noob
Messages : 3
Inscription : 27 févr. 2014 - 00:00

Attractmode & Bluetooth

Message par kaboume » 08 janv. 2019 - 21:29

Bonjour,

Ayant un vieux projet de Borne d'arcade mais sans jamais avoir le WAF :? je me suis rabatue vers une autre idée.
Un raspberry avec retropie + attractmode et des stick arcade Bluetooth.
Le rasp ne ce voie pas derrière la TV et les stick Bluetooth = pas de fil :mrgreen:

Je vais pas vous donner de photo du rasp ...il ressemble aux autres.
pour le stick voila le POC (prof of concept) .. le projet :P

Image

Le dessus c'est une plaque de PVC entre 2 plaque alu laqué blanc trouvé chez le Roi Merlu ca fait 2mm d'épaisseur avec un jolie rendue.
l'interrieur .....

Image

Le boitier est constitué de 2 morceaux de goulotte electrique collé l'un à l'autre avec de la colle PVC avec le milieu partielement supprimé après collage .... Ca marche bien
Pour le dessus un morceau de couvercle de la goulotte pour l'accroche sur le profilé,couper dans la longueur et coller sur la plaque alu laqué. (j' ai mis un schema tout en bas)

On en vient a l’essentiel ...la petite carte que l on voie :shock: :shock:

Image

Adafruit NRF52 ... un module bluetooth ;)
https://learn.adafruit.com/bluefruit-nr ... troduction" onclick="window.open(this.href);return false;
En théorie tu cables, tu lui envoie un peut de code en C( c'est comme arduino ) et Hope ça doit marché en s'appuyant sur un projet très similaire.
https://learn.adafruit.com/atarifruit-2 ... ther-nrf52" onclick="window.open(this.href);return false;

Je ne parlerais pas de la prise en main de Retropie ... ont s'y perd rapidement. Sur ce point attract mode semble plus claire et accessible ...mais c'est un autre sujet.

Ma bouteille à la mer est la suivant, grosso modo le code sur adafruit fonctionne bien ..grosso modo..
En effet si je déplace le stick d'un coté et en même temps un bouton fire, une commande bloque l'autre et je doit relacher les 2 commande. En gros une commande après l 'autre OK mais plusieurs simultanés deviennent alors aléatoire l'une prend le pas sur l'autre.
Voila le code que j'ai mis dans mon adafruit ..si une bonne âme peut y jeter un Oeil ... je n'ai jamais fait de dev ni apris de language et n'ai qu une vision global du truc ;)

Code : Tout sélectionner

/*********************************************************************
AtariFruit 2600 Joystick
by John Park for Adafruit

For nRF52 Feather and Atari CX40 (2600) joystick.
Reads joystick direction and fire button, sends iCade commands over Bluetooth.

based on:
Teensy iCade Input

by Allen C. Huffman (alsplace@pobox.com)
 http://subethasoftware.com/2013/01/04/teensy-2-0-icade-source-code/

*********************************************************************/
#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

#define VERSION "0.1"
#define LED_ON
/*
iCade keyboard mappings.
See developer doc at: http://www.ionaudio.com/products/details/icade

   WE     YT UF IM OG
AQ< -->DC
   XZ     HR JN KP LV

Atari joystick port, looking at the male DB9 on the Atari.
See: http://old.pinouts.ru/Inputs/JoystickAtari2600_pinout.shtml

 1 2 3 4 5/  Up Dn Lt Rt PA
  6 7 8 9/    Bt +5  Gd PB
*/

/*
  The following I/O pins will be used as digital inputs
  for each specific iCade function.
*/
#define UP_PIN    15  // WHT
#define DOWN_PIN  7  // BLU
#define LEFT_PIN  11  // GRN
#define RIGHT_PIN 16  // BRN
#define BTN1_PIN  A0
#define BTN2_PIN  A1
#define BTN3_PIN  A2
#define BTN4_PIN  A3
#define BTN5_PIN  A4
#define BTN6_PIN  A5
#define BTN7_PIN  12
#define BTN8_PIN  13
#define OPT1_PIN  31
#define OPT2_PIN  30
#define OPT3_PIN  27

/*
  The following keys are the iCade sequence (hold, release)
  for each function. Send "W" to indicate UP, and "E" when
  UP is released.
*/
#define UP_KEYS    "us"
#define DOWN_KEYS  "ds"
#define LEFT_KEYS  "ls"
#define RIGHT_KEYS "rs"
#define BTN1_KEYS  "1b"
#define BTN2_KEYS  "2b"
#define BTN3_KEYS  "3b"
#define BTN4_KEYS  "4b"
#define BTN5_KEYS  "5b"
#define BTN6_KEYS  "6b"
#define BTN7_KEYS  "7b"
#define BTN8_KEYS  "8b"
#define OPT1_KEYS  "xo"
#define OPT2_KEYS  "yo"
#define OPT3_KEYS  "zo"

#define DI_PIN_COUNT  15   // 12 pins used.
// #define DI_PIN_START  1    // First I/O pin.
// #define DI_PIN_END    20   // Last I/O pin.

byte myPins[DI_PIN_COUNT] =  {UP_PIN, DOWN_PIN, LEFT_PIN, RIGHT_PIN, BTN1_PIN,
  BTN2_PIN, BTN3_PIN, BTN4_PIN, BTN5_PIN, BTN6_PIN, BTN7_PIN, BTN8_PIN,
  OPT1_PIN, OPT2_PIN, OPT3_PIN};

char iCadeKeymap[][DI_PIN_COUNT] =  {UP_KEYS, DOWN_KEYS, LEFT_KEYS, RIGHT_KEYS,
  BTN1_KEYS, BTN2_KEYS, BTN3_KEYS, BTN4_KEYS, BTN5_KEYS, BTN6_KEYS, BTN7_KEYS, BTN8_KEYS,
  OPT1_KEYS, OPT2_KEYS, OPT3_KEYS};

char iCadeDesc[][DI_PIN_COUNT] =  {"Up", "Down", "Left", "Right", "Btn1",
 "Btn2", "Btn3", "Btn4", "Btn5", "Btn6", "Btn7", "Btn8",
 "Opt1", "Opt2", "Opt3"};

/* We want a very short debounce delay for an arcade controller. */
#define DI_DEBOUNCE_MS 10 // 100ms (1/10th second)

#define LED_PIN 17
//#define POWER_LED 17
#define LEDBLINK_MS 1000


/* For I/O pin status and debounce. */
unsigned int  digitalStatus[DI_PIN_COUNT];          // Last set PIN mode.
unsigned long digitalDebounceTime[DI_PIN_COUNT];    // Debounce time.
//unsigned long digitalCounter[DI_PIN_COUNT];         // Times button pressed.
unsigned int  digitalDebounceRate = DI_DEBOUNCE_MS; // Debounce rate.

/* For the blinking LED (heartbeat). */
unsigned int  ledStatus = LOW;             // Last set LED mode.
unsigned long ledBlinkTime = 0;            // LED blink time.
unsigned int  ledBlinkRate = LEDBLINK_MS;  // LED blink rate.

unsigned int pinsOn = 0;


void setup()
{
  // Just in case it was left on...
  //wdt_disable();

  // Initialize the serial port.
  Serial.begin(115200);
  Serial.println();
  Serial.println("Go to your phone's Bluetooth settings to pair your device");
  Serial.println("then open an application that accepts keyboard input");
  Bluefruit.begin();
  // Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
  Bluefruit.setTxPower(4);
  Bluefruit.setName("Stick_Droite");

  // Configure and Start Device Information Service
  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Atari Fruit Joystick 52");
  bledis.begin();

  /* Start BLE HID
   * Note: Apple requires BLE device must have min connection interval >= 20m
   * ( The smaller the connection interval the faster we could send data).
   * However for HID and MIDI device, Apple could accept min connection interval
   * up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
   * connection interval to 11.25  ms and 15 ms respectively for best performance.
   */
  blehid.begin();

  /* Set connection interval (min, max) to your perferred value.
   * Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
   * min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
   */
  /* Bluefruit.setConnInterval(9, 12); */

  // Set up and start advertising
  startAdv();

  // Docs say this isn't necessary for Uno.
  //while(!Serial) { }

  showHeader();

  // Initialize watchdog timer for 2 seconds.
  //wdt_enable(WDTO_4S);

  // LOW POWER MODE!
  // Pins default to INPUT mode. To save power, turn them all to OUTPUT
  // initially, so only those being used will be turn on. See:
  // http://www.pjrc.com/teensy/low_power.html
  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    pinMode(thisPin, OUTPUT);
  }

  // Disable Unused Peripherals
 // ADCSRA = 0;

  // Initialize the pins and digitalPin array.
  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Set pin to be digital input using pullup resistor.
    pinMode(myPins[thisPin], INPUT_PULLUP);
    // Set the current initial pin status.
    digitalStatus[thisPin] = HIGH; //digitalRead(thisPin+DI_PIN_START);
    // Clear debounce time.
    digitalDebounceTime[thisPin] = 0;
    //digitalCounter[thisPin] = 0;
  }

  // Set LED pin to output, since it has an LED we can use.
  pinMode(LED_PIN, OUTPUT);
  // pinMode(POWER_LED, OUTPUT);
  // digitalWrite(POWER_LED, HIGH);

  Serial.println("Ready.");

}


void startAdv(void)
{
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);

  // Include BLE HID service
  Bluefruit.Advertising.addService(blehid);

  // There is enough room for the dev name in the advertising packet
  Bluefruit.Advertising.addName();

  /* Start Advertising
   * - Enable auto advertising if disconnected
   * - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
   * - Timeout for fast mode is 30 seconds
   * - Start(timeout) with timeout = 0 will advertise forever (until connected)
   *
   * For recommended advertising interval
   * https://developer.apple.com/library/content/qa/qa1931/_index.html
   */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds
}


void loop()
{
  // Tell the watchdog timer we are still alive.
  //wdt_reset();

#ifndef LED_OFF
  // LED blinking heartbeat. Yes, we are alive.
  if ( (long)(millis()-ledBlinkTime) >= 0 )
  {
    // Toggle LED.
    if (ledStatus==LOW)  // If LED is LOW...
    {
      ledStatus = HIGH;  // ...make it HIGH.
    } else {
      ledStatus = LOW;   // ...else, make it LOW.
    }
    // Set LED pin status.
    if (pinsOn==0) digitalWrite(LED_PIN, ledStatus);
    // Reset "next time to toggle" time.
    ledBlinkTime = millis()+ledBlinkRate;
  }
#endif

  // Check for serial data.
  if (Serial.available() > 0) {
    // If data ready, read a byte.
    int incomingByte = Serial.read();
    // Parse the byte we read.
    switch(incomingByte)
    {
      case '?':
        showStatus();
        break;
      default:
        break;
    }
  }


  // Loop through each Digital Input pin.
  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Read the pin's current status.
    unsigned int status = digitalRead(myPins[thisPin]);

    // In pin status has changed from our last toggle...
    if (status != digitalStatus[thisPin])
    {
      blehid.keyRelease();
      // Remember when it changed, starting debounce mode.
      // If not currently in debounce mode,
      if (digitalDebounceTime[thisPin]==0)
      {
        // Set when we can accept this as valid (debounce is considered
        // done if the time gets to this point with the status still the same).
        digitalDebounceTime[thisPin] = millis()+digitalDebounceRate;
      }

      // Check to see if we are in debounce detect mode.
      if (digitalDebounceTime[thisPin]>0)
      {
        // Yes we are. Have we delayed long enough yet?
        if ( (long)(millis()-digitalDebounceTime[thisPin]) >= 0 )
        {
            // Yes, so consider it switched.
            // If pin is Active LOW,
            if (status==LOW)
            {
              // Emit BUTTON PRESSED string.
              Serial.print(iCadeDesc[thisPin]);
              Serial.print(" pressed  (sending ");
              Serial.print(iCadeKeymap[thisPin][0]);
              Serial.println(" to iCade).");
              blehid.keyPress(iCadeKeymap[thisPin][0]);
              //Keyboard.print(iCadeKeymap[thisPin][0]);
              //digitalCounter[thisPin]++;
              pinsOn++;
#ifndef LED_OFF
              digitalWrite(LED_PIN, HIGH);
#endif
            } else {
              // Emit BUTTON RELEASED string.
              Serial.print(iCadeDesc[thisPin]);
              Serial.print(" released (sending ");
              Serial.print(iCadeKeymap[thisPin][1]);
              Serial.println(" to iCade).");
              //blehid.keyPress(iCadeKeymap[thisPin][1]); //comment to stop send unecesary release 
              //Keyboard.print(iCadeKeymap[thisPin][1]);
              if (pinsOn>0) pinsOn--;
              if (pinsOn==0) digitalWrite(LED_PIN, LOW);
            }
            // Remember current (last set) status for this pin.
            digitalStatus[thisPin] = status;
            // Reset debounce time (disable, not looking any more).
            digitalDebounceTime[thisPin] = 0;
        } // End of if ( (long)(millis()-digitalDebounceTime[thisPin]) >= 0 )

      } // End of if (digitalDebounceTime[thisPin]>0)
    }
    else // No change? Flag no change.
    {
      // If we were debouncing, we are no longer debouncing.
      digitalDebounceTime[thisPin] = 0;
    }
  } // End of (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )

  // Request CPU to enter low-power mode until an event/interrupt occurs
  waitForEvent();
}

void showHeader()
{
  int i;
  // Emit some startup stuff to the serial port.
  Serial.println("Atari 2600 BlueCade by John Park for Adafruit. ");
  Serial.print("Based on: iCadeTeensy ");
  Serial.print(VERSION);
  Serial.println(" by Allen C. Huffman (alsplace@pobox.com)");
  Serial.print(DI_PIN_COUNT);
  Serial.print(" DI Pins (");
  for (i=0; i<DI_PIN_COUNT; i++)
  {
    Serial.print(myPins[i]);
    Serial.print("=");
    Serial.print(iCadeDesc[i]);
    Serial.print(" ");
  }
  Serial.print("), ");
  Serial.print(digitalDebounceRate);
  Serial.println("ms Debounce.");
}


void showStatus()
{
  showDigitalInputStatus();
}


void showDigitalInputStatus()
{
  Serial.print("DI: ");

  for (int thisPin=0; thisPin < DI_PIN_COUNT; thisPin++ )
  {
    // Read the pin's current status.
    Serial.print(iCadeDesc[thisPin]);
    Serial.print("=");
    Serial.print(digitalRead(myPins[thisPin]));
    Serial.print(" ");
    //Serial.print(" (");
    //Serial.print(digitalCounter[thisPin]);
    //Serial.print(") ");
  }
  Serial.println("");
}

/**
 * RTOS Idle callback is automatically invoked by FreeRTOS
 * when there are no active threads. E.g when loop() calls delay() and
 * there is no bluetooth or hw event. This is the ideal place to handle
 * background data.
 *
 * NOTE: FreeRTOS is configured as tickless idle mode. After this callback
 * is executed, if there is time, freeRTOS kernel will go into low power mode.
 * Therefore waitForEvent() should not be called in this callback.
 * http://www.freertos.org/low-power-tickless-rtos.html
 *
 * WARNING: This function MUST NOT call any blocking FreeRTOS API
 * such as delay(), xSemaphoreTake() etc ... for more information
 * http://www.freertos.org/a00016.html
 */
void rtos_idle_callback(void)
{
  // Don't call any other FreeRTOS blocking API()
  // Perform background task(s) here
}
// End of file.
Comme promis un schema de ma boite joystick :)

Image

Ma bouteille est à l 'eau au pire peut être que cela donnera des idées pour les autres :mrgreen:

Bonne soirée

Avatar de l’utilisateur
Funkychild
Mentor
Mentor
Messages : 2501
Inscription : 13 déc. 2014 - 21:39
A remercié : 342 fois
A été remercié : 629 fois

Re: Attractmode & Bluetooth

Message par Funkychild » 08 janv. 2019 - 22:06

Ca fait un stick au design très épuré, sympa.

Le socle est on ne peut plus original :D

Répondre

Revenir à « Aide Hardware et Software »