Quiero controlar el DexDrive

Iniciado por Meta, 23 Diciembre 2015, 12:48 PM

0 Miembros y 2 Visitantes están viendo este tema.

Meta

Hola:

Antes que nada, disculpen si esto no va aquí. Llevo un tiempo averguando como se controla el famoso y popular de la época de piedra el DexDrive con Visual Studio. Es un dispositivo que lee y guarda los datos de la Memory Card de la PlayStation 1 en el PC por puerto serie, lo que se usaba mucho en la época de antes.



Lo he desarmado.



Tiene un Led verde, cuando envia o recibe datos, se cambia a naranja, todo esto con el puerto COM1. Si no ejecutas su aplicación llamado DeXplorer 2.0.920, no funciona nada aunque lo tengas alimentado, me refiero el Led. Sospecho que usa RTS, CTS, DTR, etc. A parte de los Rx, Tx y GND.

Aquí encontré una aplicación o código fuente que no entiendo ni papa y quiero adaptarlo a Visual C#, más bien hacer una interfaz como el DexPlorer, al menos más moderno. Lo curioso que DeXplorer sabe cuando está conectado el dispositivo DexDrive, si tiene la Memory Card insertada o no.

Tal vez aquí me indique como hacerlo.
https://github.com/fbriere/linux-dexdrive/blob/master/protocol.txt

Esos códigos quiero de C, que por eso lo he puesto aquí, pasarlo a Visual C#. El diseño lo tengo hecho, solo el diseño, no la programación.

He intentado hacer caso esta parte en Visual C#.
CitarCOMMANDS
--------

 For all commands specifying a (16-bit) frame number, <lsb> and <msb> are,
 respectively, its least and most significant bytes.  Make sure to pay close
 attention to the order, as it varies between commands.

 Note that the Nintendo 64 DexDrive will get stuck if it is sent an
 incomplete command.  At that point, the only solution is to unplug it
 completely, and plug it back (power first, then serial).

0x00  INIT

 Args: <17 bytes>
 Reply: ID

 Initializes the DexDrive; see the POUTING section below.

 The contents of the 17 bytes does not appear to have any significance,
 except for determining the contents of the "weird" byte in the ID reply.
 See the WEIRD FORMULA section below for more details.

 InterAct's DexPlorer software uses the following hard-coded string:

    10 29 23 be 84 e1 6c d6 ae 52 90 49 f1 f1 bb e9 eb

Enviar esos 17 bytes pero no pasa nada.

       private void button6_Click(object sender, EventArgs e)
       {
           byte[] mBuffer = new byte[17];
           mBuffer[0] = 0x10;
           mBuffer[1] = 0x29;
           mBuffer[2] = 0x23;
           mBuffer[3] = 0xBE;
           mBuffer[4] = 0x84;
           mBuffer[5] = 0xE1;
           mBuffer[6] = 0x6C;
           mBuffer[7] = 0xD6;
           mBuffer[8] = 0xAE;
           mBuffer[9] = 0x52;
           mBuffer[10] = 0x90;
           mBuffer[11] = 0x49;
           mBuffer[12] = 0xF1;
           mBuffer[13] = 0xF1;
           mBuffer[14] = 0xBB;
           mBuffer[15] = 0xE9;
           mBuffer[16] = 0xEB;
           serialPort1.Write(mBuffer, 0, mBuffer.Length);
       }


Ni una respuesta. Creo y no estoy seguro, que los baudios son 38400.

Boceto que hice con Visual C#,sin programarlo aún.


Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

MAFUS

#1
Muy buenas.

Leyendo el txt que adjuntas veo que te has saltado varias cosas.
Cito:
Every command or reply is prefixed with the string "IAI" (0x49 0x41 0x49)
(possibly standing for "InterAct Accessories, Inc.").  A single byte follows,
indicating which command or reply is being sent.


Eso indica que antes de mandar los 17 bytes debes incluir IAI y después un byte con el número de función que vas a llamar, en este caso 00. Con lo que tu lista de bytes quedaría de esta forma

0x49 0x41 0x49 0x00 0x10 0x29 0x23 0xbe 0x84 0xe1 0x6c 0xd6 0xae 0x52 0x90 0x49 0xf1 0xf1 0xbb 0xe9 0xeb

Después de haber mandado esto DexDrive te va a mandar su ID. Desde que recibes esta tienes 100ms para mandar un magic handshake, como te indica el texto en la sección POUTING. Después, como indica la sección MAGIC HANDSHAKE, el firmware para PSX te responderá con un error, mientras que el firmware N64 no responderá nada.

Sobre la configuración del puerto. Cito:
The serial connection with the DexDrive is established at 38400 baud, 8 bits,
no parity, one stop bit (8N1).


Lo único que se desconoce es si usa RTS/CTS: Se dice que habilita estas lineas pero no está claro si las usa o cuando las usa.

Espero haberte ayudado.

Meta

Hola:

Eso me pasa porque estoy usando el traductor de google ya que no se Inglés, gracias por la aclaración. creí que el IAI es lo que te devuelve, me devolvía solo esto y a veces, "?", un interrogación y sin dobles comillas. Por lo que veo, entregar un total de 21 bytes. Siguiendo con las pruebas, el código par entragar esas tramas de bytes es esta.
Código (csharp) [Seleccionar]
        private void button6_Click(object sender, EventArgs e)
        {
            byte[] mBuffer = new byte[21];
            mBuffer[0] = 0x49;
            mBuffer[1] = 0x41;
            mBuffer[2] = 0x49;
            mBuffer[3] = 0x00;
            mBuffer[4] = 0x10;
            mBuffer[5] = 0x29;
            mBuffer[6] = 0x23;
            mBuffer[7] = 0xBE;
            mBuffer[8] = 0x84;
            mBuffer[9] = 0xE1;
            mBuffer[10] = 0x6C;
            mBuffer[11] = 0xD6;
            mBuffer[12] = 0xAE;
            mBuffer[13] = 0x52;
            mBuffer[14] = 0x90;
            mBuffer[15] = 0x49;
            mBuffer[16] = 0xF1;
            mBuffer[17] = 0xF1;
            mBuffer[18] = 0xBB;
            mBuffer[19] = 0xE9;
            mBuffer[20] = 0xEB;
            serialPort1.Write(mBuffer, 0, mBuffer.Length);
        }
    }


No devuelve nada y no hace nada. Antes me devolvía ? y a veces.

Configuración del HyperTerminal.


Desde que pulse cualquier letra del teclado, me devuelve IAI como puedes ver abajo. Por eso creí que no hay que enviarlo todo junto.


¿Relamente hay que usar IAI como indicas y luego el 0x00?

Me da que el DRT y DTS también se usa y lo he puesto en true por si acaso.


Dicen que se puede hacer trampa si los une físicamente.

http://www.moxa.com/resource_file/509820091121333.pdf

Lo quiero hacer sin usar trampas.

Por saber.
1) ¿Dónde sacas que me va a enviar su ID?
2) ¿Cómo puedo saber esa ID?

Parece ser que debo interpretar bien el protocolo de este enlace.

Cualquier apoyo en bienvenido, haber si sacamos una respuesta.

El comportamiento desde que ejecute el DeXplorer con el puerto COM1, parece que que comprueba si está el DexDrive conectado y la Memory Card si está insertada o no con el Led naranja, luego al tiempo se pone verde si no hace nada. Cualquier comando que envíes se pone naranja.

