Speichern von Dateien auf einem Stick

Dependencies:   KL46Z-USBHost MODSERIAL-RTOS mbed-rtos mbed

main.cpp

Committer:
rs27
Date:
2014-05-11
Revision:
0:dc4ad683fe77

File content as of revision 0:dc4ad683fe77:

//------------------------------------------------------------------------
//
// kl25z_USB_4
// Programm zum Speichern von Dateien auf einem memery Stick
//
// Erstellt am 10.05.14 R. Schäfer
//
#include "mbed.h"
#include "rtos.h"
#include "USBHostMSD.h"
#include "MODSERIAL.h"

#define LED_OFF 1
#define LED_ON  0
#define COM_LINE_LEN 128             // maximale Länge der Eingabezeile  

struct com_struct {
    uint8_t flag;                     // Flag zur Steuerung
    uint8_t sm;                       // State maschine
    uint8_t index;                    // Index für Zeichenzähler
    char line[COM_LINE_LEN];
};

struct msd_struct {
    bool    connect;                  // wird bei Verbindung true
    uint8_t flag;                     // Flag zur Steuerung
    uint8_t sm;                       // State maschine
    uint8_t index;                    // Index für Zeichenzähler
    char line[COM_LINE_LEN];
};

extern "C" void NVIC_SystemReset();

Thread *(msdTaskp);

Serial pc(USBTX,USBRX);

// Make TX buffer 1024bytes and RX buffer use 512bytes.
// MODSERIAL uart1(PTA2, PTA1, 256, 1024); // tx, rx
MODSERIAL uart1(PTC4, PTC3, 128, 1024); // tx, rx

DigitalOut led1(PTB18);
DigitalOut led2(PTB19);
int err_counter = 0;

// ---- globle Veariablen ----------------------------------------------

// Bitposition und Belegung
//  bit 1 CR Flag
//  bit 2 byte speichern
//  bit 4
//  bit 8

struct com_struct com;      // Eingangszeile

// Bitposition und Belegung
//  bit 1 Daten speichern in aktion
//  bit 2 Datei anlegen
//  bit 4 Daten schreiben
//  bit 8 Datei schließen

struct msd_struct m_msd;    // Speicher für Stick

// mit dieser Task werden die Datem in Hintergrund im Stick abgespeichert
// es wird auch geprüft ob für das Speichern ein Stick vorhanden ist
// falls kein Stick erkannt wird, löst das Programm einen Reset aus, womit
// die USB Schnittstelle neu initialiesiert wird. Damit kann auch ein Stick
// im Betieb abgesteckt und wieder angestecht werden.
//
// Änderungen
// Thread Zeit reduzieren
// Dateinamen über globale Variable ersetzen

void msd_task(void const *) 
{
    int i = 0;
    int n;
    FILE * fp = 0;  
    
    USBHostMSD msd("usb");
    err_counter = 0;
    
    // in a loop, append a file
    // if the device is disconnected, we try to connect it again
    while(msd.connect()) 
    {
        m_msd.connect = true;
        Thread::signal_wait(0x1);
 
        // uart1.printf("\nmsd> ");            
        //              
        // for (i = 0; i < com.index; i++)
        // {
        //   uart1.printf(" %02x",m_msd.line[i]);   
        // }           
            
        // uart1.printf("\n"); 
                   
        switch (m_msd.line[0])
        {
            case 02:                                // Datei anlegen
                              
                char buffer[40];
                sprintf(buffer, "/usb/%s", &m_msd.line[1]);
                fp = fopen(buffer, "w");
                
                // uart1.printf("\nMSD Datei %s anlegen",buffer);

                break;

            case 03:                                // Daten schreiben

                if (fp) 
                {
                    n = fprintf(fp,"%s",&m_msd.line[1]);
                    // uart1.printf("\nwrite file [%d] %s",n,&m_msd.line[1]);
                }   // if (fp ..
                
                break;

            case 04:                     // Datei schließen

                if (fp) n = fclose(fp);  
                // uart1.printf("\n close file");               
                break;
                
        } // end switch(msd-line[0]

        // Speicher für die Zeile löschen
        for (i=0; i < COM_LINE_LEN; i++) m_msd.line[i] = 0;
        m_msd.flag &= ~0x01;

        // if device disconnected, try to connect again
        if (!msd.connected()) 
        {
            // uart1.printf("\n disconnected break");
            m_msd.connect = false;
            break;
        }

    } // end while (msd_connected)

    // Task wird beendet
}

// In dieser therad werden Daten aus der Seriellen Schnittstelle gelesen. Nach dem lesen
// von einem Telegramm wird dieses falls es für das Speicher verwendet wird in m_msd abgelegt.
// Die anderen Telergamme und die Antworten werde in dieser thread gleich bearbeitet.

