-
        

Ergebnis 1 bis 2 von 2

Thema: bitmap auf nokia-display (tutorial)

  1. #1
    Erfahrener Benutzer Roboter Genie Avatar von robocat
    Registriert seit
    18.07.2006
    Beiträge
    935

    bitmap auf nokia-display (tutorial)

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    hi ihr,

    vielleicht interessierts jemanden, wie man mit einem mega8 ein bitmap auf einem alten nokia-3310-display anzeigt. diese schwarzweiss-displays haben 84*48 pixel und werden mit max. 3,3V betrieben.

    die beschaltung habe ich von http://www.microsyl.com/nokialcd/nokialcd.html beinahe 1:1 übernommen, nur der data/command-pin hängt bei mir auf PB7. ausserdem muss man spannungsteiler vorsehen, wenn man (wie ich) den mega8 mit 5V betreibt:


    mit dem code von der microsyl-seite lässt sich das display sehr einfach ansteuern, man muss nur im header ein define ändern
    Code:
    #define LCD_DC_PIN                 0x80  //  PB7
    und noch eine main-funktion in der c-datei hinzufügen
    Code:
    int main(void)
    {
      unsigned char buffer[]="ein text";
      LcdInit       ();
      //LcdContrast   (64); //hier koennte man den kontrast regeln
      LcdGotoXY     (1,1);
      LcdStr(1,buffer);
      LcdUpdate     ();
      for(;;);
      return 0;
    }
    man kann auch schön pixel setzen oder linien malen:
    Code:
      LcdLine(0,0,83,47,1);
      LcdPixel(5,5,1);
      LcdUpdate();
    das display muss mit LcdInit() initialisiert werden, bevor es verwendet werden kann. alle zeichendaten werden (mit LcdPixel, LcdLine, LcdStr) zuerst in einen puffer im atmega geschrieben und erst durch LcdUpdate() auf das display übertragen.

    ich wollte eigentlich mit sprintf etwas in einen puffer schreiben, aber sobald ich stdio.h include, hängt sich mein AVRstudio (bzw. winAVR?) komplett auf. wenn jemand weiß, woran das liegen könnte, bitte hilfe.

    wenn man allerdings bitmaps abbilden will, empfiehlt es sich, nicht alle pixel einzeln zu setzen, sondern den RAM des displays direkt vollzuschreiben. dazu sind 2 dinge zu beachten:
    1. der display-ram-zeiger muss gesetzt werden, bevor man reinschreiben kann
    2. während in windows-bitmaps die bilddaten zeile für zeile gespeichert sind (bei schwarzweiss also ein byte 8 horizontale pixel sind) sind es im display-ram 8 vertikale pixel.

    3. ein schwarz-weiss-windows-bitmap enthält headerdaten vor den bilddaten, ausserdem ist die länge einer zeile (in byte) immer durch 4 teilbar. das führt dazu, dass statt 84 pixel (10,5byte) 96 pixel (12 byte) gespeichert werden. angezeigt werden die übrigen 12 pixel im zeichenprogramm nicht.

    folgender code konvertiert ein schwarzweiss-bitmap (muss 84*48pixel gross sein) in das nokia format. erzeugt wird eine textdatei, die direkt in den AVR-code gecopypastet werden kann.
    Code:
    /*----------------------------------------------------------------
    84*48 schwarz-weiss bitmap in nokia 3310 daten wandeln
    compiler: bcc32
    OS: XP
    robocat, 14.03.07
    ----------------------------------------------------------------*/
    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <string.h>
    
    int main()
    {
    
      FILE *pDatei;
      unsigned int size,i,x,y;
      unsigned char buf[64],*file1,*file2;
      long pos1,pos2;
      
      pDatei = fopen("J:\\test.bmp", "rb");
    
      if(pDatei == NULL)
      {
        printf("Fehler beim Oeffnen der Quell-Datei!\n");
        printf("Programm beendet.\n");
        exit(1);
      }
    
      fseek(pDatei,0,SEEK_END);
      pos2=ftell(pDatei);
      fseek(pDatei,10,SEEK_SET);
      fread(&pos1,4,1,pDatei);
      fseek(pDatei,pos1,SEEK_SET);
    
      size=pos2-pos1;
      file1=malloc(size);
      fread(file1,1,size,pDatei); 
      fclose(pDatei);
    
      file2=malloc(504);
      memset(file2,0,504);
    
      for(x=0;x<84;x++)
      {  
        for(y=0;y<48;y++)
        {  
          if(!(*(file1+y*12+x/8)>>(7-(x%8)))&1==1)
          {
            *(file2+(5-y/8)*84+x)|=1<<(7-(y%8));
          }
        }
      }
    
      pDatei = fopen("J:\\test.txt", "w");
      if(pDatei == NULL)
      {
        printf("Fehler beim Oeffnen der Ziel-Datei!\n");
        printf("Programm beendet.\n");
        free(file1);
        free(file2);
        exit(1);
      } 
      sprintf(buf,"unsigned char picture[]={");        
      fwrite (buf,strlen(buf),1,pDatei);
      for(i=0;i<504;i++)
      {
        if(i%8==0)fwrite("\n",1,1,pDatei);
        sprintf(buf,"%u,",*(file2+i));        
        fwrite(buf,strlen(buf),1,pDatei);
      }
      fseek(pDatei,-1,SEEK_END);
      fwrite ("};\n",3,1,pDatei);
      fclose(pDatei);
      free(file1);
      free(file2);
      return 0;
    }
    bei bedarf kann ich auch das executable zur verfügung stellen.

    nun die bitmapdaten noch aufs lcd bringen:
    Code:
    unsigned char picture[]={
    0,0,64,192,64,64,64,128,........   };  // beispiel, das ist der bytecode
    
    int main(void)
    {
      word i; // typedef unsigned int word;
      LcdInit();
      LcdSend( 0x80, LCD_CMD );
      LcdSend( 0x40, LCD_CMD );
      for ( i = 0; i < 504; i++ )
      {
        LcdSend(picture[i], LCD_DATA );
      } 
      for(;;);
      return 0;
    }
    damit hat man das bitmap auf dem display:


    bei fragen helfe ich gern.

    gruesse von der katze

    edit:
    hier noch eine weitere einfache möglichkeit, eine katze darzustellen, sogar mit hintergrundbeleuchtung..

  2. #2
    Erfahrener Benutzer Roboter Genie Avatar von robocat
    Registriert seit
    18.07.2006
    Beiträge
    935
    da ich ums verrecken keine ausgabe eines integers mit den oben genannten routinen hinbekommen habe (ich konnte stdio.h nicht verwenden, deshalb kein sprintf - was aber sowieso sehr speicherfressend sein soll), habe ich eine kleine routine dafür geschrieben:
    Code:
    /*---------------------------------------------------------------- 
    ausgabe eines signed long (bzw. int)
    robocat, 16.03.07
    ----------------------------------------------------------------*/
    void LcdLong(long l)
    {
      unsigned long i,z;
      char b=0;
      if(l==0){LcdChr(1,'0');return;}
      else if(l<0){LcdChr(1,'-');l*=-1;}
      for(i=1000000000;;i/=10)
      {
        if((z=l/i)>0)b=1;
        if(b)LcdChr(1,'0'+z);
        l-=z*i;
        if(i==1)break;
      }
    }
    geht vielleicht auch eleganter, aber genügt mir vorerst.
    wenn jemand weiss, wie man mit AVR studio die stdio einbinden kann, verratets mir bitte.

    gruesse

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •