Subversion Repositories Projects

Rev

Rev 112 | Blame | Compare with Previous | Last modification | View Log | RSS feed


//#define F_CPU 7372800UL

#include <avr/io.h>
#include <inttypes.h>
#include <stdlib.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#include "font8x6.h"
#include "main.h"
#include "lcd.h"

#define DISP_W 128
#define DISP_H 64
// #define LCD_ORIENTATION 0 // 0 MJ Tasten unten / 4 Original Tasten oben


uint8_t lcd_xpos;
uint8_t lcd_ypos;
//volatile uint8_t display_buffer[1024];                                        // Display-Puffer, weil nicht zurückgelesen werden kann
//volatile uint16_t display_buffer_pointer;                                     // Pointer auf das aktuell übertragene Byte
//volatile uint8_t display_buffer_counter;                                      // Hilfszähler zur Selektierung der Page
//volatile uint8_t display_page_counter;                                        // aktuelle Page-Nummer
//volatile uint8_t display_mode;                                                        // Modus für State-Machine


void send_byte (uint8_t data)
{
        clr_cs();
        SPDR = data;
        while(!(SPSR & (1<<SPIF)));
        SPSR = SPSR;
        set_cs();
}

void cls (void)
{
        uint16_t i,j;
       
        for (i=0;i<1024;i++)
                display_buffer[i] = 0x00;
       
        for (i=0;i<8;i++)
        {
                clr_A0();
                send_byte(0xB0+i);  //1011xxxx
                send_byte(0x10);        //00010000
//              send_byte(0x04);        //00000100 gedreht plus 4 Byte
//              send_byte(0x00);        //00000000
                send_byte(LCD_ORIENTATION);     //00000000

       
                set_A0();
                for (j=0;j<128;j++)
                        send_byte(0x00);
        }
       
        lcd_xpos = 0;
        lcd_ypos = 0;
}

void lcd_cls (void)
{
        cls();
}

void wait_1ms(void)
{
        _delay_ms (1.0);
}

void wait_ms (uint16_t time)
{
        uint16_t i;
       
        for (i=0; i<time; i++)
                wait_1ms();
}

void lcd_init (void)
{
        lcd_xpos = 0;
        lcd_ypos = 0;

       
        DDRB = 0xFF;
       
        SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA)|(1<<CPOL)|(1<<SPR1);
       
        set_cs();
        clr_reset();
        wait_ms(10);
        set_reset();
       
        clr_cs();
        clr_A0();
       
        send_byte(0x40);

        if (LCD_ORIENTATION == 0)
        {
                send_byte(0xA1); // A1 normal A0 reverse(original)
                send_byte(0xC0); // C0 normal C8 reverse(original)
        }
        else
        {
                send_byte(0xA0); // A1 normal A0 reverse(original)
                send_byte(0xC8); // C0 normal C8 reverse(original)
        }
        send_byte(0xA6);
        send_byte(0xA2);
        send_byte(0x2F);
        send_byte(0xF8);
        send_byte(0x00);
        send_byte(0x27);
        send_byte(0x81);
        send_byte(0x16);
        send_byte(0xAC);
        send_byte(0x00);
        send_byte(0xAF);
       
        cls();

}

void set_adress (uint16_t adress, uint8_t data)
{
        uint8_t page;
        uint8_t column;
       
        page = adress >> 7;
       
        clr_A0();
        send_byte(0xB0 + page);
       
//      column = (adress & 0x7F) + 4; Wenn gedreht
//      column = (adress & 0x7F);
        column = (adress & 0x7F) + LCD_ORIENTATION;

        send_byte(0x10 + (column >> 4));
        send_byte(column & 0x0F);
       
        set_A0();
        send_byte(data);
}

void scroll (void)
{
        uint16_t adress;
       
        for (adress=0;adress<896;adress++)
        {
                display_buffer[adress] = display_buffer[adress+128];
                set_adress(adress,display_buffer[adress]);
        }
        for (adress=896;adress<1024;adress++)
        {
                display_buffer[adress] = 0;
                set_adress(adress,0);
        }
}

