Leggendo il protocollo mi sono fatto questa idea, purtroppo sbagliata perché provando Arduino collegato al PC con il programma Fritz in esecuzione non funziona.Posterò alla fine il codice x arduino.
Prendendo come riferimento la trasmissione a scacchiera singola in modalità UPDATE_BOARD , mi sembra che inizialmente la scacchiera una volta collegata al PC con il programma Fritz, aspetta il comando di 1 byte dal PC DGT_SEND_UPDATE_BRD (0x44), per poi identificarsi e rilevare la sua presenza, mandando penso una stringa al PC del tipo : " DGT Projects - This DGT board is produced by DGT Projects.\n
DGT Projects is a registered trade mark.\n
220798 ISP/bus/8KP/8KE/P6/Fritz5 Vs 1.00. Serial nr. 00137 1.0 "
I messaggi inviati alla scacchiera sono caratterizzati sempre da un byte che identifica il messaggio, seguito da altri byte a seconda del messaggio da inviare.
I possibili messaggi da inviare alla scacchiera sono:
DGT_SEND_CLK (0x41) // la scacchiera risponde con DGT_MSG_BWTIME contenente informazione sull'orologio
DGT_SEND_BOARD (0x42) // la scacchiera risponde con DGT_MSG_BOARD_DUMP trasmettendo i pezzi sulla scacchiera
DGT_SEND_UPDATE (0x43) // pone la scacchiera nella modalità UPDATE, compatibile con FRITZ5 (Fritz 5 manda questo codice)
DGT_SEND_UPDATE_BRD (0x44) // pone la scacchiera nella modalità UPDATE_BOARD, per versioni successive a Fritz 5
DGT_RETURN_SERIALNR (0x45) // restituisce un messaggio DGT_MSG_SERIALNR (Numero di serie della scacchiera ? )
DGT_RETURN_BUSADRES (0x46) // restituisce un messaggio DGT_MSG_BUSADRES … boh
DGT_SEND_TRADEMARK (0x47) // restituisce un messaggio della marca del prodotto
DGT_SEND_VERSION (0x4d) // restituisce un messaggio DGT_MSG_VERSION, versione del firmware
DGT_SEND_UPDATE_NICE (0x4b) // pone la scacchiera in modalità aggiornamento affinché trasmetta solo i risultati dei messaggi DGT_MSG_FIELD_UPDATE e DGT_MSG_BWTIME durante il gioco
DGT_SEND_EE_MOVES (0x49) // legge i dati dalla memoria interna della scacchiera restituendo il messaggio DGT_MSG_EE_MOVES */
DGT_SEND_RESET (0x40) // disattiva la scacchiera, disattivando la modalità UPDATE */
La scacchiera dopo aver interpretato il comando ricevuto, risponde nel seguente modo:
Invia prima l’intestazione del messaggio da trasmettere. L'intestazione del messaggio contiene il codice del messaggio (ID) e la dimensione in byte totali del messaggio stesso [MESSAGE SIZE].
L'inizio del messaggio in arrivo al PC per essere riconosciuto, deve avere a (1) l'MSB del messaggio stesso.
Trasmette il 1° byte inerente all’intestazione del messaggio:
MESSAGGIO ID da un byte, ricordando sempre che l’MSB del messaggio deve essere sempre a 1.
Trovo che il MESSAGGIO ID è l'OR logico di 0x80 con il codice ID dove per codice ID intendono questo:
/* codice ID: */
DGT_NONE (0x00) // se la scacchiera è in modalità reset ? boh…
DGT_BOARD_DUMP (0x06) // è il messaggio che segue il comando DGT_SEND_BOARD
DGT_BWTIME (0x0d) // gestisce il tempo.. per ora non mi serve
DGT_FIELD_UPDATE (0x0e) // segue messaggio di 5 byte quando cambia un pezzo sulla scacchira
DGT_EE_MOVES (0x0f) // contiene i contenuti della EEROM della scacchiera (non mi serve)
DGT_BUSADRES (0x10) // ??
DGT_SERIALNR (0x11) // segue il numero seriale della scacchiera
DGT_TRADEMARK (0x12) // segue la marca della scacchiera
DGT_VERSION (0x13) // segue la versione del firmware
Formato di [MESSAGE SIZE] :
Trasmette il 2° byte credo un carattere a byte singolo:
MSB di MESSAGE SIZE da un byte, MSB sempre 0, la lunghezza totale del messaggio trasmesso è da D13 a D7, compresi i 3 byte di intestazione.
Definizioni per la codifica della lunghezza dei messaggi (per evitare che MSB di [MESSAGE SIZE] sia impostato su 1) :
#define BYTE char
#define LLL_SEVEN(a) ((BYTE)(a&0x7f)) /* 0000 0000 0111 1111 */
#define LLH_SEVEN(a) ((BYTE)((a & 0x3F80)>>7)) /* 0011 1111 1000 0000 */
Trasmette il 3° byte:
LSB di MESSAGE SIZE da un byte, MSB sempre 0, la lunghezza totale del messaggio trasmesso è da D6 a D0, compresi i 3 byte di intestazione seguito dai dati: Da 0 a ((2 EXP 14) meno 3) byte di dati, di cui l'MSB è sempre zero.
Supponiamo ora un possibile esempio di dialogo tra l’Arduino ed il programma Fritz in esecuzione sul PC ….
La comunicazione è a 9600 baud senza bit di parità.
L’Arduino è in attesa di dati in USB dal PC.
Riceve da Fritz il comando DGT DGT_SEND_UPDATE (0x43), dunque ricevendo il byte 0x43 deve poi trasmettere al PC la stringa
" DGT Projects - This DGT board is produced by DGT Projects.\n
DGT Projects is a registered trade mark.\n
220798 ISP/bus/8KP/8KE/P6/Fritz5 Vs 1.00. Serial nr. 00137 1.0 " per farsi riconoscere dal programma Fritz.
Poi credo che riceve da Fritz il comando DGT_SEND_BOARD (0x42) per trovare i pezzi sulla scacchiera.
Arduino deve rispondere al comando con DGT_BOARD_DUMP (0x06)
Formato del messaggio DGT_BOARD_DUMP
byte 0: DGT_MSG_BOARD_DUMP (Credo che devo impostarlo a (0x06))
byte 1: LLH_SEVEN(DGT_SIZE_BOARD_DUMP) (Credo che devo impostarlo a 0x00)
byte 2: LLL_SEVEN(DGT_SIZE_BOARD_DUMP) (Credo che devo impostarlo a 0x67)
byte 3-66: Pezzi sulle posizioni da 0-63
I campi della scheda sono numerati da 0 a 63, in sequenza riga per riga.
Il conteggio inizia dal quadrato in alto a sinistra.
La casella A8 è numerata 0
La casella B8 è numerata 1
La casella C8 è numerata 2
La casella D8 è numerata 3
La casella E8 è numerata 4
La casella F8 è numerata 5
La casella G8 è numerata 6
La casella H8 è numerata 7
..
La casella A7 è numerata 8
..
La casella H1 è numerata 63
Valore che identifica i pezzi scacchistici:
Casella vuota 0x00
Pedone bianco 0x01
Torre bianca 0x02
Cavallo bianco 0x03
Alfiere bianco 0x04
Re bianco 0x05
Regina bianca 0x06
Pedone nero 0x07
Torre nera 0x08
Cavallo nero 0x09
Alfiere nero 0x0a
Re nero 0x0b
Regina nera 0x0c
Ora per trasmettere a Fritz la posizione devo trasmettere da Arduino i seguenti byte:
byte 0 : 0x06
byte 1 : 0x00
byte 2 : 0x67
byte 3-66: Pezzi sulle posizioni da 0-63 iniziando dal pezzo collocato nella casella A8 fino ad arrivare alla casella H1.
Ho provato con questo codice ma non funziona …
byte read_byte; //conterrà il valore letto dalla seriale
byte write_byte; //conterrà il valore scritto nella seriale
void setup() {
Serial.begin(9600); // apro la seriale, mi pare che il Programma Fritz dialoga al massimo a 9600 baud.
}
//programma principale
void loop() {
//controllo se c'è qualcosa in arrivo dalla seriale
if (Serial.available()) {
read_byte = Serial.read(); //leggo il primo byte
switch (read_byte) { //controllo i codici dei comandi
case 0x43: //Ricevo da Fritz il comando DGT DGT_SEND_UPDATE
//invio a Fritz per fare riconoscere la scacchiera
Serial.print(F(" DGT Projects - This DGT board is produced by DGT Projects.\n"));
Serial.print(F(" DGT Projects is a registered trade mark.\n"));
Serial.print(F(" 220798 ISP/bus/8KP/8KE/P6/Fritz5 Vs 1.00. Serial nr. 00137 1.0 "));
break;
case 0x42: //Ricevo da Fritz il comando DGT_SEND_BOARD (0x42) e dunque devo rispondere con il comando DGT_BOARD_DUMP (0x06)
Serial.print (0x06,HEX); // byte 0 inviato
Serial.print (0x00,HEX); // byte 1 inviato
Serial.print (0x67,HEX); // byte 2 inviato
// ora velocemente riempirò la scacchiera con i pedoni bianchi , tanto per vedere se aggiornerò la scacchiera visibile da Fritz.
for (int i=0; i <= 63; i++){
Serial.print (0x01,HEX);
} break;
}
}
while (Serial.available()) { //svuoto il buffer da eventuali altri caratteri che non mi servono più
byte a = Serial.read();
}
}