Por lo que haz contado arriba, hay que enviarle 100 ms a magic handshake. Me explicas mejor si es posible lo del magic handshake, aún no lo capto. ;(

Tendré que suar en el Visual C# (más adleante usaré Visual Basic .net para tenerlo también para los demás que le interese) un timer.

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

MAFUS

#3
Muy buenas.

Sobre la cadena IAI en toda comunicación el texto dice:

CitarA cada comando o respuesta le antecede la cadena "IAI" (0x49 0x41 0x49) [...]. Un solo byte las sigue, indicando qué comando o respuesta se está enviando. Pueden seguirle mas bytes, dependiendo del comando o la respuesta exacta; la naturaleza de estos argumentos está listada más abajo por cada comando o respuesta.

Así que según esto toda comunicación, tanto por tu parte, como por el DexDrive tendrá la forma
0x49 0x41 0x49 <byte de comando/respuesta> [<bytes de argumentos>]

El texto dice:
CitarCuando un DexDrive se energiza por primera vez, se encuentra en un estado que yo llamo "pouting", y básicamente rechaza realizar cualquier cosa hasta que no se haya inicializado. Cualquier comando válido, a parte de INIT, será respondido mediante POUT, y no sucederá nada.

(El modelo PSX continuará rechazando comandos inválidos con ERROR, mientras el modelo N64, contestará con POUT a todo menos a INIT, siempre y cuando se lleve el prefijo "IAI".)

La para inicializar DexDrive, hay que mandar el comando INIT, seguido por un MAGIC_HANDSHAKE en los subsiguientes 100ms (aprox.) después de recibir la respuesta ID.

Sobre la respuesta de INIT y el ID:
Citar0x00    INIT

   Argumentos: <17 bytes>
   Respuesta: ID

[...]

0x40    ID

   Argumentos: <byte extraño> <3-bytes modelo> <versión de firmware>

   Identifica el modelo de DexDrive en respuesta a INIT.

   <byte extraño> está derivado de la cadena de 17 bytes mandada con INIT; ver fórmula extraña de mas abajo para mas detalles.

   La cadena 3-bytes modelo es "PSX" o "N64".

   <versión firmware> es la versión firmware x.yz empaquetada en un simple byte de la forma: xxyyyyzz

Sobre la fórmula extraña da el proceso de cómo calcularla, pero hay que tener en cuenta que es algo que hace DexDrive. Por tu parte el sacarla solo te serviría como comprobación. Pero viendo lo que dice el texto el algo que te puedes ahorrar. El texto dice:
CitarNo tengo ni idea de porqué es tan complejo, especialmente por el hecho de que no conduce a ningún sitio. InterAct's DexPlorer no rechazará comunicarse con ningún dispositivo que no produzca el byte esperado, aunque si siempre se envía la misma cadena de 17 bytes, ¿cuál es la idea?. [...]

Básicamente te basta recoger de qué modelo se trata, si PSX o N64, alguna función responde de una forma según el modelo.

Si no sabes inglés te será difícil que puedas crear el programa. Los traductores informáticos no dan buenos resultados a la hora de traducir este texto.

Espero haberte ayudado.

Meta

#4
Hola campeón:

En mi caso el que tengo y uso es el de PSx. En el futuro por ebay, todavía, al menos eso dicen, se puede conseguir de paquete para la N64, cuando tenga algún éxito el de PSx, compraré sea como sea el de la N64.

Quiero sejar claro algunos aspectos del puerto serie como indica en la imagen de abajo. Este está hecho con Visual C#, l a mayoría viene por defecto.


Lo comento porque son detalles que no coinside con el que trae por defecto el serialPort1. Por ejemplo, viendo este código.
/* Timeout (in msecs) when waiting for the device to reply */
#define DEX_TIMEOUT 200


En este otro código, también te habla del timeout y más datos.
Código (cpp) [Seleccionar]
#define DEX_NAME "dexdrive" /* Driver name */
#define DEX_BUFSIZE 261 /* Size of input/output buffer */
#define DEX_TIMEOUT 100 /* Timeout in msecs when waiting */
#define DEX_MAX_RETRY 2 /* Maximum number of retries */
#define DEX_MAX_DEVICES 4 /* Maximum number of devices */


Si ves algo que no me he enterado o se me ha escapado, me avisas, aquí en estos códigos parece que le han puesto nombres diferentes y se me escapa muchas cosas, quiero ponerlo idéntico los valores por si acaso. Como dice arribas antes, se cambia aquí.

Aquí nombra el IAI y demás.
/* Prefix sent with all commands/replies */
#define DEX_CMD_PREFIX "IAI"

/* Default init string used by InterAct's software */
#define DEX_INIT_STR "\x10\x29\x23\xbe\x84\xe1\x6c\xd6\xae\x52" \
"\x90\x49\xf1\xf1\xbb\xe9\xeb"



Estoy ansioso de ver el Led verde encendido del DexDrive. Desde que ejecutes el DeXplorer, se enciende naranja que está comprobado todo, luego se pone verde, desde que cierre el DeXplorer, deja de funcionar el DexDrive y se apaga el Led. Con las pruebas que estoy haciendo, aún no pasa nada.

Con el Visual C#, en el evento Load, es decir, nada más cargar el formulario, hace comprobaciones, si está conectado DexDrive, si hay alguna Memory Card insertada, si la hay, lee los datos y lo muestra en pantalla, concretamente en ListBox parece ser.

Fijarse mucho en la tabla ASCII. Mejor ver imagen aquí que muestra los valores en hexadecimales.



Este es el código que todavía no sirve en Visual C#.
Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO.Ports; // No olvidar.

namespace DexPlorer
{
    public partial class Form1 : Form
    {
        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        public Form1()
        {
            InitializeComponent();

            // Puerto abierto desde que arranca la aplicación.
            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }
            serialPort1.DataReceived += new SerialDataReceivedEventHandler(Recepcion);
        }

        // Al recibir datos.
        private void Recepcion(object sender, SerialDataReceivedEventArgs e)
        {
            // Acumula los caracteres recibidos a nuestro 'buffer' (string).
            Recibidos += serialPort1.ReadExisting();

            // Invocar o llamar al proceso de tramas.
            Invoke(new EventHandler(Actualizar));

            //Invoke(new EventHandler(IniciarTimer));
        }

        // Procesar los datos recibidos en el bufer y extraer tramas completas.
        private void Actualizar(object sender, EventArgs e)
        {
            // Para ver lo que envía desde el DexDrive hacia esta interfaz de C#.
            // Asignar el valor de la trama al richTextBox.
            richTextBox1.Text = Recibidos;

            // Selecciona la posición final para leer los mensajes entrantes.
            richTextBox1.SelectionStart = richTextBox1.Text.Length;

            // Mantiene el scroll en la entrada de cada mensaje.
            richTextBox1.ScrollToCaret();


            switch (Recibidos)
            {
                // Aquí hay que ejecutar los case cada vez que DexDrive envía
                // los datos.

            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            byte[] mBuffer = new byte[21];
            // El famoso IAI.
            mBuffer[0] = 0x49; // I en ASCII.
            mBuffer[1] = 0x41; // A.
            mBuffer[2] = 0x49; // I.

            // El comando INIT de inicio.
            mBuffer[3] = 0x00; // 0.

            // Caractéres extraños.
            mBuffer[4] = 0x10; // DLE.
            mBuffer[5] = 0x29; // ).
            mBuffer[6] = 0x23; // #.
            mBuffer[7] = 0xBE; // ¥.
            mBuffer[8] = 0x84; // ä.
            mBuffer[9] = 0xE1; // ß.
            mBuffer[10] = 0x6C; // l.
            mBuffer[11] = 0xD6; // Í.
            mBuffer[12] = 0xAE; // «.
            mBuffer[13] = 0x52; // R.
            mBuffer[14] = 0x90; // É.
            mBuffer[15] = 0x49; // I.
            mBuffer[16] = 0xF1; // ±.
            mBuffer[17] = 0xF1; // ±.
            mBuffer[18] = 0xBB; // ╗.
            mBuffer[19] = 0xE9; // Ú.
            mBuffer[20] = 0xEB; // Ù.
            serialPort1.Write(mBuffer, 0, mBuffer.Length);

            // Activa el timer para enviar el MAGIC_HANDSHAKE.
            timer1.Enabled = true;
            // timer1.Start(); // También válido para activar el timer1.
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            // Envía MAGIC_HANDSHAKE
            byte[] mBuffer = new byte[1];

            // Comando MAGIC_HANDSHAKE.
            mBuffer[0] = 0x27; // '.
            serialPort1.Write(mBuffer, 0, 1); // Envía el byte.
            timer1.Enabled = false; // Detiene el timer1 de 100 ms el intervalo.
            // timer1.Stop();
        }
    }
}


En la parte final, se le puede poner esto así para tener más precisión, es decir, la cantidad de byte completo porque se cuanto es. Por ahora lo dejo indicado arriba.
Código (csharp) [Seleccionar]
serialPort1.Write(mBuffer, 0, 21);

Estoy ahora en la parte, leyendo bien lo que has escrito arriba de recibir datos directo del DexDrive, dejo claro que la versión o Firmware de mi DexDrive es el mismo que el creador del código de Linux.



En resumen, puede que me equivoque. Envío esta trama de bytes todo junto.
IAI (0x49 0x41 0x49) + INIT (0x00) + caractéres raros que son  (0x10 0x29 0x23 0xbe 0x84 0xe1 0x6c 0xd6 0xae 0x52 0x90 0x49 0xf1 0xf1 0xbb 0xe9 0xeb) + MAGIC_HANDSHAKE (0x27)

Recibo en el chivato richTextBox esto: ?IAI!

Cita de: MAFUS en 24 Diciembre 2015, 02:09 AM
Espero haberte ayudado.

Y tanto que me has y estás ayudando. Encantado y agradecido estoy, ya que tienes las cosas claras y aportas mucho para seguir adelante. ;)

Un cordial saludo.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

MAFUS

Muy buenas.

Buscando un poco porqué el DexDrive terespondía IAI!, que no parece ser una respuesta ID válida después de INIT, me he encontrado con un código en C# que se comunica con DexDrive. Mirándolo un poco por encima se ve que hay que hacer más cosas que las explicadas en el manual que adjuntaste.

Aquí tienes:
https://github.com/ShendoXT/memcardrex/blob/master/MemcardRex/DexDrive.cs

Meta

Hola:

Que casualidad. He encontrado esa página hace minutos y lo iba a publucar, ejjeje. Gracias de todas maneras. ;)

He estado mirando el código por el aire, por lo poco que he visto, tiene muchas funciones que no me interesa, como cambiar el icono, añadir si es de Europa o Japón o de E.E.U.U. Solo me interesa que sea similar y lo justo al DeXplorer 2.0 si es posible.

Concretamente mirando el código de la clase DexDrive.cs.

Código (csharp) [Seleccionar]
using System;
using System.Collections.Generic;
using System.Text;
using System.IO.Ports;
using System.Threading;

namespace DexDriveCommunication
{
    class DexDrive
    {
        enum DexCommands { INIT = 0x00, STATUS = 0x01, READ = 0x02, WRITE = 0x04, LIGHT = 0x07, MAGIC_HANDSHAKE = 0x27 };
        enum DexResponses { POUT = 0x20, ERROR = 0x21, NOCARD = 0x22, CARD = 0x23, WRITE_OK = 0x28, WRITE_SAME = 0x29, WAIT = 0x2A, ID = 0x40, DATA = 0x41 };

        //DexDrive communication port
        SerialPort OpenedPort = null;

        //Contains a firmware version of a detected device
        string FirmwareVersion = null;

        //Init DexDrive (string returned if an error happened)
        public string StartDexDrive(string ComPortName)
        {
            //Define a port to open
            OpenedPort = new SerialPort(ComPortName, 38400, Parity.None, 8, StopBits.One);
            OpenedPort.ReadBufferSize = 256;

            //Buffer for storing read data from the DexDrive
            byte[] ReadData = null;

            //Try to open a selected port (in case of an error return a descriptive string)
            try { OpenedPort.Open(); }
            catch (Exception e) { return e.Message; }

            //Dexdrive won't respond if RTS is not toggled on/off
            OpenedPort.RtsEnable = false;
            Thread.Sleep(300);
            OpenedPort.RtsEnable = true;
            Thread.Sleep(300);

            //DTR line is used for additional power
            OpenedPort.DtrEnable = true;

            //Check if DexDrive is attached to the port
            //Detection may fail 1st or 2nd time, so the command is sent 5 times
            for (int i = 0; i < 5; i++)
            {
                OpenedPort.DiscardInBuffer();
                OpenedPort.Write("XXXXX");
                Thread.Sleep(20);
            }

            //Check for "IAI" string
            ReadData = ReadDataFromPort();
            if (ReadData[0] != 0x49 || ReadData[1] != 0x41 || ReadData[2] != 0x49) return "DexDrive was not detected on '" + ComPortName + "' port.";

            //Wake DexDrive up (kick it from POUT mode)
            SendDataToPort((byte)DexCommands.INIT, new byte[] { 0x10, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD }, 50);
            //SendDataToPort((byte)DexCommands.INIT, new byte[] { 0x10, 0x29, 0x23, 0xbe, 0x84, 0xe1, 0x6c, 0xd6, 0xae, 0x52, 0x90, 0x49, 0xf1, 0xf1, 0xbb, 0xe9, 0xeb }, 50);

            //Check for "PSX" string
            ReadData = ReadDataFromPort();
            if (ReadData[5] != 0x50 || ReadData[6] != 0x53 || ReadData[7] != 0x58) return "Detected device is not a PS1 DexDrive.";

            //Fetch the firmware version
            FirmwareVersion = (ReadData[8] >> 6).ToString() + "." + ((ReadData[8] >> 2) & 0xF).ToString() + (ReadData[8] & 0x3).ToString();

            //Send magic handshake signal 10 times
            for (int i = 0; i < 10; i++) SendDataToPort((byte)DexCommands.MAGIC_HANDSHAKE, null, 0);
            Thread.Sleep(50);

            //Turn on the status light
            SendDataToPort((byte)DexCommands.LIGHT, new byte[] { 1 }, 50);

            //Everything went well, DexDrive is ready to recieve commands
            return null;
        }

        //Cleanly stop working with DexDrive
        public void StopDexDrive()
        {
            if (OpenedPort.IsOpen == true) OpenedPort.Close();
        }

        //Get the firmware version of a DexDrive
        public string GetFirmwareVersion()
        {
            return FirmwareVersion;
        }

        //Send DexDrive command on the opened COM port with a delay
        private void SendDataToPort(byte Command, byte[] Data, int Delay)
        {
            //Clear everything in the input buffer
            OpenedPort.DiscardInBuffer();

            //Every command must begin with "IAI" string
            OpenedPort.Write("IAI" + (char)Command);
            if (Data != null) OpenedPort.Write(Data, 0, Data.Length);

            //Wait for a required timeframe (for the DexDrive response)
            if (Delay > 0) Thread.Sleep(Delay);
        }

        //Catch the response from a DexDrive
        private byte[] ReadDataFromPort()
        {
            //Buffer for reading data
            byte[] InputStream = new byte[256];

            //Read data from DexDrive
            if(OpenedPort.BytesToRead != 0)OpenedPort.Read(InputStream, 0, 256);

            return InputStream;
        }

        //Read a specified frame of a Memory Card
        public byte[] ReadMemoryCardFrame(ushort FrameNumber)
        {
            //Buffer for storing read data from the DexDrive
            byte[] ReadData = null;

            //128 byte frame data from a Memory Card
            byte[] ReturnDataBuffer = new byte[128];

            int DelayCounter = 0;

            byte FrameLsb = (byte)(FrameNumber & 0xFF);     //Least significant byte
            byte FrameMsb = (byte)(FrameNumber >> 8);       //Most significant byte
            byte XorData = (byte)(FrameLsb ^ FrameMsb);     //XOR variable for consistency checking

            //Read a frame from the Memory Card
            SendDataToPort((byte)DexCommands.READ, new byte[] { FrameLsb, FrameMsb }, 0);

            //Wait for the buffer to fill
            while (OpenedPort.BytesToRead < 133 && DelayCounter < 16)
            {
                Thread.Sleep(5);
                DelayCounter++;
            }

            //Read Memory Card data
            ReadData = ReadDataFromPort();

            //Copy received data (filter IAI prefix)
            Array.Copy(ReadData, 4, ReturnDataBuffer, 0, 128);

            //Calculate XOR checksum
            for (int i = 0; i < 128; i++)
            {
                XorData ^= ReturnDataBuffer[i];
            }

            //Return null if there is a checksum missmatch
            if (XorData != ReadData[132]) return null;

            //Return read data
            return ReturnDataBuffer;
        }

        //Write a specified frame to a Memory Card
        public bool WriteMemoryCardFrame(ushort FrameNumber, byte[] FrameData)
        {
            //Buffer for storing read data from the DexDrive
            byte[] ReadData = null;

            byte FrameLsb = (byte)(FrameNumber & 0xFF);                                 //Least significant byte
            byte FrameMsb = (byte)(FrameNumber >> 8);                                   //Most significant byte
            byte RevFrameLsb = ReverseByte(FrameLsb);                                   //Reversed least significant byte
            byte RevFrameMsb = ReverseByte(FrameMsb);                                   //Reversed most significant byte
            byte XorData = (byte)(FrameMsb ^ FrameLsb ^ RevFrameMsb ^ RevFrameLsb);     //XOR variable for consistency checking

            int DelayCounter = 0;

            //Calculate XOR checksum
            for (int i = 0; i < 128; i++)
            {
                XorData ^= FrameData[i];
            }

            //Write a frame to a Memory Card
            SendDataToPort((byte)DexCommands.WRITE, new byte[] { FrameMsb, FrameLsb, RevFrameMsb, RevFrameLsb }, 0);        //Frame number
            OpenedPort.Write(FrameData, 0, FrameData.Length);                                                               //Save data
            OpenedPort.Write(new byte[] { XorData }, 0, 1);                                                                 //XOR Checksum

            //Wait for the buffer to fill
            while (OpenedPort.BytesToRead < 4 && DelayCounter < 20)
            {
                Thread.Sleep(5);
                DelayCounter++;
            }

            //Fetch DexDrive's response to the last command
            ReadData = ReadDataFromPort();

            //Check the return status (return true if all went OK)
            if (ReadData[0x3] == (byte)DexResponses.WRITE_OK || ReadData[0x3] == (byte)DexResponses.WRITE_SAME) return true;

            //Data was not written sucessfully
            return false;
        }