void com_thread(void const *args)
{
    char ch;
    int i;

    while (true) 
    {
        if ((uart1.readable()) && ((com.flag & 0x80) == 0))
        {
            //----------------------------------------------------------------------------------------------------
            // Eingehende Zeichen lesen und abspeichern           
            
            ch = uart1.getc();                                              // Zeichen lesen und auswerten
            // uart1.printf("\ntel> ");            
            
            com.line[com.index] = ch;                                       // Zeichen einfuegen
            com.index++;                                                    // Zeichenzähler erhöhen
            if (com.index >= 125) com.sm = 2;                               // ein Telegramm enthält maximal 1125 Zeichen
                      
            // for (i = 0; i < com.index; i++)
            // {
            //   uart1.printf(" %02x",com.line[i]);   
            // }           
            
            // uart1.printf("\n"); 
 
            //----------------------------------------------------------------------------------------------------
            // Abschlußbit auswerten und Telegramm umsetzen
            
            switch (com.sm)   // com.sm ist state machine
            {
                case 0 :      // erstes Zeichen aus einem Telegramm
                
                    switch(ch) 
                    {
                        case 0x00:                                          // Endzeichen an erter Stelle zum testen
                            // uart1.puts("Telegramm 0x00\n");                 // direkt ausführen 
                            com.sm = 12;                                    // neues Telegramm
                            break;

                        case 0x01:                                          // Reset
                            // uart1.puts("Telegramm 0x01\n");                 // direkt ausführen
                            com.sm = 12;                                    // nur ein Zeichen
                            break;
                                
                        case 0x02:                                          // Datei anlegen und öffnen
                            com.sm = 1;                                     // Kommando Byte abspeichern
                            break;                                          // Dateinamen bis 0x00 lesen

                        case 0x03:                                          // Daten schreiben
                            com.sm = 1;                                     // Kommando Byte abspeichern
                            break;                                          // Dateinamen bis 0x00 lesen
    
                        case 0x04:                                          // Datei schließen
                            // uart1.puts("Telegramm 0x04\n");                 // direkt ausführen
                            com.sm = 10;                                    // Kommando besteht nur aus einem Zeichen
                            break;

                        case 0x05:                                          // SD Stick erkannt, direkt ausführen
                            if (m_msd.connect)
                                uart1.puts("\nStick erkannt");               
                            else
                                uart1.puts("\nStick nicht erkannt");          
                            
                            com.sm = 12;                                    // Kommando besteht nur aus einem Zeichen
                            break; 
                               
                        default:                                            // Zeichen zum abspeichern
                            // uart1.puts("\nsm 0 unbekannter Befehl");
                            com.sm = 12;                                    // Speicher löschen
                            break;
    
                    }   // ende SWITCH
                     
                    break; // end case 0:
                
                case 1:  // Lesen von weitern Zeichen nach dem ersten Zeichen
                
                    //----------------------------------------------------------------------------------------------------
                    // bis Abschlussbit alle Zeichen lesen und bei Abschlußzeichen die Auswertung angehen
                    
                    if (ch == 0x00)
                    {
                        com.sm = 10;    
                    } // end if (ch == 0x00)
                    
                    break; // end case 1:
                
                case 2:  // Zeichenkette ist länger als 125 Zeichen
                
                    // uart1.puts("\nsm 2 String ist groesser 125 Zeichen");
                    com.sm = 11;
                    
                    break;  // end case 2         

            } // end switch

            //----------------------------------------------------------------------------------------------------            
            // Telegramme die an die Task msd weitergeleitet werden
            
            if (com.sm == 10)
            {
                if ((m_msd.flag & 0x01) == 0)
                {       
                    // uart1.puts("\nsm 10 Speicher kopieren");
                    
                    for (i = 0; i < COM_LINE_LEN; i++) 
                    {
                        m_msd.line[i] = com.line[i];
                        if (com.line[i] == 0x00) break;                      
                    }

                    m_msd.flag = 0x01;
                    com.sm = 12;
                         
                    msdTaskp->signal_set(0x1);
                }
                else
                {
                    com.flag |= 0x80;           // kann erst später gespeichert werden
                }
                
            }

            //----------------------------------------------------------------------------------------------------            
            // bei mehr asl 125 Zeichen werden die Daten an die msd Task übergeben

            if (com.sm == 11)
            {
                //----------------------------------------------------------------------------------------------------
                // Daten abspeichern
                
                if ((m_msd.flag & 0x01) == 0)
                {  
                    for (i = 0; i < COM_LINE_LEN; i++) 
                    {
                        m_msd.line[i] = com.line[i];
                        if (com.line[i] == 0x00) break;
                    }

                    m_msd.flag = 0x01;
                    m_msd.sm = 0x03;
                    
                    msdTaskp->signal_set(0x1); 
                    
                    for (i = 1; i < COM_LINE_LEN; i++) com.line[i] = 0x00;
    
                    com.index = 1;
                    com.sm = 1;
                    
                }
                else
                {
                    com.flag |= 0x80;           // kann erst später gespeichert werden                        
                }
                    
            } // end if com.sm == 11
            
            //----------------------------------------------------------------------------------------------------
            // Zeile wieder löschen            
            
            if (com.sm == 12)
            { 
                // uart1.puts("\nsm 12 Speicher loeschen");
                
                for (i = 0; i < COM_LINE_LEN; i++) com.line[i] = 0x00;
    
                com.index = 0;
                com.flag = 0;
                com.sm = 0;   
             }
            
                
        } // end if (uart1.readabel
        else 
        {
            //----------------------------------------------------------------------------------------------------
            // prüfen ob die Daten auf dem Stick schon abgespeichert sind
            
            if ((com.flag & 0x80) == 0x80)
            {
                if ((m_msd.flag & 0x01) == 0)
                {
                    //----------------------------------------------------------------------------------------------------            
                    // Telegramme die an die Task msd weitergeleitet werden
                    
                    if (com.sm == 10)
                    {     
                        for (i = 0; i < COM_LINE_LEN; i++) 
                        {
                            m_msd.line[i] = com.line[i];
                            if (com.line[i] == 0x00) break;
                        }
    
                        m_msd.flag = 0x01;
                        com.sm = 12;
                                 
                        msdTaskp->signal_set(0x1);
                    }

                    if (com.sm == 11)
                    {
                        //----------------------------------------------------------------------------------------------------
                        // Daten abspeichern

                        for (i = 0; i < COM_LINE_LEN; i++) 
                        {
                            m_msd.line[i] = com.line[i];
                            if (com.line[i] == 0x00) break;
                        }

                        m_msd.flag = 0x01;
                        
                        msdTaskp->signal_set(0x1); 
                        
                        for (i = 1; i < COM_LINE_LEN; i++) com.line[i] = 0x00;
        
                        com.index = 1;
                        com.sm = 1;
                            
                    } // end if com.sm == 11
            
                    //----------------------------------------------------------------------------------------------------
                    // Zeile wieder löschen            
            
                    if (com.sm == 12)
                    { 
                        // uart1.puts("\nsm 10 Speicher loeschen");
                        
                        for (i = 0; i < COM_LINE_LEN; i++) com.line[i] = 0x00;
            
                        com.index = 0;
                        com.flag = 0;
                        com.sm = 0;   
                     }
                }
                Thread::wait(10);   // falls keine Zeichn mehr im Buffer 10 ms warten 
            }
            else
            {
                Thread::wait(100);  // falls keine Zeichn mehr im Buffer 10 ms warten
            }
        }

        led2 = !led2;
    }
}

//---------------------------------------------------------------------

int main() 
{
        int i;

        // Speicher für die Eingangszeile löschen
        for (i=0; i < COM_LINE_LEN; i++) 
        {
            com.line[i] = 0;
        }
        com.flag = 0;
        com.sm  = 0;
        com.index = 0;

        // Speicher für den Stick Speicher löschen
        for (i=0; i < COM_LINE_LEN; i++) 
        {
            m_msd.line[i] = 0;
        }
        m_msd.connect = false;
        m_msd.flag = 0;
        m_msd.sm = 0;
        m_msd.index = 0;

        led2 = LED_OFF;

        // Uhrzeit initialisieren
        struct tm t;
        t.tm_sec  = 00;   // 0-59
        t.tm_min  = 01;   // 0-59
        t.tm_hour = 11;   // 0-23
        t.tm_mday = 4;    // 1-31
        t.tm_mon  = 2;    // 0-11 0 = Januar
        t.tm_year = 114;  // year since 1900

        // Zeit umwandeln und setzen >> die Zeit wird für die Datei benötigt
        time_t seconds = mktime(&t);
        set_time(seconds);

        // pc ist die USB Schnittstelle des Debuggers
        pc.baud(56700);
        pc.printf("\nUSB_4 Test Programm V1.0d");

        // uart1 ist die Schnittstelle zur microSPS
        uart1.baud(56700);
        // uart1.printf("\nUSB_2 Test Programm V1.0d");
        
        //uart1.attach(&txCallback, MODSERIAL::TxIrq);
        //uart1.attach(&rxCallback, MODSERIAL::RxIrq);
        //uart1.attach(&txEmpty,    MODSERIAL::TxEmpty);

        // diese Task werden die nakommenden Zeichen gelesen und ausgewertet
        Thread thread(com_thread, NULL, osPriorityNormal, 512);

        // diese Taks ist die Schnittstelle zum Stick
        Thread msdTask(msd_task, NULL, osPriorityNormal, 1024 * 4);
        msdTaskp = &msdTask;
        
        while(1) 
        {
            // falls der Stick gezogen wurde, wird damit die USB Schnittstelle neu initialisiert
            if (err_counter >= 10) 
            {
                NVIC_SystemReset();
            }

            // Systemzeit neu setzen, da keine Hardwareuhr
            // auf der oginal Karte wird die Uhr über einen Eingang angesteuert
            time_t seconds = time(NULL);
            char buffer[40];
            strftime(buffer, 40, "%a,%d %m %Y.%H:%M:%S", localtime(&seconds));
            pc.printf("\nTime as a custom formatted string = %s %02x %02x %02x", buffer, com.index, com.sm, com.flag);
            // uart1.printf("\nTime as a custom formatted string");
            seconds++;
            set_time(seconds);

            // Zeitintervall
            // könnte auch in eine Taks verlagert werden
            led1 = !led1;
            Thread::wait(1000);

        } // end while
    }