//
// x,y = character-Pos. !
//
// mode: 0=Overwrite, 1 = OR, 2 = XOR, 3 = AND, 4 = Delete
void put_char (uint8_t x, uint8_t y, uint8_t c, uint8_t mode)
{
        uint8_t ch;
        uint8_t i;
        uint16_t adress;

        switch(c)
        {
                case 'ä':
                        c = 0x84;
                        break;
                case 'ö':
                        c = 0x94;
                        break;
                case 'ü':
                        c = 0x81;
                        break;
                case 'Ä':
                        c = 0x8E;
                        break;
                case 'Ö':
                        c = 0x99;
                        break;
                case 'Ü':
                        c = 0x9A;
                        break;
                case 'ß':
                        c = 0xE1;
                        break;
        }
       
        adress = y*128 + x*6;
        adress &= 0x3FF;
               
        for (i=0;i<6;i++)
        {
                ch = pgm_read_byte (&f8x6[0][0] + i + c * 6);
               
                switch (mode)
                {
                        case 0:
                                display_buffer[adress+i] = ch;
                                break;
                        case 1:
                                display_buffer[adress+i] |= ch;
                                break;
                        case 2:
                                display_buffer[adress+i] ^= ch;
                                break;
                        case 3:
                                display_buffer[adress+i] &= ch;
                                break;
                        case 4:
                                display_buffer[adress+i] &= ~ch;
                                break;
                }
               
                set_adress(adress+i,display_buffer[adress+i]);
        }
}

void new_line (void)
{
        lcd_ypos++;
       
        if (lcd_ypos > 7)
        {
                scroll();
                lcd_ypos = 7;
        }
}


void lcd_printp (const char *text, uint8_t mode)
{
        while (pgm_read_byte(text))
        {
                if (pgm_read_byte(text) > 0x1F)
                {
                        put_char(lcd_xpos,lcd_ypos,pgm_read_byte(text++),mode);
                       
                        lcd_xpos++;
                        if (lcd_xpos > 20)
                        {
                                lcd_xpos = 0;
                                new_line();
                        }
                }
                else
                {
                        switch (pgm_read_byte(text))
                        {
                                case 0x0D:
                                        lcd_xpos = 0;
                                        break;
                                case 0x0A:
                                        new_line();
                                        break;
                        }
                        text++;
                }
        }
}

void lcd_print_atp (uint8_t x, uint8_t y, const char *text, uint8_t mode)
{
        lcd_xpos = x;
        lcd_ypos = y;
        lcd_printp (text, mode);
}


void lcd_print (uint8_t *text, uint8_t mode)
{
        while (*text)
        {
                if (*text > 0x1F)
                {
                        put_char(lcd_xpos,lcd_ypos,*text++,mode);
                       
                        lcd_xpos++;
                        if (lcd_xpos > 20)
                        {
                                lcd_xpos = 0;
                                new_line();
                        }
                }
                else
                {
                        switch (*text)
                        {
                                case 0x0D:
                                        lcd_xpos = 0;
                                        break;
                                case 0x0A:
                                        new_line();
                                        break;
                        }
                        text++;
                }
        }
}