        //Reverse order of bits in a byte
        byte ReverseByte(byte InputByte)
        {
            byte ReturnByte = new byte();

            int i = 0;
            int j = 7;

            while (i < 8)
            {
                if((InputByte & (1 << i)) > 0) ReturnByte |= (byte)(1 << j);

                i++;
                j--;
            }

            //Return reversed byte
            return ReturnByte;
        }
    }
}


La parte de enumerar los hedaceimales sean comandos o respuestas está muy cómodo.
Código (csharp) [Seleccionar]
        enum DexCommands { INIT = 0x00, STATUS = 0x01, READ = 0x02, WRITE = 0x04, LIGHT = 0x07, MAGIC_HANDSHAKE = 0x27 };
        enum DexResponses { POUT = 0x20, ERROR = 0x21, NOCARD = 0x22, CARD = 0x23, WRITE_OK = 0x28, WRITE_SAME = 0x29, WAIT = 0x2A, ID = 0x40, DATA = 0x41 };


Por supuesto, tengo el componente serialPort1 en el formulario, no se el motivo de que este usuario lo ha puesto a base de códigos. En fin, cuestión de gustos.
Código (csharp) [Seleccionar]
            //Define a port to open
            OpenedPort = new SerialPort(ComPortName, 38400, Parity.None, 8, StopBits.One);
            OpenedPort.ReadBufferSize = 256;


Voy hacer el código desde 0, así me ahorro muchas cosas que tiene este ejemplo, solo me centraré en el DexDrive. Poco a poco pondré avances y/o pedir ayuda.

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Meta

Hola:



Primera prueba y me costó coger el truco, he logrado encender el Led verde del DexDrive. Por algo se empieza. ;) Lo que he hecho, solo despierta el DeDrive mostrándolo conel Led verde encendido, está preparado para recibir comandos en el cual aún no lo he programado.

En el cuadro negro, muestra letras en verde los caracteres.

Por ahora, este es el código.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.IO.Ports; // No olvidar.
using System.Threading;

namespace DexPlorer
{
    public partial class Form1 : Form
    {
        public enum Dex_Comandos
        {
            INIT = 0x00, STATUS = 0x01, READ = 0x02, SEEK = 0x03, WRITE = 0x04, PAGE = 0x05, LIGHT = 0x07, MAGIC_HANDSHAKE = 0x27
        }

        public enum Dex_Respuestas
        {
            POUT = 0x20, ERROR = 0x21, NOCARD = 0x22, CARD = 0x23, CARD_NEW = 0x25, SEEK_OK = 0x27, WRITE_OK = 0x28, WRITE_SAME = 0x29, WAIT = 0x2A, ID = 0x40, DATA = 0x41
        }

        byte[] TRAMAS = { 0x10, 0x29, 0x23, 0xbe, 0x84, 0xe1, 0x6c, 0xd6, 0xae, 0x52, 0x90, 0x49, 0xf1, 0xf1, 0xbb, 0xe9, 0xeb };

        // Utilizaremos un string como buffer de recepción.
        string Recibidos;

        // Buffer para almacenar leer datos de la DexDrive.
        byte[] Leer_Datos = null;

        // Contiene una versión de firmware de un dispositivo detectado.
        string Firmware_Version = null;

