26

Re : LedMatrix Hacking en ligne de commande

Merci encore hugo ! aucun problème prends ton temps, je continue de creuser de mon coté smile
je vais essayer d'écrire un autre firmware pour que l'ecran accepte des commandes en paramètre, comme ca, je pourrais envoyer ce que je veux directement en ligne de commande ou en fichier bat en faisant:

c:\led.bat -m test texte -s 8 -d 1 -l 1

et avec le fichier bat contenant:

echo %1 > \\.\COM2

mais je ne sais pas trop si c'est techniquement possible encore, j'entends par là si la liaison série limite la chose.

après peut etre qu'avec ton script je vais pouvoir obtenir un peu les mêmes resultats donc je vais voir

Dernière modification par hycday (2015-08-24 16:28:03)

27

Re : LedMatrix Hacking en ligne de commande

Hello,

En fait, j'avais réalisé un dépôt pour le pilote bash : https://github.com/hugokernel/203LedMatrix-driver.sh

++

28

Re : LedMatrix Hacking en ligne de commande

merci hugo ! je check ca de suite.
si je suis en COM2, le "device" c'est "COM2" ? ou ca fonctionne différemment en bash

29

Re : LedMatrix Hacking en ligne de commande

T'es sous windows ?

30

Re : LedMatrix Hacking en ligne de commande

oui
j'ai installé cygwin, j'ai ce fichier cmd.sh

#!/bin/bash
SPEED=9
SPACING=0
INTENSITY=1
DIRECTION=1
WATCHDOG=4
DEVICE="COM2"
PARAM="-v 0"

# Set configuration
sh led.sh -V -x "$DEVICE" "$PARAM" -s $SPEED -l $SPACING -i $INTENSITY -w $WATCHDOG

while true;
do
#    content="`uptime` - Free `df /home | awk '{ print $5 }' | tail -n 1`"
    content="hello"

    # Send text for screen
    sh led.sh -V -x "$DEVICE" -m "$content"
    sleep 30
done

que je lance en faisant "sh cmd.sh" et là, il me dit "stty command not found" (et il me dit aussi "sleep: invalid time interval '0.1'")

edit:

j'ai enlever la partie "stty" car sous windows la config se fait directement depuis le "device manager". et j'ai changé les valeurs de sleep en nombre entier.
Toujours rien sur l'écran.
Je poursuis mes recherches !

Dernière modification par hycday (2015-08-28 18:22:19)

31

Re : LedMatrix Hacking en ligne de commande

juste pour savoir, il est possible de "simuler" un "receivedBuffer" ?
en gros, si j'envoi un "hello world !" d'un coup, ca ne va pas fonctionner, car il faut y aller petit à petit, certains caractères peuvent sauter d'ailleurs.
Du coup, y a t il un moyen de prendre un string et le décomposer en lettre par lettre pour simuler un "receivedBuffer" ?


genre ca ?

string text = "Hello world !";
        int[] buffer = new int[text.Length];
        int count = 0;
        //add to buffer
        foreach(char c in text)
        {
            buffer[count] = c;
            count++;
        }

et comment receptionner le "hello world !" en un string, car je vois "USART_SendByte(receivedBuffer);"...est-il possible de récuperer une chaine de caractère pour la traiter ensuite ?

Dernière modification par hycday (2015-08-29 00:45:41)

32

Re : LedMatrix Hacking en ligne de commande

Pourquoi l'envoi de chaine comme "Hello world" ne fonctionnerai pas ??

Si tu n'est pas en mode interactif, aucun souci, c'est justement le but...

33

Re : LedMatrix Hacking en ligne de commande

parce qu'il il faut un délai entre chaque caractère. Tu as toi même dit "Lors de l'envoi de message, il est important de respecter un délai minimal entre chaque caractère sinon, des caractères vont être ignorés.".

je cherche vraiment à faire quelque chose de simple en fait:

pouvoir envoyer des messages, en passant par un fichier .bat et en faisant : echo hello world this is a test > COM2