void lcd_print_at (uint8_t x, uint8_t y, uint8_t *text, uint8_t mode)
{
        lcd_xpos = x;
        lcd_ypos = y;
        lcd_print(text, mode);
}


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Plot (set one Pixel)
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// mode:
// 0=Clear, 1=Set, 2=XOR
void lcd_plot (uint8_t xpos, uint8_t ypos, uint8_t mode)
{
        uint16_t adress;
        uint8_t mask;
       
        if ((xpos < 128) && (ypos < 64))
        {
                adress = (ypos/8) * 128 + xpos;                         // adress = 0/8 * 128 + 0   = 0
                mask = 1<<(ypos & 0x07);                                                // mask = 1<<0 = 1
               
                adress &= 0x3FF;
               
                switch (mode)
                {
                        case 0:
                                display_buffer[adress] &=~mask;
                                break;
                        case 1:
                                display_buffer[adress] |= mask;
                                break;
                        case 2:
                                display_buffer[adress] ^= mask;
                                break;
                }
               
                set_adress(adress,display_buffer[adress]);
        }
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Line (draws a line from x1,y1 to x2,y2
// + Based on Bresenham line-Algorithm
// + found in the internet, modified by thkais 2007
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void lcd_line(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, uint8_t mode)

{
        int x,y,count,xs,ys,xm,ym;

        x=(int)x1;
        y=(int)y1;
        xs=(int)x2 - (int)x1;
        ys=(int)y2 - (int)y1;
        if(xs < 0)
                xm= -1;
        else
                if(xs > 0)
                        xm= 1;
                else
                        xm= 0;
        if(ys < 0)
                ym= -1;
        else
                if(ys > 0)
                        ym= 1;
                else
                        ym= 0;
        if(xs < 0)
                xs= -xs;
        if(ys < 0)
                ys= -ys;

        lcd_plot((unsigned char)x, (unsigned char)y, mode);

        if(xs > ys) // Flat Line <45 degrees
        {
                count= -(xs / 2);
                while(x != x2)
                {
                        count= count + ys;
                        x= x + xm;
                        if(count > 0)
                        {
                                y= y + ym;
                                count= count - xs;
                        }
                        lcd_plot((unsigned char)x, (unsigned char)y, mode);
                }
        }
        else // Line >=45 degrees
        {
                count=- (ys / 2);
                while(y != y2)
                {
                        count= count + xs;
                        y= y + ym;
                        if(count > 0)
                        {
                                x= x + xm;
                                count= count - ys;
                        }
                        lcd_plot((unsigned char)x, (unsigned char)y, mode);
                }
        }
}


// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + Filled rectangle
// + x1, y1 = upper left corner
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void lcd_frect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode)
{
        uint16_t x2, y2;
        uint16_t i;

        if (x1 >= DISP_W)
                x1 = DISP_W - 1;
        if (y1 >= DISP_H)
                y1 = DISP_H - 1;
        x2 = x1 + widthx;
        y2 = y1 + widthy;
       
        if (x2 > DISP_W)
                x2 = DISP_W;
        if (y2 > DISP_H)
                y2 = DISP_H;
               
        for (i=y1;i<=y2;i++)
        {
                lcd_line(x1,i,x2,i,mode);
        }
       
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + outline of rectangle
// + x1, y1 = upper left corner
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void lcd_rect (uint8_t x1, uint8_t y1, uint8_t widthx, uint8_t widthy, uint8_t mode)
{
        uint16_t x2, y2;

        if (x1 >= DISP_W)
                x1 = DISP_W - 1;
        if (y1 >= DISP_H)
                y1 = DISP_H - 1;
        x2 = x1 + widthx;
        y2 = y1 + widthy;
       
        if (x2 > DISP_W)
                x2 = DISP_W;
        if (y2 > DISP_H)
                y2 = DISP_H;

        lcd_line (x1, y1, x2, y1, mode);
        lcd_line (x2, y1, x2, y2, mode);
        lcd_line (x2, y2, x1, y2, mode);
        lcd_line (x1, y2, x1, y1, mode);
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + outline of a circle
// + Based on Bresenham-algorithm found in wikipedia
// + modified by thkais (2007)
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


void draw_circle(int16_t x0, int16_t y0, int16_t radius, uint8_t mode)
{
        int16_t f = 1 - radius;
        int16_t ddF_x = 0;
        int16_t ddF_y = -2 * radius;
        int16_t x = 0;
        int16_t y = radius;

        lcd_plot(x0, y0 + radius, mode);
        lcd_plot(x0, y0 - radius, mode);
        lcd_plot(x0 + radius, y0, mode);
        lcd_plot(x0 - radius, y0, mode);

        while(x < y)
        {
                if(f >= 0)
                {
                        y --;
                        ddF_y += 2;
                        f += ddF_y;
                }
                x ++;
                ddF_x += 2;
                f += ddF_x + 1;

                lcd_plot(x0 + x, y0 + y, mode);
                lcd_plot(x0 - x, y0 + y, mode);
                 
                lcd_plot(x0 + x, y0 - y, mode);
                lcd_plot(x0 - x, y0 - y, mode);
                 
                lcd_plot(x0 + y, y0 + x, mode);
                lcd_plot(x0 - y, y0 + x, mode);
                 
                lcd_plot(x0 + y, y0 - x, mode);
                lcd_plot(x0 - y, y0 - x, mode);
        }
}

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// + filled Circle
// + modified circle-algorithm thkais (2007)
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void draw_fcircle(int16_t x0, int16_t y0, int16_t radius)
{
        int16_t f = 1 - radius;
        int16_t ddF_x = 0;
        int16_t ddF_y = -2 * radius;
        int16_t x = 0;
        int16_t y = radius;
 
        lcd_line(x0, y0 + radius,x0, y0 - radius,1);
   
        lcd_line(x0 + radius, y0,x0 - radius, y0,1);
   
        while(x < y)
        {
                if(f >= 0)
                {
                        y--;
                        ddF_y += 2;
                        f += ddF_y;
                }
                x++;
                ddF_x += 2;
                f += ddF_x + 1;
 
                lcd_line(x0 + x, y0 + y,x0 - x, y0 + y,1);
                lcd_line(x0 + x, y0 - y,x0 - x, y0 - y,1);
                lcd_line(x0 + y, y0 + x,x0 - y, y0 + x,1);
                lcd_line(x0 + y, y0 - x,x0 - y, y0 - x,1);
        }
 }