        public Form1()
        {
            InitializeComponent();

            // Puerto abierto desde que arranca la aplicación.
            if (!serialPort1.IsOpen)
            {
                try
                {
                    serialPort1.Open();
                }
                catch (System.Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }
            }

            //Dexdrive won't respond if RTS is not toggled on/off
            serialPort1.RtsEnable = false;
            Thread.Sleep(300);
            serialPort1.RtsEnable = true;
            Thread.Sleep(300);

            //DTR line is used for additional power
            serialPort1.DtrEnable = true;

            // Comprobar si DexDrive está conectado al puerto.
            // La detección puede fallar primera o segunda vez, por lo que el comando es enviado 5 veces.
            for (int i = 0; i < 5; i++)
            {
                serialPort1.DiscardInBuffer();
                serialPort1.Write("XXXXX");
                Thread.Sleep(20);
            }

            // Compruebe cadena "IAI".
            Leer_Datos = Leer_datos_del_puerto();
            if ((Leer_Datos[0] != 0x49) || (Leer_Datos[1] != 0x41) || (Leer_Datos[2] != 0x49)) return;

            // Despierta DexDrive arriba (patear desde el modo POUT).
            //Envia_dato_al_puerto((byte)Dex_Comandos.INIT, new byte[] { 0x10, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0xAA, 0xBB, 0xCC, 0xDD }, 50);
            Envia_dato_al_puerto((byte)Dex_Comandos.INIT, new byte[] { 0x10, 0x29, 0x23, 0xbe, 0x84, 0xe1, 0x6c, 0xd6, 0xae, 0x52, 0x90, 0x49, 0xf1, 0xf1, 0xbb, 0xe9, 0xeb }, 50);

            // Compruebe cadena "PSX".
            Leer_Datos = Leer_datos_del_puerto();
            if ((Leer_Datos[5] != 0x50) || (Leer_Datos[6] != 0x53) || (Leer_Datos[7] != 0x58)) return; // "Dispositivo detectado no es un PS1 DexDrive."

            // Obtener la versión del firmware.
            Firmware_Version = (Leer_Datos[8] >> 6).ToString() + "." + ((Leer_Datos[8] >> 2) & 0xF).ToString() + (Leer_Datos[8] & 0x3).ToString();

            // Enviar señal de handshake magia 10 veces.
            for (int i = 0; i < 10; i++) Envia_dato_al_puerto((byte)Dex_Comandos.MAGIC_HANDSHAKE, null, 0);
            Thread.Sleep(50);

            // Enciende la luz de estado.
            Envia_dato_al_puerto((byte)Dex_Comandos.LIGHT, new byte[] { 1 }, 50);

            // Todo ha ido bien, DexDrive está listo para recibir comandos.
            //return null;

            Recibidos = Encoding.ASCII.GetString(Leer_Datos);

            // Recibidos = Encoding.Default.GetString(Leer_Datos);

            // Para ver lo que envía desde el DexDrive hacia esta interfaz de C#.
            // Asignar el valor de la trama al richTextBox.
            richTextBox1.Text = Recibidos;

            //    // Para ver lo que envía desde el DexDrive hacia esta interfaz de C#.
            //    // Asignar el valor de la trama al richTextBox.
            richTextBox1.Text = Recibidos;

            // Selecciona la posición final para leer los mensajes entrantes.
            richTextBox1.SelectionStart = richTextBox1.Text.Length;

            //serialPort1.DataReceived += new SerialDataReceivedEventHandler(Recepcion);
        }

        // Enviar comando DexDrive en el puerto COM se abrió con un retraso.
        private void Envia_dato_al_puerto(byte Comando, byte[] Dato, int Delay)
        {
            // Borrar todo en el búfer de entrada.
            serialPort1.DiscardInBuffer();

            // Cada comando debe comenzar con la cadena "IAI".
            serialPort1.Write("IAI" + (char)Comando);
            if (Dato != null) serialPort1.Write(Dato, 0, Dato.Length);

            // Espere un tiempo establecido (para la respuesta DexDrive).
            if (Delay > 0) Thread.Sleep(Delay);
        }

        // Captura la respuesta de un DexDrive.
        private byte[] Leer_datos_del_puerto()
        {
            // Buffer para la lectura de datos.
            byte[] Flujo_de_entrada = new byte[256];

            // Leer datos de DexDrive.
            if (serialPort1.BytesToRead != 0) serialPort1.Read(Flujo_de_entrada, 0, 256);

            return Flujo_de_entrada;
        }
    }
}


Sigo con ello intentar enviar comandos a ver si se deja, como formatear, leer, borrar, algo.

Felices fiesta.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/

Meta

Buensa:

¿Alguna idea de leer, borrar, escribir......?

Saludos.
Tutoriales Electrónica y PIC: http://electronica-pic.blogspot.com/