le reste des paramètres (speed=8, spacing=1, direction=0) je ne cherche pas à les modifier en fait.

34

Re : LedMatrix Hacking en ligne de commande

> je cherche vraiment à faire quelque chose de simple en fait:

Je n'ai pas compliqué la chose volontairement, traité les caractères reçu prend du temps et donc, tu ne peux les envoyer trop vite.

Si tu passes par un buffer, tu perdras l'avantage de la mise à jour immédiate.

35

Re : LedMatrix Hacking en ligne de commande

ah mais je ne disais pas que c'était compliqué, au contraire ! je pense que c'est ultra simple maintenant que j'ai du recul, et je vois l'énorme boulot que tu as fait, tant pour le reverse engineering, que pour le code avec et sans "menu" !

j'essaye uniquement d'adapter ton code pour une utilisation ultra basique que je veux en faire.

ajouter un buffer me permettera d'envoyer une chaine de caractère en une fois, puis ensuite de l'avoir affichée sur l'écran sans avoir des caractères ignorés ?

quand tu dis que ca ne sera pas immediat, as-tu une estimation du délai ? si c'est une histoire de quelques secondes cela me va.

j'ai essayer d'enlever le max de chose du code pour ne laisser que la partie "texte" et en enlever la partie "menu" (avec speed, spacing, direction etc étant défini et non changeable) mais bien entendu cela ne fonctionne pas, donc je vais continue de travailler dessus, si un de ces quatres tu as un moment, je peux partager le code basé sur ton travail, pour avoir ton avis

merci encore hugo

36

Re : LedMatrix Hacking en ligne de commande

Alors, ça avance ce code ?

37

Re : LedMatrix Hacking en ligne de commande

non impossible d'obtenir quoi que ce soit, j'ai essayé mais à chaque fois j'en retire trop j'ai l'impression... et du coup il ne se passe rien, la connexion série ne se lance même pas...pourtant je pense avoir compris le code, j'ai mis les valeurs constantes pour les variables que je ne désire pas changer (vitesse, direction, espacement), et j'essaye d'adapter le reste du code pour uniquement recevoir une chaine de caractère après une variable (du style "-m ceci est mon texte abc 123", tout ce qui est après -m), pour l'afficher, mais ca ne fonctionne pas. et je ne sais pas comment débugger cela...

38

Re : LedMatrix Hacking en ligne de commande

bon, je me suis repenché sur la chose, j'ai réussi à alleger et nettoyer le code (attention, je ne dit pas que je l'ai "optimisé", je dis que j'ai enlevé ce dont je n'avais pas besoin pour mon projet)

du coup, maintenant, j'ai un code fonctionnel, plus léger et petit, en mode non interactif, et qui n'a qu'une fonction:
une fois la connexion ouverte, on presse "m", on attend le "." et on envoi le texte, puis "ENTER" et voila, ca l'affiche correctement sur l'écran, avec tous les autres paramètres prédéfinis.

maintenant, en partant de ceci, j'ai essayé, en vain, de changer la méthode dont le texte à envoyer est traité.
je n'arrive pas à récupérer une variable, et l'afficher d'un coup (quitte à faire un traitement dans le code pour décomposer le texte en caractère par caractère)

je désire envoyer un texte via ligne de commande, pour l'afficher sur l'écran. idéalement en utilisant par exemple un fichier .bat comme ceci (ou même sans avoir à envoyer "m" étant donné que c'est la seule commande que je désire)

mode COM2 BAUD=9600 PARITY=n DATA=8
echo m >\\.\COM2
echo "Hello World !" >\\.\COM2
echo. >\\.\COM2

une petite aide si possible ? je peux poster le .hex ou bien même le .c et .h si cela aide pour partir de la même base

merci d'avance !

Dernière modification par hycday (2015-10-03 15:04:31)

39

Re : LedMatrix Hacking en ligne de commande

Hello,
sorry, je peux pas vraiment t'aider, ça se passe sous Windows et ça fait longtemps que je n'y touche plus...
++

40

Re : LedMatrix Hacking en ligne de commande

Bonjour hugo,

Je me permets de vous revenir après ces quelques mois, au sujet de ce hack.
Je l'avais mis en standby et j'ai maintenant un peu de temps pour m'y remettre. J'ai besoin d'une petite aide car je ne m'en sors pas.
C'est au niveau du code Ledmatrix.c

J'ai réussi la partie sous windows pour communiquer en ligne de commande avec l'écran. Donc aucun soucis à ce niveau.
Cependant, je suis maintenant concerné par la modification du code LedMatrix.c car je bloque et je pense que c'est vraiment tout simple.

Voici maintenant le code que j'ai après quelques modifications pour réduire à l'essentiel. Ce code fonctionne tel quel.
Je veux partir de ca pour faire les modifications décrites plus bas.

#include "LedMatrix.h"

inline void setLed(unsigned int x, unsigned int y) {

    if (x >= MATRIX_COL_COUNT || y >= MATRIX_LINE_COUNT) {
        return;
    }

    // Reset all ports
    DDRB = DDRC = DDRD = 0;
    PORTB = PORTC = PORTD = 0;

    DDRB = pgm_read_byte(&(matrix[x][y][_DDRB]));
    DDRC = pgm_read_byte(&(matrix[x][y][_DDRC]));

    DDRD = 0b11100000 & pgm_read_byte(&(matrix[x][y][_DDRD]));

    PORTB = pgm_read_byte(&(matrix[x][y][_PORTB]));
    PORTC = pgm_read_byte(&(matrix[x][y][_PORTC]));

    PORTD = 0b11100000 & pgm_read_byte(&(matrix[x][y][_PORTD]));
}

inline void clearLeds() {
    // Reset all ports
    DDRB = DDRC = DDRD = 0;
    PORTB = PORTC = PORTD = 0;
}


inline void writeLine(char * str, int offset) {
    char col, tmp = 0;
    int x = 0;
    unsigned int start_2 = 0;
    int start = 0;
    char ii = 0;
    char i = 0;
    unsigned char b = 0;

    unsigned int offset_abs = abs(offset);

    if (offset < 0) {
        start_2 = offset_abs % 5;
        x = 0;
        start = offset_abs / 5;
    } else {
        start_2 = 0;
        x = offset;
        start = 0;
    }

   

    for (col = start; x < MATRIX_COL_COUNT; col++) {

        tmp = (col < message_size) ? str[col] : ' ';

        for (i = start_2, ii = 0; i < 5; i++, ii++) {    
            for (b = 0; b < 7; b++) {
                if (pgm_read_byte(Font5x7 + (tmp - 0x20) * 5 + i) & (1 << b)) {
                    setLed(x + ii, b);
                    asm("nop");
                    asm("nop");
                } else {
                    clearLeds();
                }
            }

            start_2 = 0;
        }
        
        // Ecart entre les lettres
        x = x + ii + char_spacing;
    }

    clearLeds();
}


#define SEND_ACK  printf("."); 

#define RESPONSE(c) USART_SendByte(c);


inline char waitData() {
    char value = 0;
    while (!receivedBuffer);
    value = receivedBuffer;
    receivedBuffer = 0;
    return value;
}

void handleAction() {

    char command = 0;
    char data = 0;
    int size = 0;

    char key, key_tmp = 0;
    char value, in = 0;

    SEND_ACK

    receivedBuffer = 0;
    while (1) {

        command = 0;
   
        // Wait for command
        while (1) {

            if (receivedBuffer) {
                command = receivedBuffer;
                receivedBuffer = 0;
                break;
            }

            ADCSRA |= (1 << ADSC) | (1 << ADIE);
            value = adc_value;        
            if (value > 126 && value < 130) {           // 128
                key = 'A';
            } else if (value > 152 && value < 157) {    // 155
                key = 'B';
            } else if (value > 76 && value < 82) {      // 79
                key = 'C';
            } else if (value > 54 && value < 59) {      // 57
                key = 'D';
            } else if (value > 17 && value < 23) {      // 19
                key = 'E';
            } else if (value > 40 && value < 47) {      // 42
                key = 'F';
            } else if (value > 189 && value < 195) {    // 192
                key = 'G';
            } else {
                key = '?';
                continue;
            }

            // Todo: Faire une boucle d'attente de message sur le port serie...??
            _delay_ms(100);

            if (key != key_tmp) {
                printf("%c", key);
                key_tmp = key;
            }

            ADCSRA |= (1 << ADSC) | (1 << ADIE);
            if (adc_value > 250) {
                printf("%c", tolower(key_tmp));
                key_tmp = 0;
            }
        }

        if (isspace(command)) {
            continue;
        }

        // Response
        _delay_ms(500);
        RESPONSE(command);

        switch (command) {
            case 'm':
                data = 0;

                const char tab[] = { 5, 5, 4, 4, 3, 3, 3, 3, 2, 2 };

                // Wait for first char
                size = message_size * (5 + char_spacing);
                while (1) {
                    if ((index - STEP) == -size) {
                        _delay_ms(100);
                        SEND_ACK
                    }

                    if (receivedBuffer) {
                        data = receivedBuffer;
                        receivedBuffer = 0;
                        break;
                    }
                }
          
                message_size = 0;
                memset(message, 0, sizeof(message));
                while (1) {
                    // Return ?
                    if (data == 8) {
                        message[--message_size] = 0;
                        continue;
                    }

                    // Enter pressed ?
                    if (data == 13) {
                        break;
                    }

                    message[message_size++] = data;

                    // Test max string size
                    if (message_size == sizeof(message) - 1) {
                        break;
                    }

                    data = waitData();
                }

                _delay_ms(500);

                // Send message size
                printf("%03i", message_size);
                goto end;
            default:
                continue;
        }


end:
printf("\n\r");
    }
}



ISR(TIMER0_OVF_vect)
{
    writeLine(message, index);
}

ISR(TIMER1_OVF_vect)
{
    int size = message_size;

        size *= (5 + char_spacing);
        if (scroll_direction) {
            index = index - STEP;
            if (index < -size) {
                index = MATRIX_COL_COUNT;

            }
        } else {
            index = index + STEP;
            if (index > MATRIX_COL_COUNT) {
                index = 0 - size;

            }
        }

    TCNT1H = speed_table[scroll_speed];
    TCNT1L = 0;
}

ISR(TIMER2_OVF_vect)
{
    if (watchdog_value && watchdog_counter++ >= watchdog_table[watchdog_value]) {
        SET_MESSAGE(WATCHDOG_ERROR_MSG)
        WATCHDOG_RESET
    }
}

ISR(ADC_vect)
{
    adc_value = ADCH;
}


void loadData() {
    int i = 0;


    eeprom_read_block((void*)&message, (const void*)EEPROM_CONFIG_ADDR_MESSAGE, sizeof(message));

    // First boot ?
    char found = 0;
    for (i = 0; i < sizeof(message); i++) {
        // No 0 ?
        if (!message[i]) {
            found = 1;
            break;
        }
    }

    if (!found) {
        memset(message, 0, sizeof(message));
    }

    message_size = strlen(message);

    scroll_speed = eeprom_read_byte((const void*)EEPROM_CONFIG_ADDR_SPEED);
    if (scroll_speed != 8) {
        scroll_speed = 8;
        eeprom_update_byte((const void*)EEPROM_CONFIG_ADDR_SPEED, scroll_speed);
    }

    scroll_direction = eeprom_read_byte((const void*)EEPROM_CONFIG_ADDR_DIRECTION);
    if (scroll_direction != 1) {
        scroll_direction = 1;
        eeprom_update_byte((const void*)EEPROM_CONFIG_ADDR_DIRECTION, scroll_direction);
    }

    char_spacing = eeprom_read_byte((const void*)EEPROM_CONFIG_ADDR_SPACING);
    if (char_spacing != 1) {
        char_spacing = 1;
        eeprom_update_byte((const void*)EEPROM_CONFIG_ADDR_SPACING, char_spacing);
    }

    intensity = eeprom_read_byte((const void*)EEPROM_CONFIG_ADDR_INTENSITY);
    if (intensity >= 9) {
        intensity = 9;
        eeprom_update_byte((const void*)EEPROM_CONFIG_ADDR_INTENSITY, intensity);

/*
// see if keep ?
                if (intensity) {
                    TCCR0B = (0<<CS02) | (1<<CS01) | (1<<CS00);
                } else {
                    TCCR0B = (1<<CS02);
                }
*/

    }

    watchdog_value = eeprom_read_byte((const void*)EEPROM_CONFIG_ADDR_WATCHDOG);
    if (watchdog_value >= 9) {
        watchdog_value = 9;

/*
// see if keep ?
                if (watchdog_value) {
                    WATCHDOG_RESET
                    TIMSK2 |= (1<<TOIE2);
                } else {
                    TIMSK2 = 0;
                }
*/

        eeprom_update_byte((const void*)EEPROM_CONFIG_ADDR_WATCHDOG, watchdog_value);
    }


}

int main(void) {

    clearLeds();

    // Timer 0 configuration : Print message
    TIMSK0 |= (1<<TOIE0);
    TCCR0A = 0;
    TCCR0B |= ((0<<CS02) | (1<<CS01) | (1<<CS00));
    TCNT0 = 0;

    // Timer 1 configuration : Scroll message
    TIMSK1 |= (1<<TOIE1);
    TCCR1A = 0;
    TCCR1B |= ((0<<CS12) | (1<<CS11) | (1<<CS10));
    TCCR1C  = 0;
    TCNT1 = 0;

    // Timer 2 configuration
    TIMSK2 |= 0;
    TCCR2A = 0;
    TCCR2B |= ((1<<CS22) | (1<<CS21) | (1<<CS20));
    TCNT2 = 0;

    // Init ADC
    ADMUX = 0b01100110;

    //set prescaller and enable ADC
    ADCSRA |= (1 << ADEN) | (1 << ADIE);

    USART_Init();
    stdout = &mystdout;

    memset(message, 0, sizeof(message));

    loadData();

    sei();

    DDRD = 0;
    PORTD = 0;

    handleAction();
}

Donc pour le moment :

j'ouvre une connexion série, dans le terminal j'envoi la lettre m (sans appuyer sur ENTER), l'écran répond avec des ".". A partir de là, j'écris un texte qui s'affiche instantanément, lettre par lettre sur l'écran. Le texte défile en continue. Quand j'ai finis j'appuie sur ENTER, l'écran me renvoi le nombre de caractère envoyés. Si je vais trop vite, ou si j'utilise un soft pour communiquer en ligne de commande, ca "bug" à cause de l'étape "m" et à cause de l'instantané qui fait sauter des lettres. Ce n'est pas un bug à proprement parler, c'est la manière dont ca fonctionne qui fait cette règle de "patience".

Je veux brièvement modifier le code pour fonctionner ainsi :

j'ouvre le terminal, j'écris un texte et ensuite j'appuie sur ENTER pour l'envoyer à l'écran.
le microcontrolleur ne garde que les 100 premiers caractères (je ne sais pas jusqu'à combien on peut aller pour éviter l'overflow?).
le texte d'avant, si il y a, est effacé et c'est maintenant le nouveau en entier qui s'affiche en défilant (et non lettre par lettre, ou bien avec quelques millisecondes entre chaque si ceci est essentiel).

L'idée est donc de n'avoir qu'une étape dans le terminal : on écrit un texte et on envoi.
Et l'écran l'affiche directement.

Penses-tu pouvoir m'aider au niveau du code LedMatrix.c car je ne m'y connais pas du tout mais je pense honnetement que ca ne doit pas être sorcier pour une si petite fonction.

Je te remercie d'avance de ton aide !

41

Re : LedMatrix Hacking en ligne de commande

Hello,

réponse tardive, vacances, toussa...

Par rapport aux problème de délai, pourquoi ne réalises-tu pas l;'envoi lettre par lettre avec un tempo entre chaque ?