vga-rtc.zip

Zegar "VGA-RTC" - ATMega16+PCF8583+TeleVGA+Monito

http://obrazki.elektroda.pl/8074733100_1291296395_thumb.jpg Witam, Ostatnio wpadła mi w ręce karta VGA sterowana poprzez zł±cze szeregowe SPI. A a ponieważ w domu poniewiera się kilka starych monitorów VGA to postanowiłem zbudować zegar wy¶wietlaj±cy czas i datę na monitorze VGA (bez udziału PC) Takiego zegarka na elektrodzie chyba jeszcze nie było. Wybór padł na popularne układy: procesor z rodziny AVR ATMEGA16 i zegarek RTC Philipsa PCF8583. Układ jest bardzo prosty i składa się z następuj±cych elementów: - zasilacza 5V (LM7805) - procesora (ATMEGA16) - zegara czasu rzeczywistego (PCF8583+bateria CR2032) - 3 mikroprzeł±czników - zł±cza JTAG - zasilacza 3.3V (LM1117-3.3V) - karty TeleVGA Schemat w zał±czonej dokumentacji. Karta co prawda pracuje tylko w trybie znakowym ale ma możliwo¶ć definiowania własnych znaków co pozwala na wykorzystanie semi-grafiki. Ponieważ bardzo lubię wy¶wietlacze matrycowe to postanowiłem upodobnić wy¶wietlane znaki do wy¶wietlacza matrycowego LED 5x7 punktów. Zdefiniowałem trzy wielko¶ci fontów: duży do wy¶wietlania czasu, ¶redni do wy¶wietlania daty i mały do wy¶wietlania sekund i dnia tygodnia. Do tej pory programy pisałem głównie w assemblerze ale teraz postanowiłem spróbować zmierzyć się z C i Basic. C znam z PC a w Basicu pisałem ostatnio na ZX Spectrum. Do testów wybrałem GCC zintegrowane z AVR studio, IDE IAR i BASCOM. Przyznam, że z C poszło gładko, co prawda pomiędzy GCC a IAR jest trochę różnic zwi±zanych z dostępem do stałych umieszczonych w pamięci FLASH i dostępem do zmiennych bitowych. Ale w obydwu przypadkach problemy udało się szybko rozwi±zać. Natomiast Bascom to była dla mnie mordęga, co chwilę trafiałem na jakie¶ dziwol±gi a to w jednej linii może być tylko jedno działanie, a to nawiasy s± zastrzeżone dla tablic, a to nie ma tablic dwuwymiarowych itd. Zawzi±łem się i dokończyłem projekt ale był to pierwszy i ostatni projekt w Basicu. Dziwię się, że tylu osobom tak bardzo się on podoba. Na pewno zalet± jest automatyczne konfigurowanie układów peryferyjnych ale w moim przypadku na pewno nie rekompensowało to innych wad. W przypadku C czę¶ciowo korzystałem z bibliotek dostępnych razem z kata TeleVGA. Co do wielko¶ci kodu wynikowego to najlepiej wypadł IDE IAR ale tego można było się spodziewać po komercyjnym kompilatorze , na drugim miejscu AVRStudio z GCC i na szarm końcu Bascom. Niestety ze względu na wielko¶ć kodu wynikowego > 4kB w przypadku IDE IAR i Bascom trzeba mieć dostęp do pełnych wersji. Starałem się aby kod projektu był przejrzysty i dobrze skomentowany. Cały projekt jest podzielony na funkcjonalne bloki typu VGA, I2C, SPI, RTC, FONT itd. Kolory wy¶wietlania można prosto zmienić poprzez zmianę definicji stałych COLOR1,COLOR2,COLOR3 i COLOR_PRG. Programowanie zegara odbywa się za pomoc± trzech przycisków ENTER, PLUS i MINUS. Po naci¶nięciu przycisku ENTER wywołany zostaje tryb programowania, teraz przy pomocy klawiszy PLUS i MINUS możemy kolejno zmieniać godziny, minuty, dzień miesi±ca, miesi±c, rok i dzień tygodnia. Przej¶cie pomiędzy kolejnymi parametrami następuje po naci¶nięciu ENTER. Po ustawieniu sprawdzana jest poprawno¶ć daty tzn. gdy ustawimy na 31 kwietnia to zostanie ona skorygowana na 30 kwietnia. Przy ustawianiu czasu sekundy s± zerowane. Aktualnie zegar nie koryguje daty dla lat przestępnych. Zegar można rozbudować np. o obsługę termometru na DS18B20. Ze względu iż karta VGA jest sterowana po SPI można j± łatwo podł±czyć do PICa, 8051 czy ARMa. My¶lę wła¶nie nad projektem na ARM z wykorzystaniem monitora VGA i panelu dotykowego. Zał±czam schemat, kartę katalogow± karty TeleVGA, pliki Ľródłowe projektu w wersji C(IAR), C(GCC) i BASCOM. Projektu płytki nie ma gdyż układ został zmontowany na płytce uniwersalnej. Elementy zegara RTC s± zmontowane na osobnej płytce, któr± posiadałem od innego projektu. Zał±czam również kilka zdjęć zmontowanego układu i obrazu z monitora. Niestety nie udał mi się załadować filmiku pokazuj±cego jak tworzona jest semi-grafika (wy¶wietlanie w zwolnionym tempie). Przy próbie ładowania dostaję komunikat "zły plik". Próbowałem zakodować film przy pomocy różnych formatów ale zawsze kończy się niepowodzeniem. Na pewno padn± pytania co do kosztów. Monitor 0zł, karta TeleVga 120zł, ATMega16 ok 16-18zł, PCF8583 4-5zł, płytka, stabilizatory, elementy dyskretne ok 10zł. Pozdrawiam JarekC http://obrazki.elektroda.pl/7154003800_1291295938_thumb.jpg http://obrazki.elektroda.pl/8074733100_1291296395_thumb.jpg http://obrazki.elektroda.pl/4413677300_1291296366_thumb.jpg http://obrazki.elektroda.pl/9291271700_1291296315_thumb.jpg

  • vga-rtc.zip
    • display.h
    • FONT0.C
    • SPI.C
    • VGA.H
    • i2c.h
    • RTC.C
    • font0.h
    • VGA.C
    • DISPLAY.C
    • vga-rtc.aps
    • version.txt
    • rtc.h
    • spi.h
    • I2C.C
    • typedef.h
    • vga-rtc.aws
    • Makefile
    • MAIN.C


Pobierz plik - link do postu

vga-rtc.zip > display.h

#ifndef _DISPLAY_H_
#define _DISPLAY_H_

#define DOTS_NONE 0
#define DOTS_BOTTOM_ONLY 1
#define DOTS_TOP_ONLY 2
#define DOTS_TOP_BOTTOM 3

#define DOT_NONE 0
#define DOT_ON 1

#define BLANK 10
#define CHAR_A 11
#define CHAR_PLA 'A'+26
#define CHAR_PLS 'A'+27
#define CHAR_PP 'A'+28
#define CHAR_PO 'A'+29
#define CHAR_PN 'A'+30
#define CHAR_PE 'A'+31
#define CHAR_PD 'A'+32
#define CHAR_PZ 'A'+33
#define CHAR_PA 'A'+34
#define CHAR_PLL 'A'+35
#define CHAR_PK 'A'+36

// prototypy funkcji
void Show_Seconds (uint8_t bColorS);
void Show_Time (uint8_t bColorH, uint8_t bColorM, uint8_t bColorF);
void Show_Date (uint8_t bColorD, uint8_t bColorM, uint8_t bColorY, uint8_t bColorF);
void Show_WeekDay_Name (uint8_t bColor);

void Show_Frame (uint8_t bCurX, uint8_t bCurY, uint8_t bSizeX, uint8_t bSizeY, uint8_t bColor);
void Show_Dots (uint8_t bDots, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Digit_Big (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Digit_Small (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Dot_Small (uint8_t bDot, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Digit_Mini (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);

#endif


vga-rtc.zip > FONT0.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - definicja znaków
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-GCC WINAVR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include & lt; avr/pgmspace.h & gt;
#include " typedef.h "
#include " font0.h "

const uint8_t Font0_8_16 [33*16] PROGMEM=
{
// dwie puste punkty cz?śae A
// dwie puste punkty cz?śae B
// dwie puste punkty cz?śae C
// 0x00
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// pe?ny punkt górny, pusty punkt dolny, cz?śae A
// 0x03
0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,
0x00,0x00,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xF8,0xF8,

// pe?ny punkt górny, pusty punkt dolny, cz?śae B
// 0x06
0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// pusty punkt górny, pe?ny punkt dolny, cz?śae B
// 0x09
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,

// pusty punkt górny, pe?ny punkt dolny, cz?śae C
// 0x0C
0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0x00,0x00,
0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xF8,0xF8,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,

// pe?ny punkt górny. pe?ny punkt dolny, cz?śae B
// 0x0F
0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,
0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0x00,0x00,0x00,0x00,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,
0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,

// kreska pionowa
// 0x12
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,

// kreska pozioma
// 0x13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// lewy górny naro?nik
// 0x14
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,

// lewy dolny naro?nik
// 0x15
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// prawy górny naro?nik
// 0x16
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,

// prawy dolny naro?nik
// 0x17
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// ma?a punkt lewa po?owa
// 0x18
0x00,0x00,0x03,0x0F,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x0F,0x03,0x00,0x00,

// ma?a punkt prawa po?owa
// 0x19
0x00,0x00,0xC0,0xF0,0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xF8,0xF8,0xF0,0xC0,0x00,0x00,

// pusty punkt górny, pe?ny punkt dolny
// 0x1A
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,

// pe?ny punkt górny, pusty punkt dolny
// 0x1B
0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// pe?ny punkt górny, pe?ny punkt dolny
// 0x1C
0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,

// 0x1D
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// 0x20
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};


vga-rtc.zip > SPI.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi portu SPI
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-GCC WINAVR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include " avr/io.h "
#include " typedef.h "
#include " spi.h "

//------------------------------------------------------------------------------
// Inicjalizacja portu SPI
// Tryb 1 , Master, F=Fosc/4
// Linie RESET i SLEEP = 0

void SPI_Init (void)
{
//linie MOSI,SCK,CS,RESET_SLEEP=0, MISO=1
SPI_Port |= (1 & lt; & lt; SPI_MISO) | (1 & lt; & lt; SPI_MOSI);
SPI_Port & = ~( (1 & lt; & lt; SPI_MOSI) | (1 & lt; & lt; SPI_SCK) | (1 & lt; & lt; SPI_CS) |
(1 & lt; & lt; SPI_RESET) | (1 & lt; & lt; SPI_SLEEP));

//linie MOSI,SCK,CS,RESET_SLEEP jako wyj, MISO jako wej.
SPI_Port_Dir |= (1 & lt; & lt; SPI_MOSI) | (1 & lt; & lt; SPI_SCK) | (1 & lt; & lt; SPI_CS) |
(1 & lt; & lt; SPI_RESET) | (1 & lt; & lt; SPI_SLEEP);
SPI_Port_Dir & = ~(1 & lt; & lt; SPI_MISO);

// Fosc/2, SPI tryb 1, Master, Enable
SPCR= (1 & lt; & lt; SPE) | (1 & lt; & lt; MSTR);
SPSR= 1 & lt; & lt; SPI2X;
}

//------------------------------------------------------------------------------
// Transmisja bajtu na szyn? SPI.

void SPI_Transmit (uint8_t bData)
{
SPDR= bData;
while (! (SPSR & (1 & lt; & lt; SPIF)));
}

//------------------------------------------------------------------------------
// Odbiór bajtu z szyny SPI. Transmitowany bajt dummy=0.

uint8_t SPI_Receive (void)
{
SPDR= 0;
while (! (SPSR & (1 & lt; & lt; SPIF)));
return (SPDR);
}


vga-rtc.zip > VGA.H

#ifndef _VGA_H_
#define _VGA_H_

// definica adresów rejestrów karty VGA
#define VGA_ADDR_WR_LO 0x80 // adres kursora/generatora znaków LSB dla zapisu (tylko zapis)
#define VGA_ADDR_WR_HI 0x90 // adres kursora/generatora znaków MSB dla zapisu (tylko zapis)
#define VGA_ADDR_RD_LO 0xA0 // adres kursora/generatora znaków LSB dla odczytu (tylko zapis)
#define VGA_ADDR_RD_HI 0xB0 // adres kursora/generatora znaków MSB dla odczytu (tylko zapis)
#define VGA_DATA_WR 0xC0 // dana do zapisu (tylko zapis)
#define VGA_DATA_RD 0x40 // dana do odczytu (tylko odczyt)
#define VGA_CONTROL 0xD0 // konfiguracja karty (tylko zapis)

// drfinicja bitów konfiguracujnych (rejestr VGA_CONTROL)
#define CTRL_CHG0 0x01 // numer generatora znaków dla VM=0
#define CTRL_CHG1 0x02 //
#define CTRL_PNR 0x04 // numer strony video
#define CTRL_CEN 0x08 // za??czenie kursora
#define CTRL_CT 0x10 // rodzaj kursora
#define CTRL_VEN 0x20 // za??czenie video
#define CTRL_VM 0x40 // tryb video
#define CTRL_LCEN 0x80 // za??czenie podwójnego kursora

// definicja adresów pami?ci RAM karty VGA
#define VPAGE0_ADDR 0x0000 // adres pocz?tku 0 strony pami?ci Video
#define VPAGE1_ADDR 0x2000 // adres pocz?tku 1 strony pami?ci Video
#define CHARGEN0_ADDR 0x4000 // adres pocz?tku 0 genertora znaków
#define CHARGEN1_ADDR 0x5000 // adres pocz?tku 1 genertora znaków
#define CHARGEN2_ADDR 0x6000 // adres pocz?tku 2 genertora znaków
#define CHARGEN3_ADDR 0x7000 // adres pocz?tku 3 genertora znaków

#define VPAGE_SIZE 2400 // rozmiar strony graficznej 80*30

// definicja bitów konfiguracyjnych atrybutu znaków
#define BLACK 0x00
#define RED 0x01
#define GREEN 0x02
#define BLUE 0x04
#define YELLOW RED+GREEN
#define MAGENTA RED+BLUE
#define CYAN GREEN+BLUE
#define WHITE RED+GREEN+BLUE
#define BLINK 0x40
#define UNDERLINE 0x80

// prototypy funkcji
void VGA_CharGen_Init (uint8_t bCharGenNr, uint8_t bCharStart, uint8_t bCharEnd, uint8_t *pCharDef);
void VGA_Video_Page_Clear (uint8_t bPageNr);
void VGA_Put_Char (uint8_t bChar, uint8_t bAttr);

void VGA_Write_Addr_Set (uint16_t wAddr);
void VGA_Read_Addr_Set (uint16_t wAddr);

void VGA_Transmit (uint8_t bRegAddr, uint8_t bData);
uint8_t VGA_Receive (void);

#endif


vga-rtc.zip > i2c.h

#ifndef _I2C_H_
#define _I2C_H_

// dla zegara 8MHz cz?stotliowśae szyny I2C=100kHz
// F_i2c=Fosc/(16+2*TWBR*2^TWPS)

#define TWI_Port PORTC
#define SCL PC0
#define SDA PC1

#define TWI_TWBR 0x22 // TWI Bit Rate Register setting.
#define TWI_TWPS 0x00 // Prescaler = 00

#define TWI_START 0x08 // START has been transmitted
#define TWI_REP_START 0x10 // Repeated START has been transmitted
#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been tramsmitted and ACK received
#define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received

#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been tramsmitted and ACK received
#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK transmited
#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK transmited

// adres slave dla PCF8583
#define SLAVE_ADDR_WR 0xA0
#define SLAVE_ADDR_RD 0xA1

// prototypy funkcji
void I2C_Master_Init (void);
uint8_t I2C_Xmit (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr);
uint8_t I2C_Recv (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr);

uint8_t I2C_Send_Start (void);
uint8_t I2C_Get_ByteLast (uint8_t* pDataPtr);
uint8_t I2C_Get_Byte (uint8_t* pDataPtr);
uint8_t I2C_Send_Byte (uint8_t bData);
void I2C_Send_Stop (void);
uint8_t I2C_Ready (void);

extern uint8_t tI2CBuffer[4]; // bufor i2C



#endif


vga-rtc.zip > RTC.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi zegara RTC (PCF8583)
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-GCC WINAVR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include & lt; avr/io.h & gt;
#include & lt; avr/pgmspace.h & gt;
#include " typedef.h "
#include " i2c.h "
#include " rtc.h "

TIME Time; // czas i data

// tablica d?ugości miesi?cy
const uint8_t MonthTable [19] PROGMEM =
{0x0,0x31,0x29,0x31,0x30,0x31,0x30,0x31,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
0x31,0x30,0x31};

//-----------------------------------------------------------------------------
// Procedura inicjalizacji RTC

void RTC_Init (void)
{
tI2CBuffer[0]=0x00; // RTC w??czony, Alarmy i Timer wy??czone
I2C_Xmit (1, PCF_Status1, tI2CBuffer);
}

//-----------------------------------------------------------------------------
// Procedura odczytu czasu z RTC
// Wykonywany jest test poprawności odczytanego czasu (format BCD + zakresy)
// W przypadku b??du zapisywany jest do RTC czas = 12:00:00

void RTC_Read_Time (void)
{
I2C_Recv (3, PCF_Seconds, tI2CBuffer); // odczyt czasu

// test poprawności formatu czasu
if (Test_BCD (tI2CBuffer[0],0x00,0x59) == OK)
if (Test_BCD (tI2CBuffer[1],0x00,0x59)== OK)
if (Test_BCD (tI2CBuffer[2],0x00,0x23)==OK)
{
Time.bcdSeconds = tI2CBuffer[0];
Time.bcdMinutes = tI2CBuffer[1];
Time.bcdHours = tI2CBuffer[2];
return;
}

// w przypadku b??du odczytu ustawiamy 12:00:00
Time.bcdSeconds = 0x00;
Time.bcdMinutes = 0x00;
Time.bcdHours = 0x12;
RTC_Write_Time();
}


//-----------------------------------------------------------------------------
// Procedura zapisu czasu do RTC

void RTC_Write_Time (void)
{
tI2CBuffer[0] = Time.bcdSeconds;
tI2CBuffer[1] = Time.bcdMinutes;
tI2CBuffer[2] = Time.bcdHours;
I2C_Xmit (3, PCF_Seconds, tI2CBuffer); // zapis czasu
}

//-----------------------------------------------------------------------------
// Procedura odczytu daty z RTC
// Wykonywany jest test poprawności odczytanej daty (format BCD + zakresy)
// W przypadku b??du zapisywana jest do RTC data = 01:01:10

void RTC_Read_Date (void)
{
I2C_Recv (2, PCF_Date, tI2CBuffer); // odczyt daty
I2C_Recv (1, PCF_Year, & tI2CBuffer[2]); // odczyt roku

// " rozpakowanie " danych
Time.bcdDay = tI2CBuffer[0] & 0x3F;
Time.bWeekDay = tI2CBuffer[1] & gt; & gt; 5;
Time.bcdMonth = tI2CBuffer[1] & 0x1F;
Time.bcdYear = tI2CBuffer[2];

// test poprawności formatu daty
if (Test_BCD (Time.bcdDay,0x01,0x31) == OK)
if (Test_BCD (Time.bcdMonth,0x01,0x12) == OK)
if (Test_BCD (Time.bcdYear,0x00,0x99) == OK)
if (Time.bWeekDay & lt; 7)
if (Time.bcdDay & lt; = pgm_read_byte( & MonthTable[Time.bcdMonth]))
return;

// w przypadku b??du odczytu ustawiamy 1:01:2010 pi?tek
Time.bcdDay = 0x01;
Time.bWeekDay = 5;
Time.bcdMonth = 0x01;
Time.bcdYear = 0x10;
RTC_Write_Date();
}

//-----------------------------------------------------------------------------
// Procedura zapisu daty do RTC

void RTC_Write_Date (void)
{
// " spakowanie danych
tI2CBuffer[0] = Time.bcdDay;
tI2CBuffer[1] = (Time.bWeekDay & lt; & lt; 5) | Time.bcdMonth;
tI2CBuffer[2] = Time.bcdYear;

I2C_Xmit (2, PCF_Date, tI2CBuffer); // zapis daty
I2C_Xmit (1, PCF_Year, & tI2CBuffer[2]); // zapis roku
}

//-----------------------------------------------------------------------------
// Procedura testu formatu i zakresu BCD
// Wej: bcdData - dana do testów
// bcdMin - dolny dozwolony zakres
// bcdMax - górny dozwolony zakres
// Wyj: wynik testu OK/ERROR

uint8_t Test_BCD (uint8_t bcdData, uint8_t bcdMin, uint8_t bcdMax)
{
if ((bcdData & 0x0F) & lt; 0x0A & & (bcdData & 0xF0) & lt; 0xA0) // test formatu
if ( bcdData & gt; = bcdMin & & bcdData & lt; = bcdMax) // test zakresu
return (OK);

return (ERROR);
}

//-----------------------------------------------------------------------------
// Procedura zwi?kszaj?ca dan? w formacie BCD o 1
// Wej: pData - wskaźnik na dan?
// bcdMin, bcdMax - dozwolony zakres danej

void Dec_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax)
{
if (*pData == bcdMin)
*pData = bcdMax;
else
{
if ((*pData & 0x0F) == 0x00)
*pData-=7;
else
*pData-=1;
}
}
//-----------------------------------------------------------------------------
// Procedura zwi?kszaj?ca dan? w formacie BCD o 1
// Wej: pData - wskaźnik na dan?
// bcdMin, bcdMax - dozwolony zakres danej

void Inc_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax)
{
if (*pData == bcdMax)
*pData = bcdMin;
else
{
if ((*pData & 0x0F) == 0x09)
*pData+=7;
else
*pData+=1;
}
}


vga-rtc.zip > font0.h

#ifndef _FONT0_H_
#define _FONT0_H_

#include & lt; avr/pgmspace.h & gt;

// definicja znaków dla du?ych punktów
#define BIG_DOT_00A 0x00
#define BIG_DOT_00B 0x00
#define BIG_DOT_00C 0x00

#define BIG_DOT_10A 0x03
#define BIG_DOT_10B 0x06
#define BIG_DOT_10C 0x00

#define BIG_DOT_01A 0x00
#define BIG_DOT_01B 0x09
#define BIG_DOT_01C 0x0C

#define BIG_DOT_11A 0x03
#define BIG_DOT_11B 0x0F
#define BIG_DOT_11C 0x0C

#define MINI_DOT_00 0x00
#define MINI_DOT_01 0x1A
#define MINI_DOT_10 0x1B
#define MINI_DOT_11 0x1C

// definicja elementów ramki
#define LT_LINE 0x12
#define RT_LINE 0x12
#define TP_LINE 0x13
#define BM_LINE 0x13
#define LT_TP_CORNER 0x14
#define LT_BM_CORNER 0x15
#define RT_TP_CORNER 0x16
#define RT_BM_CORNER 0x17

// definicja znaków dla ma?ych punktów
#define SMALL_DOT_BLANK 0x00
#define SMALL_DOT_LEFT 0x18
#define SMALL_DOT_RIGHT 0x19

extern const uint8_t Font0_8_16 [528] PROGMEM;

#endif


vga-rtc.zip > VGA.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi karty VGA
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-GCC WINAVR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include & lt; avr/io.h & gt;
#include & lt; avr/pgmspace.h & gt;
#include " typedef.h "
#include " spi.h "
#include " vga.h "

//------------------------------------------------------------------------------
// Kasowanie pami?ci obrazu.
// Kasowanie polega na wype?nieniu strony " spacjami " .
// Wej: bPageNr - numer strony Video

void VGA_Video_Page_Clear (uint8_t bPageNr)
{
uint16_t wCounter=VPAGE_SIZE; // rozmiar strony pami?ci

// ustawienie adresu na pocz?tek strony
VGA_Write_Addr_Set ((bPageNr)?VPAGE1_ADDR:VPAGE0_ADDR);

do
{
VGA_Transmit (VGA_DATA_WR, ' '); // spacja
VGA_Transmit (VGA_DATA_WR, ((BLACK & lt; & lt; 3)|(WHITE))); // atrybut
}
while (--wCounter);
}

//------------------------------------------------------------------------------
// Zainicjowanie pami?ci generatora znaków
// Wej: bCharGenNr - numer generatora
// bCharStart - numer pierwszego definiowanego znaku (0-255)
// bCharEnd - numer ostatniego definiowanego znaku (0-255)
// pCharDef - wskaźnik na dane opisujace wygl?d znaków

void VGA_CharGen_Init (uint8_t bCharGenNr, uint8_t bCharStart, uint8_t bCharEnd, uint8_t *pCharDef)
{
uint16_t wAddr;
uint16_t wCounter;

if (bCharStart & gt; bCharEnd) // test poprawności parametrów
return;

switch (bCharGenNr) // wyznaczenie adresu pocz?tku pami?ci
{ // dla wybranego generatora znaków
case 0:
wAddr=CHARGEN0_ADDR;
break;

case 1:
wAddr=CHARGEN1_ADDR;
break;

case 2:
wAddr=CHARGEN2_ADDR;
break;

case 3:
wAddr=CHARGEN3_ADDR;
break;

default:
return; // niedozwolony numer generatora
// break;
}

wAddr=wAddr+(uint16_t)(bCharStart & lt; & lt; 4); // wyznaczenie adresu pierwszego
VGA_Write_Addr_Set (wAddr); // zedfiniowanego znaku
wCounter = (uint16_t)((bCharEnd-bCharStart)+1) & lt; & lt; 4; // wyznaczenie ilości bajtów
// do przes?ania (16 bajtów na znak)
do
{
VGA_Transmit (VGA_DATA_WR, pgm_read_byte(pCharDef)); // przepisanie definicji znaków
pCharDef++; // do pami?ci karty
} // do pami?ci karty
while (--wCounter);
}

//------------------------------------------------------------------------------
// Wyświetlenie znaku na aktualnej pozycji kursora.
// Wej: bChar - kod znaku
// bAttr - atrybut znaku

void VGA_Put_Char (uint8_t bChar, uint8_t bAttr)
{
VGA_Transmit (VGA_DATA_WR, bChar);
VGA_Transmit (VGA_DATA_WR, bAttr);
}

//------------------------------------------------------------------------------
// Zapis adresu do pary rejestrów VGA ADDR_WR
// Wej: wData - adres

void VGA_Write_Addr_Set (uint16_t wData)
{
VGA_Transmit (VGA_ADDR_WR_LO, wData & 0xFF);
VGA_Transmit (VGA_ADDR_WR_HI, (wData & gt; & gt; 8) & 0xFF);
}

//------------------------------------------------------------------------------
// Zapis adresu do pary rejestrów VGA_ADDR_RD
// Wej: wData - adres

void VGA_Read_Addr_Set (uint16_t wData)
{
VGA_Transmit (VGA_ADDR_RD_LO, wData & 0xFF);
VGA_Transmit (VGA_ADDR_RD_HI, (wData & gt; & gt; 8) & 0xFF);
}

//------------------------------------------------------------------------------
// Zapis rejestru karty VGA
// Wej: bRegAdrr - adres rejestru
// bData - dana do zapisu

void VGA_Transmit (uint8_t bRegAddr, uint8_t bData)
{
SPI_Port |= (1 & lt; & lt; SPI_CS);
SPI_Transmit (bRegAddr);
SPI_Transmit (bData);
SPI_Port & = ~(1 & lt; & lt; SPI_CS);

while (SPI_Port_Pin & (1 & lt; & lt; SPI_MISO)); // oczekiwanie na koniec cyklu zapisu
} // karta sygnalizuje gotowośae poprzez wystawienie '0' na linii MISO

//------------------------------------------------------------------------------
// Odczyt rejestru karty VGA
// Mozliwy jjest odczyt tylko jednego rejestru VGA_DATA)RD
// Wej:
// Wyj: odczytana dana

uint8_t VGA_Receive (void)
{
uint8_t bData;

SPI_Port |= (1 & lt; & lt; SPI_CS);
SPI_Transmit (VGA_DATA_RD);
bData= SPI_Receive ();
SPI_Port & = ~(1 & lt; & lt; SPI_CS);

while (SPI_Port_Pin & (1 & lt; & lt; SPI_MISO)); // oczekiwanie na koniec cyklu odczytu
// karta sygnalizuje gotowośae poprzez wystawienie '0' na linii MISO
return (bData);
}


vga-rtc.zip > DISPLAY.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury wyświetlania
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-GCC WINAVR
// Uk?ad ATMega16 + PCF8583 + TeleVGA


#include & lt; avr/io.h & gt;
#include & lt; avr/pgmspace.h & gt;
#include " typedef.h "
#include " vga.h "
#include " font0.h "
#include " display.h "
#include " rtc.h "

// Znak ma wymiary 8x16 punktów
// Kropka ma wymiary 24x24 punkty czyli w poziomie 3 znaki w pione 1 i 1/2 znaku
// dlatego definijujemy zestaw dwóch kropek o rozmiarze 24x48 punktów czyli
// 3 znaki w poziomie i 2 znaki w pionie
const uint8_t Bit2[4][3] PROGMEM =
{ // uk?ad w pionie
{BIG_DOT_00A, BIG_DOT_00B ,BIG_DOT_00C}, //  Kropka wygaszona, kropka wygaszona
{BIG_DOT_01A, BIG_DOT_01B ,BIG_DOT_01C}, //  Kropka wygaszona, kropka zapalona
{BIG_DOT_10A, BIG_DOT_10B ,BIG_DOT_10C}, //  Kropka zapalona, kropka wygaszona
{BIG_DOT_11A, BIG_DOT_11B ,BIG_DOT_11C}, //  Kropka zapalona, kropka zapalona
};

// Mini kropka ma wymiary 8x8 punktów czyli w poziomie 1 znak, w pione 1/2 znaku
// dlatego definijujemy zestaw dwóch kropek o rozmiarze 16x8 punktów czyli 1 znak
const uint8_t MiniBit2[4] PROGMEM =
{ MINI_DOT_00, MINI_DOT_01, MINI_DOT_10, MINI_DOT_11};

// Definicja fontu 5x7 kropek
const uint8_t Font58[48][20] PROGMEM=
{
{0,1,1,1,0, 3,0,0,1,3, 3,1,2,0,3, 2,1,1,1,2}, // 0 cyfry 0-9
{0,0,1,0,0, 0,2,3,0,0, 0,0,3,0,0, 0,1,3,1,0}, // 1
{0,1,1,1,0, 2,0,0,0,3, 0,0,1,2,0, 1,3,1,1,1}, // 2
{1,1,1,1,1, 0,0,1,2,0, 0,0,0,2,1, 2,1,1,1,2}, // 3
{0,0,0,1,0, 0,1,2,3,0, 3,1,1,3,1, 0,0,0,3,0}, // 4
{1,1,1,1,1, 3,1,1,1,0, 0,0,0,0,3, 2,1,1,1,2}, // 5
{0,0,1,1,0, 1,2,0,0,0, 3,2,2,2,1, 2,1,1,1,2}, // 6
{1,1,1,1,1, 0,0,0,1,2, 0,1,2,0,0, 0,3,0,0,0}, // 7
{0,1,1,1,0, 3,0,0,0,3, 1,2,2,2,1, 2,1,1,1,2}, // 8
{0,1,1,1,0, 3,0,0,0,3, 0,2,2,2,3, 0,1,1,2,0}, // 9
{0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0}, // BLANK

{0,1,1,1,0, 3,0,0,0,3, 3,1,1,1,3, 3,0,0,0,3}, // A znaki A-Z
{1,1,1,1,0, 3,0,0,0,3, 3,2,2,2,1, 3,1,1,1,2}, // B
{0,1,1,1,0, 3,0,0,0,3, 3,0,0,0,0, 2,1,1,1,2}, // C
{1,1,1,0,0, 3,0,0,2,1, 3,0,0,0,3, 3,1,1,2,0}, // D
{1,1,1,1,1, 3,0,0,0,0, 3,2,2,2,0, 3,1,1,1,1}, // E
{1,1,1,1,1, 3,0,0,0,0, 3,2,2,2,0, 3,0,0,0,0}, // F
{0,1,1,1,0, 3,0,0,0,2, 3,0,2,2,3, 2,1,1,1,3}, // G
{1,0,0,0,1, 3,0,0,0,3, 3,2,2,2,3, 3,0,0,0,3}, // H
{0,1,1,1,0, 0,0,3,0,0, 0,0,3,0,0, 0,1,3,1,0}, // I
{0,0,1,1,1, 0,0,0,3,0, 0,0,0,3,0, 2,1,1,2,0}, // J
{1,0,0,0,1, 3,0,1,2,0, 3,2,1,0,0, 3,0,0,2,1}, // K
{1,0,0,0,0, 3,0,0,0,0, 3,0,0,0,0, 3,1,1,1,1}, // L
{1,0,0,0,1, 3,2,1,2,3, 3,0,3,0,3, 3,0,0,0,3}, // M
{1,0,0,0,1, 3,1,0,0,3, 3,0,2,1,3, 3,0,0,0,3}, // N
{0,1,1,1,0, 3,0,0,0,3, 3,0,0,0,3, 2,1,1,1,2}, // O
{1,1,1,1,0, 3,0,0,0,3, 3,2,2,2,0, 3,0,0,0,0}, // P
{0,1,1,1,0, 3,0,0,0,3, 3,0,1,0,3, 2,1,1,2,1}, // Q
{1,1,1,1,0, 3,0,0,0,3, 3,2,3,2,0, 3,0,0,2,1}, // R
{0,1,1,1,1, 3,0,0,0,0, 0,2,2,2,1, 1,1,1,1,2}, // S
{1,1,1,1,1, 0,0,3,0,0, 0,0,3,0,0, 0,0,3,0,0}, // T
{1,0,0,0,1, 3,0,0,0,3, 3,0,0,0,3, 2,1,1,1,2}, // U
{1,0,0,0,1, 3,0,0,0,3, 3,0,0,0,3, 0,2,1,2,0}, // V
{1,0,0,0,1, 3,0,0,0,3, 3,0,3,0,3, 2,1,2,1,2}, // W
{1,0,0,0,1, 2,1,0,1,2, 1,0,2,0,1, 3,0,0,0,3}, // X
{1,0,0,0,1, 3,0,0,0,3, 0,2,1,2,0, 0,0,3,0,0}, // Y
{1,1,1,1,1, 0,0,0,1,2, 0,1,2,0,0, 3,1,1,1,1}, // Z

{0,1,1,1,0, 3,0,0,0,3, 3,1,1,1,3, 3,0,0,1,3}, // CHAR_PLA ?
{0,1,1,3,1, 3,2,0,0,0, 0,2,2,2,1, 1,1,1,1,2}, // CHAR_PLS Ś

// zaw??ony font dla napisu " PONIEDZIA?EK "
{1,1,1,0,0, 3,0,0,3,0, 3,2,2,0,0, 3,0,0,0,0}, // CHAR_PP
{0,1,1,0,0, 3,0,0,3,0, 3,0,0,3,0, 2,1,1,2,0}, // CHAR_PO
{1,0,0,1,0, 3,1,0,3,0, 3,0,2,3,0, 3,0,0,3,0}, // CHAR_PN
{1,1,1,1,0, 3,0,0,0,0, 3,2,2,0,0, 3,1,1,1,0}, // CHAR_PE
{1,1,1,0,0, 3,0,0,3,0, 3,0,0,3,0, 3,1,1,2,0}, // CHAR_PD
{1,1,1,1,0, 0,0,0,3,0, 0,1,2,0,0, 3,1,1,1,0}, // CHAR_PZ
{0,1,1,0,0, 3,0,0,3,0, 3,1,1,3,0, 3,0,0,3,0}, // CHAR_PA
{1,0,0,0,0, 3,0,1,0,0, 3,2,0,0,0, 3,1,1,1,0}, // CHAR_PLL ?
{1,0,0,1,0, 3,0,1,2,0, 3,2,1,0,0, 3,0,0,3,0} // CHAR_PK
};

const uint8_t DigitsSmall[12][7] PROGMEM =
{
{0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70}, // 0
{0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70}, // 1
{0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8}, // 2
{0xF8, 0x10, 0x20, 0x10, 0x08, 0x88, 0x70}, // 3
{0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10}, // 4
{0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70}, // 5
{0x30, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70}, // 6
{0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40}, // 7
{0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70}, // 8
{0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60}, // 9
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // BLANK
{0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00} // -
};

// definicje nazw dni tygodnia
const uint8_t WeekDayName[7][13] PROGMEM =
{
{'N', 'I', 'E', 'D', 'Z', 'I', 'E', 'L', 'A', 0x00},
{CHAR_PP,CHAR_PO,CHAR_PN,'I',CHAR_PE,CHAR_PD,CHAR_PZ,'I',CHAR_PA,CHAR_PLL,CHAR_PE,CHAR_PK, 0x00},
{'W', 'T', 'O', 'R', 'E', 'K', 0x00},
{CHAR_PLS, 'R', 'O', 'D', 'A', 0x00},
{'C', 'Z', 'W', 'A', 'R', 'T', 'E', 'K', 0x00},
{'P', 'I', CHAR_PLA, 'T', 'E', 'K', 0x00},
{'S', 'O', 'B', 'O', 'T', 'A', 0x00}
};

//-----------------------------------------------------------------------------
// Procedura wyświetlania sekund
// Wej: bColorS - kolor sekund

void Show_Seconds (uint8_t bColorS)
{
Show_Digit_Mini (Time.bcdSeconds & gt; & gt; 4, 65, 15, bColorS);
Show_Digit_Mini (Time.bcdSeconds & 0x0F, 71, 15, bColorS);
Show_Frame (62,14,17,6, bColorS);
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania bie??cego czasu
// Wej: bColorH, bColorM - kolor godzin i minut
// bColorF - kolor ramki

void Show_Time (uint8_t bColorH, uint8_t bColorM, uint8_t bColorF)
{
Show_Digit_Big ((Time.bcdHours & gt; & gt; 4)?Time.bcdHours & gt; & gt; 4:BLANK,3, 2, bColorH);
Show_Digit_Big (Time.bcdHours & 0x0F, 21, 2, bColorH);
Show_Digit_Big (Time.bcdMinutes & gt; & gt; 4, 45, 2, bColorM);
Show_Digit_Big (Time.bcdMinutes & 0x0F, 63, 2, bColorM);

Show_Frame (2, 1,77,13, bColorF); // pojedyncza ramka

// Show_Frame (2, 1,17,13, bColorF); // ramki dla poszczególnych cyfr
// Show_Frame (20,1,17,13, bColorF);
// Show_Frame (44,1,17,13, bColorF);
// Show_Frame (62,1,17,13, bColorF);
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania bie??cej daty
// Wej: bColorD, bColorM, bColorY - kolory dnia, miesi?ca i roku
// bColorF - kolor ramki i myślników

#define YPOS 21
void Show_Date (uint8_t bColorD, uint8_t bColorM, uint8_t bColorY, uint8_t bColorF)
{
Show_Digit_Small ((Time.bcdDay & gt; & gt; 4)?Time.bcdDay & gt; & gt; 4:BLANK,4, YPOS, bColorD);
Show_Digit_Small (Time.bcdDay & 0x0F, 14, YPOS, bColorD);
Show_Dot_Small (DOT_ON,25,YPOS+3, bColorF);
Show_Dot_Small (DOT_ON,27,YPOS+3, bColorF);
Show_Digit_Small (Time.bcdMonth & gt; & gt; 4, 30, YPOS, bColorM);
Show_Digit_Small (Time.bcdMonth & 0x0F,40, YPOS, bColorM);
Show_Dot_Small (DOT_ON,51,YPOS+3, bColorF);
Show_Dot_Small (DOT_ON,53,YPOS+3, bColorF);
Show_Digit_Small (Time.bcdYear & gt; & gt; 4, 56, YPOS, bColorY);
Show_Digit_Small (Time.bcdYear & 0x0F,66, YPOS, bColorY);
Show_Frame (2, YPOS-1,77,9 , bColorF);
}
#undef YPOS

//-----------------------------------------------------------------------------
// Procedura wyświetlania nazwy dnia tygodnia
// Wej: bColorF - kolor napisu

#define XPOS 2
#define YPOS 15

void Show_WeekDay_Name (uint8_t bColor)
{
uint8_t i,j,bChar,bCurX;

// Skasowanie poprzedniego napisu
for (i=0;i & lt; 4;i++)
{
VGA_Write_Addr_Set ((uint16_t)((YPOS+i) & lt; & lt; 8) | XPOS & lt; & lt; 1);
for (j=0;j & lt; 60;j++)
VGA_Put_Char (' ', bColor);
}

i=0;
bCurX=XPOS;
while ((bChar=pgm_read_byte( & WeekDayName[Time.bWeekDay][i++])))
{
if (bChar==' ')
Show_Digit_Mini (BLANK, bCurX, YPOS, bColor);
else
Show_Digit_Mini (bChar-'A'+CHAR_A, bCurX, YPOS, bColor);

// zaw??enie fontu dla napisu poniedzia?ek
if(Time.bWeekDay ==1)
bCurX+=5;
else
bCurX+=6;
};
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania ramki
// Wej: bCurX, bCurY - pozycja lewego górnego naro?nika
// bSizeX, bSizeY - rozmiar ramki
// bColor - kolor ramki

void Show_Frame (uint8_t bCurX, uint8_t bCurY, uint8_t bSizeX, uint8_t bSizeY, uint8_t bColor)
{
uint8_t i;

// ustawienie adresu lewego górnego naro?nika
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);

// górna cz?śae ramki
VGA_Put_Char (LT_TP_CORNER, bColor); // lewy-górny naro?nik
for (i=0;i & lt; bSizeX-2;i++)
VGA_Put_Char (TP_LINE, bColor); // górna kreska
VGA_Put_Char (RT_TP_CORNER, bColor); // prawy-górny naro?nik

// lewa i prawa cz?śae ramki
for (i=0;i & lt; bSizeY-2;i++)
{
bCurY++;
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
VGA_Put_Char (LT_LINE, bColor); // lewa kreska pionowa
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | (bCurX+bSizeX-1) & lt; & lt; 1);
VGA_Put_Char (RT_LINE, bColor); // prawa kreska pionowa
}

// dolna cz?śae ramki
bCurY++;
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
VGA_Put_Char (LT_BM_CORNER, bColor); // lewy-dolny naro?nik
for (i=0;i & lt; bSizeX-2;i++)
VGA_Put_Char (BM_LINE, bColor); // dolna kreska
VGA_Put_Char (RT_BM_CORNER, bColor); // prawy-dolny naro?nik

}

//-----------------------------------------------------------------------------
// Wyświetlenie elementu sk?adajacego si? z dwóch punktów.
// Element taki zajmuje pole 3x2 znaki.
// Wej: bDots - typ punktów
// bCurX,bCurY - pozycja kursora
// bColor - kolor punktów

void Show_Dots (uint8_t bDots, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,k;

for (i=0;i & lt; 3;i++)
{
// ustawienie pozycji kursora
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;

k=pgm_read_byte( & Bit2[bDots][i]);
for (j=0;j & lt; 3;j++)
VGA_Put_Char (k++, bColor);
}
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania cyfry du?ej (matryca 5x7 punktów)
// Wej: bDigit - cyfra do wyświetlenia
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Digit_Big (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,k,l,bTmp1,bTmp2;

if (bDigit & gt; BLANK)
return;

j=1;
for (i=1; i & lt; 12; i++)
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;

for (k=0;k & lt; 5;k++) // 5 kolumn
{
bTmp1=pgm_read_byte( & Font58[bDigit][((i/3)*5)+k]);
bTmp2=pgm_read_byte( & Bit2[bTmp1][j%3]);
for (l=0;l & lt; 3;l++) // 3 znaki = 1 kolumna
VGA_Put_Char (bTmp2++, bColor);
}
j++;
}
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania ma?ego punktu
// Wej: bDot - stan kropki
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Dot_Small (uint8_t bDot, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
if (bDot)
{
VGA_Put_Char (SMALL_DOT_LEFT, bColor);
VGA_Put_Char (SMALL_DOT_RIGHT, bColor);
}
else
{
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
}
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania cyfry ma?ej (matryca 5x7 punktów)
// Wej: bDigit - cyfra do wyświetlenia
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Digit_Small (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,bTmp1;

for (i=0;i & lt; 7;i++) // 7 wierszy
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;

bTmp1=pgm_read_byte( & DigitsSmall[bDigit][i]);
for (j=0;j & lt; 5;j++) // 5 kolumn
{
if (bTmp1 & 0x80)
{
VGA_Put_Char (SMALL_DOT_LEFT, bColor);
VGA_Put_Char (SMALL_DOT_RIGHT, bColor);
}
else
{
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
}
bTmp1 & lt; & lt; =1;
}
}
}


//-----------------------------------------------------------------------------
// Procedura wyświetlania cyfry ma?ej (matryca 5x7 punktów)
// Wej: bDigit - cyfra do wyświetlenia
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Digit_Mini (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,bTmp1;

for (i=0;i & lt; 4;i++) // 4 wiersze
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;
for (j=0;j & lt; 5;j++) // 5 kolumn
{
bTmp1=pgm_read_byte( & Font58[bDigit][i*5+j]);
VGA_Put_Char (pgm_read_byte( & MiniBit2[bTmp1]), bColor);
}
}
}


vga-rtc.zip > version.txt

Wersja 1.01

Main 1.00
Display 1.00
Rtc 1.00
Vga 1.01
Spi 1.00
I2C 1.01
Font0 1.00


vga-rtc.zip > rtc.h

#ifndef _RTC_H_
#define _RTC_H_

#include & lt; avr/pgmspace.h & gt;

#define PCF_Status1 0x00 // rejestr statusowy zegara
#define PCF_Hundredths 0x01 // rejestr setnych sekundy
#define PCF_Seconds 0x02 // rejestr sekund
#define PCF_Minutes 0x03 // rejestr minut
#define PCF_Hours 0x04 // rejestr godzin
#define PCF_Date 0x05 // rejestr daty i roku
#define PCF_Month 0x06 // rejestr miesiecy i dnia tygodnia
#define PCF_Timer 0x07 // rejestr timera
#define PCF_Al_Ctrl 0x08 // rejestr sterujacy alarmu
#define PCF_Al_Hundredths 0x09 // rejestr alarmu setne sekundy
#define PCF_Al_Seconds 0x0A // rejestr alarmu sekundy
#define PCF_Al_Minutes 0x0B // rejestr alarmu minuty
#define PCF_Al_Hours 0x0C // rejestr alarmu godziny
#define PCF_Al_Day 0x0D // rejestr alarmu dzie?
#define PCF_Al_WeekDay 0x0E // rejestr alarmu dni tygodnia
#define PCF_Al_Timer 0x0F // rejestr alarmu timer

#define PCF_Year 0x10

typedef struct // struct for time information
{
uint8_t bcdSeconds;
uint8_t bcdMinutes;
uint8_t bcdHours;
uint8_t bcdDay;
uint8_t bcdMonth;
uint8_t bcdYear;
uint8_t bWeekDay; //0-6 0=niedziela
} TIME;

// prototypy funkcji
void RTC_Init (void);
void RTC_Read_Time (void);
void RTC_Write_Time (void);
void RTC_Read_Date (void);
void RTC_Write_Date (void);

uint8_t Test_BCD (uint8_t bcdData, uint8_t bcdMin, uint8_t bcdMax);
void Inc_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax);
void Dec_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax);

extern TIME Time; // czas i data
extern const uint8_t MonthTable [19] PROGMEM;

#endif


vga-rtc.zip > spi.h

#ifndef _SPI_H_
#define _SPI_H_

// definicja pod??cze? portu SPI dla procesora ATMEGA16
#define SPI_Port PORTB
#define SPI_Port_Dir DDRB
#define SPI_Port_Pin PINB

#define SPI_RESET PB2
#define SPI_SLEEP PB3
#define SPI_CS PB4
#define SPI_MOSI PB5
#define SPI_MISO PINB6
#define SPI_SCK PB7

// prototypy funkcji
void SPI_Init (void);
void SPI_Transmit (uint8_t bData);
uint8_t SPI_Receive (void);

#endif


vga-rtc.zip > I2C.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi portu I2C
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.01
// Data 24.11.2010
// Kompilator C-GCC WINAVR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include & lt; avr/io.h & gt;
#include & lt; avr/pgmspace.h & gt;
#include " typedef.h "
#include " i2c.h "

uint8_t tI2CBuffer[4]; // bufor i2C

//------------------------------------------------------------------------------
// Inicjalizacja interfejsu I2C.
// Tryb MASTER, rezystory Pull-Up

void I2C_Master_Init (void)
{
TWI_Port |= (1 & lt; & lt; SDA); // Pull-Up dla linii SDA i SCL
TWI_Port |= (1 & lt; & lt; SCL);

TWBR = TWI_TWBR; // ustawienie BitRate
TWSR = TWI_TWPS;

TWDR = 0xFF;
TWCR = (1 & lt; & lt; TWEN); // TWI odblokowany, odpi?ty od szyny, przerwania zablokowane
}

//------------------------------------------------------------------------------
// Procedura transmisji danych po szynie I2C
// Wej: bDataCnt - ilośae danych do wys?ania
// bAddr - adres
// pDataPtr - wskaźnik na dane
// Wyj: Status transmisji OK/ERROR

uint8_t I2C_Xmit (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr)
{
if (I2C_Send_Start () == TWI_START) // wys?anie START
if (I2C_Send_Byte (SLAVE_ADDR_WR) == TWI_MTX_ADR_ACK) // wys?anie SLAVE_ADDR + WR
if (I2C_Send_Byte (bAddr) == TWI_MTX_DATA_ACK) // wys?anie adresu
{
// transmsja danych
while (bDataCnt--)
{
if (I2C_Send_Byte (*pDataPtr++) != TWI_MTX_DATA_ACK)
{
I2C_Send_Stop();
return (ERROR);
}
};
I2C_Send_Stop();
return (OK);
}

I2C_Send_Stop();
return (ERROR);
}

//------------------------------------------------------------------------------
// Procedura odbioru danych po szynie I2C
// Wej: bDataCnt - ilośae danych do odebrania
// pDataPtr - wskaźnik na bufor
// Status odbioru OK/ERROR

uint8_t I2C_Recv (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr)
{
if (I2C_Send_Start () == TWI_START) // wys?anie START
if (I2C_Send_Byte (SLAVE_ADDR_WR) == TWI_MTX_ADR_ACK) // wys?anie SLAVE_ADDR + WR
if (I2C_Send_Byte (bAddr) == TWI_MTX_DATA_ACK) // wys?anie adresu
if (I2C_Send_Start () == TWI_REP_START) // wys?anie REP_START
if (I2C_Send_Byte (SLAVE_ADDR_RD) == TWI_MRX_ADR_ACK)// wys?anie SLAVE_ADDR + RD
{
// odbiór danych
while (bDataCnt--)
{
if (bDataCnt)
{
if (I2C_Get_Byte (pDataPtr++) != TWI_MRX_DATA_ACK)
{
I2C_Send_Stop();
return (ERROR);
}
}
else
if (I2C_Get_ByteLast (pDataPtr++) != TWI_MRX_DATA_NACK)
{
I2C_Send_Stop();
return (ERROR);
}
};

I2C_Send_Stop();
return (OK);
}

I2C_Send_Stop();
return (ERROR);
}

//------------------------------------------------------------------------------
// Wys?anie bitu START
// Wej:
// Wyj: Status wykonania operacji

uint8_t I2C_Send_Start (void)
{
TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWSTA)|(1 & lt; & lt; TWEN);
return (I2C_Ready());
}

//------------------------------------------------------------------------------
// Odbiór bajtu + bit NACK
// Wej: pDataPtr - wskaźnik na bufor
// Wyj: Status wykonania operacji

uint8_t I2C_Get_ByteLast (uint8_t* pDataPtr)
{
uint8_t bStatus;

TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWEN);
if ((bStatus=I2C_Ready()) == TWI_MRX_DATA_NACK)
*pDataPtr=TWDR;

return (bStatus);
}

//------------------------------------------------------------------------------
// Odbiór bajtu + bit ACK
// Wej: pDataPtr - wskaźnik na bufor
// Wyj: Status wykonania operacji

uint8_t I2C_Get_Byte (uint8_t* pDataPtr)
{
uint8_t bStatus;

TWCR=(1 & lt; & lt; TWINT)|(1 & lt; & lt; TWEN)|(1 & lt; & lt; TWEA);
if ((bStatus=I2C_Ready()) == TWI_MRX_DATA_ACK)
*pDataPtr=TWDR;

return (bStatus);
}

//------------------------------------------------------------------------------
// Wys?anie bajtu
// Wej: bData - dna do wys?ania
// Wyj: Status wykonania operacji

uint8_t I2C_Send_Byte (uint8_t bData)
{
TWDR = bData;
TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWEN);
return (I2C_Ready());
}

//------------------------------------------------------------------------------
// Wys?anie bitu STOP

void I2C_Send_Stop (void)
{
TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWSTO)|(1 & lt; & lt; TWEN); // wys?anie STOP
}

//------------------------------------------------------------------------------
// Oczekiwanie na zako?czenie operacji
// Wyj: Status wykonania operacji

uint8_t I2C_Ready (void)
{
while (!(TWCR & (1 & lt; & lt; TWINT))); // oczekiwanie na zako?czenie operacji
return (TWSR & 0xF8); // wydzielenie Status
}

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


vga-rtc.zip > typedef.h

#ifndef _TYPEDEF_H
#define _TYPEDEF_H

typedef unsigned char uint8_t;
typedef unsigned int uint16_t;

#define OK 0
#define ERROR 1

#endif


vga-rtc.zip > MAIN.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - cześae g?ówna
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-GCC WINAVR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include & lt; avr/io.h & gt;
#include & lt; avr/pgmspace.h & gt;
#include & lt; avr/interrupt.h & gt;
#include " typedef.h "
#include " spi.h "
#include " vga.h "
#include " font0.h "
#include " display.h "
#include " i2c.h "
#include " rtc.h "

#define XTAL 8000000
#define COLOR1 ((WHITE) | (BLACK & lt; & lt; 3)) // kolor dla czasu
#define COLOR2 ((GREEN) | (BLACK & lt; & lt; 3)) // kolor dla daty
#define COLOR3 ((YELLOW) | (BLACK & lt; & lt; 3)) // kolor dla dnia tygodnia
#define COLOR_PRG ((RED) | (BLACK & lt; & lt; 3)) // kolor dla trybu programownia

volatile uint8_t bFlags;
#define SEC_F 0x01 // znacznik zmiany sekund
#define TIME_F 0x02 // znacznik zmiany czasu (minuty, godziny)
#define DATE_F 0x04 // znacznik zmiany daty
#define COLON_F 0x08 // znacznik wygaszenia dwukropka

volatile uint8_t bKey; // stan klawiszy po eliminacji drga?
volatile uint8_t bKeyPrev; // poprzedni stan klawiszy po eliminacji drga?
volatile uint8_t bKeySample; // próbka stanu portu klawiatury
#define KEY_ENTER 0x01
#define KEY_MINUS 0x02
#define KEY_PLUS 0x04

volatile uint8_t bPresc05; // dzielnik dla 0.5 sekundy
#define PRESC05_LOAD 20 // 20*25ms

#define KEY_Port PORTA // klawiatura na porcie A
#define KEY_Port_Pin PINA
#define KEY_Port_Dir DDRA
#define KEY_MASK 0x07 // KEY1=PA0, KEY2=PA1,KEY3=PA2

uint8_t Get_Key (void);

int main( void )
{
SPI_Init();

uint8_t bKeyPress;

// zainicjowanie portu SPI i I2C
SPI_Init();
I2C_Master_Init();

// zako?czenie sygna?u RESET dla karty VGA
SPI_Port |= (1 & lt; & lt; SPI_RESET);

// zainicjowanie 0 generatora znaków (33 znaki)
VGA_CharGen_Init (0, 0, 33, (uint8_t*)Font0_8_16);

// zainicjowanie 0 strony pami?ci Video
VGA_Video_Page_Clear (0);

// za??czenie karty, kusor podkreślenie, video z??czone
// tryb z miganiem i podświetleniem
VGA_Transmit (VGA_CONTROL, CTRL_VEN);

// zainicjowanie zegara RTC
RTC_Init();

// konfiguracja przerwania INT0
PORTD |= (1 & lt; & lt; PD2); // pull-up na linii INT0
DDRD & = ~(1 & lt; & lt; PD2); // INT0 jako wejście
MCUCR |= 1 & lt; & lt; ISC00 | 1 & lt; & lt; ISC01; // reakcja na zbocze opadaj?ce
GICR |= 1 & lt; & lt; INT0; // odblokowanie przerwania

// zainicjowanie portu klawiatury
KEY_Port = KEY_MASK; // pull-up dla klawiszy
KEY_Port_Dir =0x00; // wszystkie linie jako wejścia

// zainicjowanie Timera 0, cykliczne przerwanie co 25ms
// Timer clock = system clock / 1024, CTC mode
TCCR0 = (1 & lt; & lt; CS02)|(1 & lt; & lt; CS00)|(1 & lt; & lt; WGM01);
OCR0 = (XTAL/1024/40)-1; // 24.96ms
TIFR |= (1 & lt; & lt; OCF0); // skasowanie znacznika przerwania
TIMSK |= (1 & lt; & lt; OCIE0); // odblokowanie przerwania od Timera 0

// odczyt czasu i daty
RTC_Read_Time();
RTC_Read_Date();

// wymuszenie wyświetlenia czasu i daty
bFlags = SEC_F | TIME_F | DATE_F;

// odblokowanie przerwa?
sei();

while (1)
{
if (Get_Key() == KEY_ENTER) // wejście w tryb programowania zegara
{
GICR & = ~(1 & lt; & lt; INT0); // zablokowanie przerwania od RTC

// wyzerowanie sekund
Time.bcdSeconds=0x00;
Show_Seconds (COLOR1);

// ustawianie godzin
Show_Dots (DOTS_TOP_ONLY, 40, 4, COLOR1); // zapalenie dwukropka
Show_Dots (DOTS_TOP_ONLY, 38,10, COLOR1);
do
{
Show_Time (COLOR_PRG, COLOR1, COLOR1); // wyświetlenie czasu
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdHours,0x00,0x23);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdHours,0x00,0x23);
} while (!(bKeyPress & KEY_ENTER));

// ustawianie minut
do
{
Show_Time (COLOR1, COLOR_PRG, COLOR1); // wyświetlenie czasu
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdMinutes,0x00,0x59);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdMinutes,0x00,0x59);
} while (!(bKeyPress & KEY_ENTER));

Show_Time (COLOR1, COLOR1, COLOR1); // wyświetlenie czasu

// ustawianie dnia miesi?ca
do
{
Show_Date (COLOR_PRG,COLOR2,COLOR2,COLOR2); // wyświetlenie daty
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdDay,0x01,0x31);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdDay,0x01,0x31);
} while (!(bKeyPress & KEY_ENTER));

// ustawianie miesi?ca
do
{
Show_Date (COLOR2,COLOR_PRG,COLOR2,COLOR2); // wyświetlenie daty
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdMonth,0x01,0x12);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdMonth,0x01,0x12);
} while (!(bKeyPress & KEY_ENTER));

// ustawianie roku
do
{
Show_Date (COLOR2,COLOR2,COLOR_PRG,COLOR2); // wyświetlenie daty
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdYear,0x00,0x99);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdYear,0x00,0x99);
} while (!(bKeyPress & KEY_ENTER));

Show_Date (COLOR2,COLOR2,COLOR2,COLOR2); // wyświetlenie daty

// ustawianie dnia tygodnia
do
{
Show_WeekDay_Name (COLOR_PRG); // wyświetlenie dnia tygodnia
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bWeekDay,0x00,0x06);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bWeekDay,0x00,0x06);
} while (!(bKeyPress & KEY_ENTER));

// sprawdzenie poprawności dnia miesi?ca
if (Time.bcdDay & gt; MonthTable[Time.bcdMonth])
Time.bcdDay = MonthTable[Time.bcdMonth];

// zapis nowego czasu i daty do PCF8583
RTC_Write_Time();
RTC_Write_Date();

GICR |= 1 & lt; & lt; INT0; // odblokowanie przerwania od RTC

// wymuszenie wyświetlenia czasu i daty
bFlags |= SEC_F | TIME_F | DATE_F;
}

// odświerzanie sekund
if (bFlags & SEC_F)
{
bFlags & = ~(SEC_F | COLON_F); // skasowanie znaczników zmiany sekund
Show_Seconds (COLOR1);
Show_Dots (DOTS_TOP_ONLY, 40, 4, COLOR1); // zapalenie dwukropka
Show_Dots (DOTS_TOP_ONLY, 38,10, COLOR1);
bPresc05 = PRESC05_LOAD;
}

// odświerzanie godzin i minut
if (bFlags & TIME_F)
{
bFlags & = ~TIME_F; // skasowanie znacznika zmiany czasu
Show_Time (COLOR1, COLOR1, COLOR1); // wyświetlenie czasu
}

// odświerzanie daty
if (bFlags & DATE_F)
{
bFlags & = ~DATE_F ; // skasowanie znacznika
Show_Date (COLOR2,COLOR2,COLOR2,COLOR2); // wyświetlenie daty
Show_WeekDay_Name (COLOR3);
}

// miganie dwukropkiem
if (bFlags & COLON_F)
{
bFlags & = ~(COLON_F); // skasowanie znacznika wygaszenia dwukropka
Show_Dots (DOTS_NONE, 40, 4, COLOR1); // zgaszenie dwukropka
Show_Dots (DOTS_NONE, 38,10, COLOR1);
}
};

return (0);
}

//*****************************************************************************
// obs?uga przerwania od RTC (co 1 sekund?)
// - odczyt czasu i daty

ISR (INT0_vect)
{
RTC_Read_Time();
bFlags |= SEC_F; // znacznik zmiany sekund

if (!Time.bcdSeconds)
{
bFlags |= TIME_F; // znacznik zmiany czasu
if (!Time.bcdHours & & !Time.bcdMinutes)
{
RTC_Read_Date();
bFlags |= DATE_F; // znacznik zmiany daty
}
}
}

//*****************************************************************************
// obs?uga przerwania od TIMER0 (co 25ms)
// - obs?uga klawiatury
// - obs?uga migania dwukropkiem

ISR(TIMER0_COMP_vect)
{
uint8_t bTemp1,bTemp2;

// obs?uga klawiatury
bTemp1 = bKeySample;
bTemp2 = KEY_Port_Pin;
bKeySample = bTemp2;
bKey=(~((bTemp1^bTemp2) | bTemp2)) & KEY_MASK;

if (bPresc05--)
if (!bPresc05)
bFlags |= COLON_F;
}

//*****************************************************************************
//-----------------------------------------------------------------------------
// Procedura odczytu stanu klawiatury (bez repetycji)

uint8_t Get_Key (void)
{
uint8_t bTemp1,bTemp2;

bTemp1 = bKeyPrev;
bTemp2 = bKey;
bKeyPrev = bTemp2;
bTemp1= (bTemp1 ^ bTemp2) & bTemp2;

return (bTemp1);
}
//-----------------------------------------------------------------------------


vga-rtc.zip > TeleVGA.pdf

TeleVGA
Dokumentacja
wer. 1.00

Spis tre¶ci
Wprowadzenie ........................................................................................................................... 3
Opis zł±cz karty .......................................................................................................................... 4
Zł±cze komunikacyjne - J1 ...................................................................................................................................................... 4
Zł±cze monitora - J2 ................................................................................................................................................................ 4
Zł±cze serwisowe - J3 ............................................................................................................................................................... 4
Zł±cze zasilania - J4 (opcja) .................................................................................................................................................... 5

Schemat blokowy karty .............................................................................................................. 5
Rozmieszczenie zł±cz oraz rozstaw otworów montażowych ......................................................... 6
Komunikacja z kart± ................................................................................................................... 6
Poziomy napięd sygnałów interfejsu SPI ...................................................................................... 7
Zasilanie karty ............................................................................................................................ 7
Tabela rejestrów......................................................................................................................... 8
Rejestr VGA_CONTROL ............................................................................................................................................................ 8

Podział pamięci karty ................................................................................................................. 9
Programowanie karty ............................................................................................................... 10
Inicjalizacja ..................................................................................................................................................................................10
Programowanie generatora znaków .................................................................................................................................10
Czyszczenie pamięci obrazu ................................................................................................................................................11
Konfiguracja karty ....................................................................................................................................................................11
Tworzenie obrazu .....................................................................................................................................................................12
Przykłady .....................................................................................................................................................................................12

Przebiegi sygnałów synchronizacji poziomej i pionowej ............................................................ 14
Historia dokumentacji .............................................................................................................. 15

TeleVGA

Wprowadzenie
Moduł TeleVGA jest układem karty graficznej pracuj±cej w
trybie tekstowym. Rozdzielczo¶d obrazu karty to 30 linii po
80 znaków (640x480 punktów) z 3-bitow± głębi± kolorów.
Obsługuje dwie strony pamięci obrazu i 4 generatory
znaków (po 256 znaków każdy). Umożliwia jednoczesne
wy¶wietlanie znaków z różnych generatorów co pozwala na
tworzenie obrazu składaj±cego się z tekstu i semigrafiki.
Dzięki szeregowemu interfejsowi SPI wymaga tylko 4-6 linii
do podł±czenia mikrokontrolera. Karta przystosowana jest
do pracy z zasileniem 3.3V lub 5V (opcja), umożliwia
podł±czenie
monitora
poprzez
standardowe
zł±cze D-Sub (15HD).

Wymienione cechy sprawiaj±, że TeleVGA może
byd
dodatkowym
modułem
dla
nowoprojektowanych lub gotowych systemów
mikroprocesorowych. W prosty sposób rozbuduje
projekt o obsługę monitora np. panelu LCD.

Podstawowe cechy:
?
?
?
?
?
?
?
?
?
?
?

rozdzielczo¶d 30x80 znaków (tryb monitora 640x480 60Hz)
3-bitowa głębia koloru
4 generatory znaków (po 256 znaków każdy)
2 strony pamięci obrazu
2 rodzaje kursora
atrybuty podkre¶lenia i migania
interfejs szeregowy SPI
tryb niskiego poboru pr±du -,,u¶pienia"
zasilanie 3.3V lub 5V (opcja)
zł±cze monitora DB15-HD
zł±cze interfejsu i zasilania IDC10

3

TeleVGA

Opis zł±cz karty
Zł±cze komunikacyjne - J1
Pin
1
2
3
4
5
6

Symbol
CLK
MOSI
CS
MISO
RESET
SLEEP

7,8 3.3V
9,10 GND

Opis
Sygnał zegarowy
Sygnał danych
Sygnał wyboru karty
Sygnał danych
Sygnał resetu karty
Sygnał wybory trybu niskiego
poboru mocy
Zasilanie karty
Masa GND

IDC2x5 raster 2.54mm
(J1-CONTROL)

Zł±cze monitora - J2
Pin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Symbol
R
G
B
ID2
GND
R GND
G GND
B GND
KEY
SYNCGND
ID0
ID1
HSYNC
VSYNC
ID3

Opis
Sygnał koloru czerwonego
Sygnał koloru zielonego
Sygnał koloru niebieskiego
Niewykorzystane
Niewykorzystane
Masa GND
Masa GND
Masa GND
Niewykorzystane
Masa GND
Niewykorzystane
Niewykorzystane
Sygnał synchronizacji poziomej
Sygnał synchronizacji pionowej
Niewykorzystane

Zł±cze monitora D-Sub 15HD żeoskie
(J2-VGA)

Zł±cze serwisowe - J3
Pin
1
2
3
4
5
6

Symbol
GND
3.3V
TDI
TDO
TCK
TMS

Opis
Masa GND
Zasilanie 3.3V
JTAG-TDI
JTAG-TDO
JTAG-TCK
JTAG-TMS

Pin6x1 raster 1,27mm
(J3-JTAG)

4

TeleVGA

Zł±cze zasilania - J4 (opcja)
Pin Symbol
1 GND
2 5V

Opis
Masa GND
Zasilanie 5V
Pin 2x1 raster 2.54mm.
(J4-5V)

Zł±cze występuje tylko w wersji do systemów zasilanych napięciem 5V.

Schemat blokowy karty

5

TeleVGA

Rozmieszczenie zł±cz oraz rozstaw otworów montażowych

Komunikacja z kart±
Komunikacja z kart± odbywa się poprzez interfejs szeregowy SPI składaj±cy się z następuj±cych linii:
Nazwa sygnału
CS
CLK
MOSI
MISO
RESET*
SLEEP**

Funkcja

MASTER

VGA

Sygnał wyboru karty
Sygnał wyboru karty
Sygnał danych
Sygnał danych
Sygnał resetu karty
Sygnał wybory trybu niskiego poboru mocy

Wyj¶cie
Wyj¶cie
Wyj¶cie
Wej¶cie
Wyj¶cie
Wyj¶cie

Wej¶cie
Wej¶cie
Wej¶cie
Wyj¶cie
Wej¶cie
Wej¶cie

*Sygnał RESET inicjuje tylko układ generacji sygnałów synchronizacji i video oraz powoduje wyzerowanie wszystkich
rejestrów jednak nie wpływa na zawarto¶ci pamięci VRAM i CGRAM.
**Sygnał SLEEP powoduje przej¶cie karty w tryb obniżonego poboru mocy. Zawarto¶d pamięci VRAM,CGRA M zostaje
zachowana. Po wyj¶ciu z trybu SLEEP karta musi zostad zresetowana a rejestry ponownie skonfigurowane.

Maksymalna częstotliwo¶d zegara CLK wynosi 10MHz. Przykładowy przebieg transmisji SPi
przedstawiono na rysunku.

6

TeleVGA

Poziomy napięd sygnałów interfejsu SPI
Tabela dla VCC = 3,3 V
Min
[V]
VIH
VIL
VOH
VOL

IOH = -50uA
IOH = -4mA
IOL = 50uA
IOL = 4mA

Max
[V]

2,4
3,2
2,8
-

5*
0,8
0,1
0,4

Opis
Napięcie wej¶ciowe dla stanu ,,1"
Napięcie wej¶ciowe dla stanu ,,0"
Napięcie wyj¶ciowe dla stanu ,,1"
Napięcie wyj¶ciowe dla stanu ,,0"

*Linie wej¶ciowe s± odporne na napięcie +5 V

Układ nadrzędny steruj± kart± poprzez zapis i odczyt 7 rejestrów (patrz ,,Tabela rejestrów").
Dostęp do rejestru składa się z dwóch etapów:
1. Pierwszy etap to przesłanie adresu rejestru i znacznika kierunku
2. Drugi etap do przesłanie danych do/z rejestru. Karta rozpoznaje pocz±tek cyklu na
podstawie zmiany sygnału CS z 0 na 1 a koniec na podstawie zmiany sygnału CS z 1 na 0.
Dane do karty s± zapisywane na narastaj±cym zboczu sygnału CLK a odczytywane na opadaj±cym
zboczu CLK. (SPI Mode 0). Wszystkie transmisje odbywaj± się w cyklu najstarszy bit (MSB) pierwszy,
najmłodszy bit (LSB) ostatni.

Zasilanie karty
Karta wymaga zasilania stabilizowanym napięciem 3,3 V. Pobór pr±du wynosi & lt; 35mA dla trybu
aktywnego (SLEEP="0") a & lt; 300uA dla trybu u¶pienia (SLEEP="1").
W przypadku współpracy karty z systemami zasilanymi napięciem +5 V istnieje opcja montażu na
karcie, dodatkowego stabilizatora napięcie +3,3 V. W takim przypadku karta zasilana jest przez
zł±cze J4 a PINy 7 i 8 na zł±czu J1 pozostaj± niewykorzystane.

7

TeleVGA

Tabela rejestrów
Nazwa rejestru

Adres
rejestru

Funkcja rejestru

Bit
7

6

5

4

3

2

1

0

A5

A4

A3

A2

VGA_ADDR_WR_LO

80h

Adres VRAM/CGRAM zapis

A7 A6

A1

A0

VGA_ADDR_WR_HI
VGA_ADDR_RD_LO
VGA_ADDR_RD_HI

90h
A0h
B0h

Adres VRAM/CGRAM zapis
Adres VRAM/CGRAM odczyt
Adres VRAM/CGRAM odczyt

A15 A14 A13 A12 A11 A10 A9
A7 A6 A5 A4 A3 A2 A1
A15 A14 A13 A12 A11 A10 A9

A8
A0
A8

VGA_DATA_WR
VGA_DATA_RD

C0h
40h

Dana do zapisu VRAM/CGRAM
Dana odczytana z RAM/CGRAM

D7 D6
D7 D6

D0
D0

VGA_CONTROL

D0h

Konfiguracja karty

LCEN

D5
D5

D4
D4

D3
D3

W tabeli przedstawiono opis poszczególnych bitów dla rejestru VGA_CONTROL
Nazwa bitu

Funkcja

LCEN
VM

kursor podwójnej szeroko¶ci
tryb video
? 0 - tryb z czterema generatorami znaków
? 1 - tryb z atrybutami migania i podkre¶lenia znaków
zał±czenie sygnału video
tryb kursora
? 0 - kursor podkre¶lenie
? 1 - kursor pełny
zał±czenie kursora
numer strony VRAM
numer generatora znaków (tylko gdy VM=0)

CEN
PNR
CHG0, CHG1

8

D1
D1

VM VEN CT CEN PNR CHG1 CHG0

Rejestr VGA_CONTROL

VEN
CT

D2
D2

Dostęp
zapis
zapis
zapis
zapis
zapis
odczyt
zapis

TeleVGA

Podział pamięci karty
Pamięd karty podzielona jest na 6 obszarów:
Nazwa

Funkcja

Adres

W ielko¶d

VRAM VPAGE0
VRAM VPAGE1
CGRAM CHARGEN0
CGRAM CHARGEN1
CGRAM CHARGEN2
CGRAM CHARGEN3

Pamięd obrazu strona 0
Pamięd obrazu strona 1
Pamięd generatora znaków 0
Pamięd generatora znaków 1
Pamięd generatora znaków 2
Pamięd generatora znaków 3

0000h
2000h
4000h
5000h
6000h
7000h

8192 bajty (4800+3392)*
8192 bajty (4800+3392)*
4096 bajtów
4096 bajtów
4096 bajtów
4096 bajtów

*3392 bajty niewykorzystane, mog± zostad użyte jako np. zewnętrzny RAM dla mikroprocesora.

Każdy wy¶wietlany znak jest opisywany poprzez kod znaku i atrybuty wy¶wietlania.
Atrybuty opisuj± kolor znaku, kolor tła, numer generatora znaków (dla VideoMode=0), zał±czenie
migania BLINK (dla VideoMode=1) i zał±czenie podkre¶lenia UNDERLINE (dla VideoMode=1).

Pozycja bitu

Funkcja

Uwagi

B2,B1,B0

Kolor znaku

B5,B4,B3

Kolor tła

B6

Miganie (BLINK)

Tylko gdy VM=0

B7

Podkre¶lenie(UNDERLINE)

Tylko gdy VM=0

B7,B6

Numer generatora znaków

Tylko gdy VM=1

000 - czarny (BLACK)
001 - czerwony (RED)
010 - zielony (GREEN)
100 - niebieski (BLUE)
011 - żółty (YELLOW)
101 - purpurowy (MAGENTA)
110 - cyjan (CYAN)
111 - biały (WHITE)
000 - czarny (BLACK)
001 - czerwony (RED)
010 - zielony (GREEN)
100 - niebieski (BLUE)
011 - żółty (YELLOW)
101 - purpurowy (MAGENTA)
110 - cyjan (CYAN)
111 - biały (WHITE)

9

TeleVGA

Programowanie karty
Inicjalizacja
Proces inicjalizacji karty powinien przebiegad w następuj±cy sposób:
? zał±czenie zasilania karty
? ustawnie linii CS i SLEEP w stan nieaktywny
? podanie impulsu 0- & gt; 1- & gt; 0 na linii RESET
? zaprogramowanie jednego lub wszystkich generatorów znaków
? wyczyszczenie pamięci VRAM strona0 i strona1
? skonfigurowanie trybu pracy karty poprzez zapis do rejestru VGA_CTRL
Od tego momentu karta jest gotowa do pracy.

Programowanie generatora znaków
Wy¶wietlane znaki maj± format 8x16 punktów. Definicja pojedynczego znaku składa się z 16
bajtów. Przykładowy znak i opowiadaj±cy mu ci±g danych przedstawiono poniżej:
18h
18h
7Ch
C6h
C2h
C0h
7Ch
06h
06h
86h
C6h
7Ch
18h
18h
00h
00h

Programowanie generatora znaków polega na:
1. Obliczeniu adresu definiowanego znaku. Adres wyliczany jest w następuj±cy sposób:
adres pocz±tku wybranego generatora znaków + numer znaku*16
2. Zapisaniu wyliczonego adresu do rejestrów VGA_ADDR_WR_LO (młodsze 8 bitów) oraz
VGA_ADDR_WR_HI (starsze 8 bitów). Wymagana jest kolejno¶d zapisu LO HI.
3. Zapisaniu 16 bajtów danych do rejsteru VGA_DATA_WR
Zapis do rejestru VGA_DATA_RD powoduje automatyczne inkrementację adresu (rejestry
VGA_ADDR_WR_HI i VGA_ADDR_WR_LO). Definiuj±c kolejny znak nie jest wymagane ustawianie
adresu a tylko dalszy zapis do rejestru VGA_DATA_WR.
Po osi±gnięciu kooca pamięci wybranego generatora, następuje przesunięcie adresu na następny
generator.
UWAGA:
W przypadku zapisu definicji ostatniego znaku w generatorze CHARGEN3 nast±pi ustawienie adresu
na 0000h czyli pocz±tek pamięci obrazu VRAM strona 0.
10

TeleVGA

Czyszczenie pamięci obrazu
Wyczyszczenie pamięci obrazu polega na wypełnieniu pamięci VRAM znakami ,,Spacji".

Konfiguracja karty
Skonfigurowanie karty polega na zapisie bajtu konfiguracji do rejestru VGA_CTRL. Aby nast±piło
zał±czenie sygnału video wymagane jest ustawienie bitu VEN (Video Enable). Karta może pracowad
w dwóch trybach:
? VM (Video Mode)=0
? VM=1
Pierwszy tryb umożliwia wy¶wietlanie znaków z czterech dostępnych generatorów. Mamy tym
samych dostępne 1024 znaki, co pozwala na wy¶wietlanie tekstu i np. definiowanej sami-grafiki.
Tryb drugi umożliwia dostęp tylko do jednego generatora znaków jednak powala nadawad znakom
dodatkowe atrybuty migania (BLINK) i podkre¶lenia (UNDERLINE). W przypadku tego trybu bity
CHG0 (Character Generator 0) i CHG1 (Charakter Generator 1) okre¶laj±, który generator znaków
jest wykorzystywany przy wy¶wietlaniu.
Praca kursora definiowana jest poprzez 3 bity CEN (Kursor Enable), CT (Kursor Type) i CLEN (Large
Kursor Enable).
Bit CEN odpowiada za zał±czanie i wył±czanie wy¶wietlania kursora.
Bit CT okre¶la typ wy¶wietlanego kursora, gdy CT=0 wy¶wietlany jest kursor typu migaj±ce
podkre¶lenie natomiast gdy CT=1 wy¶wietlany jest kursor typu migaj±ce pole.
Bit LCEN zał±cza wy¶wietlanie kursora o podwójnej szeroko¶ci. Obsługa wy¶wietlania znaków o
podwójnej szeroko¶ci (16x16 punktów) jest realizowana w trybie programowym. Wymaga
zdefiniowania lewej i prawej czę¶ci znaku oraz odpowiednie ich wy¶wietlenie. Gdy LCEN=1 to
kursor jest automatycznie wy¶wietlany na obydwu czę¶ciach znaku.
Bit PNR (Page Numer) okre¶la, która strona pamięci VRAM jest aktualnie wykorzystywana do
wy¶wietlania. Karta umożliwia wy¶wietlanie jednej strony pamięci gdy w międzyczasie możliwe jest
przygotowywanie informacji na drugiej stronie.

11

TeleVGA

Tworzenie obrazu
Wy¶wietlenie znaku na okre¶lonej pozycji na ekranie polega na:
1. Obliczeniu adresu kursora. Adres kursora wyliczany jest w następuj±cy sposób:
Adres pocz±tku strony pamięci VRAM + pozycjaY *256 + pozycja X*2.
Pozycje kursora s± numerowane od 0-79 dla osi X oraz od 0-29 dla osi Y.
2. Zapisaniu wyliczonego adresu kursora do rejestrów VGA_ADDR_WR_LO (młodsze 8 bitów)
oraz VGA_ADDR_WR_HI (starsze 8 bitów). Wymagana jest kolejno¶d zapisu LO HI.
3. Zapisaniu kodu znaku do rejestru VGA_DATA_WR
4. Zapisaniu atrybutu znaku do rejestru VGA_DATA_WR
Zapis do rejestru VGA_DATA_RD powoduje automatyczne inkrementację adresu kursora
(rejestryVGA_ADDR_WR_HI i VGA_ADDR_WR_LO). Wy¶wietlaj±c znak na kolejnej pozycji nie jest
wymagane ustawianie adresu kursora. Po osi±gnięciu kooca linii nast±pi przej¶cie kursora do nowej
linii. Należy pamiętad, że zawsze zapisywana jest para danych kod znaku i jego atrybut.
Karta umożliwia odczyt pamięci VRAM i CGRAM. Dzięki temu możliwe jest uproszczenie procedur
przewijania ekranu lub jego fragmentów (scrolling). Procedura odczytu znaku i jego atrybutów jest
analogiczna do procedury zapisu z tym że po zapisaniu adresu kursora musi nast±pid dwukrotny
odczyt z rejestru VGA_DATA_RD.

Przykłady
Przykładowe procedury w języku C przedstawiono poniżej.
Pełna biblioteka obsługi karty i przykłady s± dostępne na stronie www.televox.pl
// Wy¶wietlenie czerwonego znaku 'A' na pozycji X=5 Y=7
bCurX=5;
bCurY=7;
VGA_Write_Addr_Set (bCurY & lt; & lt; 8 | bcurX & lt; & lt; 1);
VGA_Put_Char ( 'A', BLACK & lt; & lt; 3|RED);
//-----------------------------------------------------------------------------// Wy¶wietlenie znaku na aktualnej pozycji kursora.
// Wej: bChar - kod znaku
//
bAttr - atrybut znaku
void VGA_Put_Char (uint8_t bChar, uint8_t bAttr)
{
VGA_Transmit (VGA_DATA_WR, bChar);
VGA_Transmit (VGA_DATA_WR, bAttr);
}
//-----------------------------------------------------------------------------// Zapis adresu do pary rejestrów VGA ADDR_WR (ustawienie pozycji kursora)
// Wej: wData - adres
void VGA_Write_Addr_Set (uint16_t wData)
{
VGA_Transmit (VGA_ADDR_WR_LO, wData & 0xFF);
VGA_Transmit (VGA_ADDR_WR_HI, (wData & gt; & gt; 8) & 0xFF);
}

12

TeleVGA
//----------------------------------------------------------------------------// Zapis rejestru karty VGA
// Wej: bRegAdrr - adres rejestru
//
bData - dana do zapisu
void VGA_Transmit (uint8_t bRegAddr, uint8_t bData)
{
SPI_CS = 1;
SPI_Transmit (bRegAddr);
SPI_Transmit (bData);
SPI_CS = 0;
while (SPI_MISO);
}

// oczekiwanie na koniec cyklu zapisu
// karta sygnalizuje gotowo¶ć poprzez wystawienie '0'
// na linii MISO

13

TeleVGA

Przebiegi sygnałów synchronizacji poziomej i pionowej
Obraz
Ilo¶d punktów w poziomie
Ilo¶d linii w pionie
Synchronizacja pozioma (H)
Częstotliwo¶d
Polaryzacja (Polarity)
Okres (Period)
Aktywny obszar (Active Area)
Szeroko¶d impulsu (Pulse Width)
Okres nieaktywny przed impulsem(Front Porch)
Okres nieaktywny za impulsem (Back Porch)
Synchronizacja pionowa (V)
Częstotliwo¶d
Polaryzacja (Polarity)
Okres (Period)
Aktywny obszar (Active Area)
Szeroko¶d impulsu (Pulse Width)
Okres nieaktywny przed impulsem(Front Porch)
Okres nieaktywny za impulsem (Back Porch)

Warto¶d
640
480
31.25
32
25.6
3.84
0.64
1.92
60.56
16.512
15.36
64
64
896

Synchronizacja pozioma (H)

Synchronizacja pionowa (V)

14

Jednostka
kHz
[?s]
[?s]
[?s]
[?s]
[?s]
Hz
[ms]
[ms]
[?s]
[?s]
[?s]

TeleVGA

Historia dokumentacji
Wersja
1.00

Data
Opis zmian
22 listopada 2010

-

15

ul. Dobrego Pasterza 100
31-416 Kraków
tel (012) 415-67-00
fax (012) 415-67-15
e-mail: biuro@televox.pl
http://www.televox.pl


vga-rtc.zip > DISPLAY.H

#ifndef _DISPLAY_H_
#define _DISPLAY_H_

#define DOTS_NONE 0
#define DOTS_BOTTOM_ONLY 1
#define DOTS_TOP_ONLY 2
#define DOTS_TOP_BOTTOM 3

#define DOT_NONE 0
#define DOT_ON 1

#define BLANK 10
#define CHAR_A 11
#define CHAR_PLA 'A'+26
#define CHAR_PLS 'A'+27
#define CHAR_PP 'A'+28
#define CHAR_PO 'A'+29
#define CHAR_PN 'A'+30
#define CHAR_PE 'A'+31
#define CHAR_PD 'A'+32
#define CHAR_PZ 'A'+33
#define CHAR_PA 'A'+34
#define CHAR_PLL 'A'+35
#define CHAR_PK 'A'+36

// prototypy funkcji
void Show_Seconds (uint8_t bColorS);
void Show_Time (uint8_t bColorH, uint8_t bColorM, uint8_t bColorF);
void Show_Date (uint8_t bColorD, uint8_t bColorM, uint8_t bColorY, uint8_t bColorF);
void Show_WeekDay_Name (uint8_t bColor);

void Show_Frame (uint8_t bCurX, uint8_t bCurY, uint8_t bSizeX, uint8_t bSizeY, uint8_t bColor);
void Show_Dots (uint8_t bDots, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Digit_Big (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Digit_Small (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Dot_Small (uint8_t bDot, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);
void Show_Digit_Mini (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor);

#endif


vga-rtc.zip > RTC.H

#ifndef _RTC_H_
#define _RTC_H_


#define PCF_Status1 0x00 // rejestr statusowy zegara
#define PCF_Hundredths 0x01 // rejestr setnych sekundy
#define PCF_Seconds 0x02 // rejestr sekund
#define PCF_Minutes 0x03 // rejestr minut
#define PCF_Hours 0x04 // rejestr godzin
#define PCF_Date 0x05 // rejestr daty i roku
#define PCF_Month 0x06 // rejestr miesiecy i dnia tygodnia
#define PCF_Timer 0x07 // rejestr timera
#define PCF_Al_Ctrl 0x08 // rejestr sterujacy alarmu
#define PCF_Al_Hundredths 0x09 // rejestr alarmu setne sekundy
#define PCF_Al_Seconds 0x0A // rejestr alarmu sekundy
#define PCF_Al_Minutes 0x0B // rejestr alarmu minuty
#define PCF_Al_Hours 0x0C // rejestr alarmu godziny
#define PCF_Al_Day 0x0D // rejestr alarmu dzie?
#define PCF_Al_WeekDay 0x0E // rejestr alarmu dni tygodnia
#define PCF_Al_Timer 0x0F // rejestr alarmu timer

#define PCF_Year 0x10

typedef struct // struct for time information
{
uint8_t bcdSeconds;
uint8_t bcdMinutes;
uint8_t bcdHours;
uint8_t bcdDay;
uint8_t bcdMonth;
uint8_t bcdYear;
uint8_t bWeekDay; //0-6 0=niedziela
} TIME;

// prototypy funkcji
void RTC_Init (void);
void RTC_Read_Time (void);
void RTC_Write_Time (void);
void RTC_Read_Date (void);
void RTC_Write_Date (void);

uint8_t Test_BCD (uint8_t bcdData, uint8_t bcdMin, uint8_t bcdMax);
void Inc_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax);
void Dec_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax);

extern TIME Time; // czas i data
extern const __flash uint8_t MonthTable [19];

#endif


vga-rtc.zip > FONT0.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - definicja znaków
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-IAR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include " typedef.h "
#include " font0.h "

const __flash uint8_t Font0_8_16 [33*16]=
{
// dwie puste punkty cz?śae A
// dwie puste punkty cz?śae B
// dwie puste punkty cz?śae C
// 0x00
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// pe?ny punkt górny, pusty punkt dolny, cz?śae A
// 0x03
0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,
0x00,0x00,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xF8,0xF8,

// pe?ny punkt górny, pusty punkt dolny, cz?śae B
// 0x06
0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// pusty punkt górny, pe?ny punkt dolny, cz?śae B
// 0x09
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,

// pusty punkt górny, pe?ny punkt dolny, cz?śae C
// 0x0C
0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0x00,0x00,
0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xF8,0xF8,0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,

// pe?ny punkt górny. pe?ny punkt dolny, cz?śae B
// 0x0F
0x1F,0x0F,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x0F,0x1F,
0xFF,0xFF,0xFF,0xFF,0xFF,0x3C,0x00,0x00,0x00,0x00,0x3C,0xFF,0xFF,0xFF,0xFF,0xFF,
0xF8,0xF0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xF0,0xF8,

// kreska pionowa
// 0x12
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,

// kreska pozioma
// 0x13
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// lewy górny naro?nik
// 0x14
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,

// lewy dolny naro?nik
// 0x15
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// prawy górny naro?nik
// 0x16
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,

// prawy dolny naro?nik
// 0x17
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// ma?a punkt lewa po?owa
// 0x18
0x00,0x00,0x03,0x0F,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x0F,0x03,0x00,0x00,

// ma?a punkt prawa po?owa
// 0x19
0x00,0x00,0xC0,0xF0,0xF8,0xF8,0xFC,0xFC,0xFC,0xFC,0xF8,0xF8,0xF0,0xC0,0x00,0x00,

// pusty punkt górny, pe?ny punkt dolny
// 0x1A
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,

// pe?ny punkt górny, pusty punkt dolny
// 0x1B
0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// pe?ny punkt górny, pe?ny punkt dolny
// 0x1C
0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x7E,0x3C,0x00,

// 0x1D
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

// 0x20
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};


vga-rtc.zip > I2C.H

#ifndef _I2C_H_
#define _I2C_H_

// dla zegara 8MHz cz?stotliowśae szyny I2C=100kHz
// F_i2c=Fosc/(16+2*TWBR*2^TWPS)

#define TWI_Port PORTC
#define SCL PORTC_Bit0
#define SDA PORTC_Bit1

#define TWI_TWBR 0x22 // TWI Bit Rate Register setting.
#define TWI_TWPS 0x00 // Prescaler = 00

#define TWI_START 0x08 // START has been transmitted
#define TWI_REP_START 0x10 // Repeated START has been transmitted
#define TWI_MTX_ADR_ACK 0x18 // SLA+W has been tramsmitted and ACK received
#define TWI_MTX_DATA_ACK 0x28 // Data byte has been tramsmitted and ACK received

#define TWI_MRX_ADR_ACK 0x40 // SLA+R has been tramsmitted and ACK received
#define TWI_MRX_DATA_ACK 0x50 // Data byte has been received and ACK transmited
#define TWI_MRX_DATA_NACK 0x58 // Data byte has been received and NACK transmited

// adres slave dla PCF8583
#define SLAVE_ADDR_WR 0xA0
#define SLAVE_ADDR_RD 0xA1

// prototypy funkcji
void I2C_Master_Init (void);
uint8_t I2C_Xmit (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr);
uint8_t I2C_Recv (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr);

uint8_t I2C_Send_Start (void);
uint8_t I2C_Get_ByteLast (uint8_t* pDataPtr);
uint8_t I2C_Get_Byte (uint8_t* pDataPtr);
uint8_t I2C_Send_Byte (uint8_t bData);
void I2C_Send_Stop (void);
uint8_t I2C_Ready (void);

extern uint8_t tI2CBuffer[4]; // bufor i2C



#endif


vga-rtc.zip > SPI.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi portu SPI
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-IAR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include & lt; ioavr.h & gt;
#include & lt; intrinsics.h & gt;
#include " typedef.h "
#include " spi.h "

//------------------------------------------------------------------------------
// Inicjalizacja portu SPI
// Tryb 1 , Master, F=Fosc/4
// Linie RESET i SLEEP = 0

void SPI_Init (void)
{
//linie MOSI,SCK,CS,RESET_SLEEP=0, MISO=1
SPI_Port |= (1 & lt; & lt; SPI_MISO_Bit) | (1 & lt; & lt; SPI_MOSI_Bit);
SPI_Port & = ~( (1 & lt; & lt; SPI_MOSI_Bit) | (1 & lt; & lt; SPI_SCK_Bit) | (1 & lt; & lt; SPI_CS_Bit) |
(1 & lt; & lt; SPI_RESET_Bit) | (1 & lt; & lt; SPI_SLEEP_Bit));

//linie MOSI,SCK,CS,RESET_SLEEP jako wyj, MISO jako wej.
SPI_Port_Dir |= (1 & lt; & lt; SPI_MOSI_Bit) | (1 & lt; & lt; SPI_SCK_Bit) | (1 & lt; & lt; SPI_CS_Bit) |
(1 & lt; & lt; SPI_RESET_Bit) | (1 & lt; & lt; SPI_SLEEP_Bit);
SPI_Port_Dir & = ~(1 & lt; & lt; SPI_MISO_Bit);

// Fosc/2, SPI tryb 1, Master, Enable
SPCR= (1 & lt; & lt; SPE) | (1 & lt; & lt; MSTR);
SPSR= 1 & lt; & lt; SPI2X;
}

//------------------------------------------------------------------------------
// Transmisja bajtu na szyn? SPI.

void SPI_Transmit (uint8_t bData)
{
SPDR= bData;
while (! (SPSR & (1 & lt; & lt; SPIF)));
}

//------------------------------------------------------------------------------
// Odbiór bajtu z szyny SPI. Transmitowany bajt dummy=0.

uint8_t SPI_Receive (void)
{
SPDR= 0;
while (! (SPSR & (1 & lt; & lt; SPIF)));
return (SPDR);
}


vga-rtc.zip > VGA.H

#ifndef _VGA_H_
#define _VGA_H_

// definica adresów rejestrów karty VGA
#define VGA_ADDR_WR_LO 0x80 // adres kursora/generatora znaków LSB dla zapisu (tylko zapis)
#define VGA_ADDR_WR_HI 0x90 // adres kursora/generatora znaków MSB dla zapisu (tylko zapis)
#define VGA_ADDR_RD_LO 0xA0 // adres kursora/generatora znaków LSB dla odczytu (tylko zapis)
#define VGA_ADDR_RD_HI 0xB0 // adres kursora/generatora znaków MSB dla odczytu (tylko zapis)
#define VGA_DATA_WR 0xC0 // dana do zapisu (tylko zapis)
#define VGA_DATA_RD 0x40 // dana do odczytu (tylko odczyt)
#define VGA_CONTROL 0xD0 // konfiguracja karty (tylko zapis)

// drfinicja bitów konfiguracujnych (rejestr VGA_CONTROL)
#define CTRL_CHG0 0x01 // numer generatora znaków dla VM=0
#define CTRL_CHG1 0x02 //
#define CTRL_PNR 0x04 // numer strony video
#define CTRL_CEN 0x08 // za??czenie kursora
#define CTRL_CT 0x10 // rodzaj kursora
#define CTRL_VEN 0x20 // za??czenie video
#define CTRL_VM 0x40 // tryb video
#define CTRL_LCEN 0x80 // za??czenie podwójnego kursora

// definicja adresów pami?ci RAM karty VGA
#define VPAGE0_ADDR 0x0000 // adres pocz?tku 0 strony pami?ci Video
#define VPAGE1_ADDR 0x2000 // adres pocz?tku 1 strony pami?ci Video
#define CHARGEN0_ADDR 0x4000 // adres pocz?tku 0 genertora znaków
#define CHARGEN1_ADDR 0x5000 // adres pocz?tku 1 genertora znaków
#define CHARGEN2_ADDR 0x6000 // adres pocz?tku 2 genertora znaków
#define CHARGEN3_ADDR 0x7000 // adres pocz?tku 3 genertora znaków

#define VPAGE_SIZE 2400 // rozmiar strony graficznej 80*30

// definicja bitów konfiguracyjnych atrybutu znaków
#define BLACK 0x00
#define RED 0x01
#define GREEN 0x02
#define BLUE 0x04
#define YELLOW RED+GREEN
#define MAGENTA RED+BLUE
#define CYAN GREEN+BLUE
#define WHITE RED+GREEN+BLUE
#define BLINK 0x40
#define UNDERLINE 0x80

// prototypy funkcji
void VGA_CharGen_Init (uint8_t bCharGenNr, uint8_t bCharStart, uint8_t bCharEnd, uint8_t __flash * pCharDef);
void VGA_Video_Page_Clear (uint8_t bPageNr);
void VGA_Put_Char (uint8_t bChar, uint8_t bAttr);

void VGA_Write_Addr_Set (uint16_t wAddr);
void VGA_Read_Addr_Set (uint16_t wAddr);

void VGA_Transmit (uint8_t bRegAddr, uint8_t bData);
uint8_t VGA_Receive (void);

#endif


vga-rtc.zip > RTC.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi zegara RTC (PCF8583)
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-IAR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

#include & lt; ioavr.h & gt;
#include & lt; intrinsics.h & gt;
#include " typedef.h "
#include " i2c.h "
#include " rtc.h "

TIME Time; // czas i data

// tablica d?ugości miesi?cy
const __flash uint8_t MonthTable [19]=
{0x0,0x31,0x29,0x31,0x30,0x31,0x30,0x31,0x31,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
0x31,0x30,0x31};

//-----------------------------------------------------------------------------
// Procedura inicjalizacji RTC

void RTC_Init (void)
{
tI2CBuffer[0]=0x00; // RTC w??czony, Alarmy i Timer wy??czone
I2C_Xmit (1, PCF_Status1, tI2CBuffer);
}

//-----------------------------------------------------------------------------
// Procedura odczytu czasu z RTC
// Wykonywany jest test poprawności odczytanego czasu (format BCD + zakresy)
// W przypadku b??du zapisywany jest do RTC czas = 12:00:00

void RTC_Read_Time (void)
{
I2C_Recv (3, PCF_Seconds, tI2CBuffer); // odczyt czasu

// test poprawności formatu czasu
if (Test_BCD (tI2CBuffer[0],0x00,0x59) == OK)
if (Test_BCD (tI2CBuffer[1],0x00,0x59)== OK)
if (Test_BCD (tI2CBuffer[2],0x00,0x23)==OK)
{
Time.bcdSeconds = tI2CBuffer[0];
Time.bcdMinutes = tI2CBuffer[1];
Time.bcdHours = tI2CBuffer[2];
return;
}

// w przypadku b??du odczytu ustawiamy 12:00:00
Time.bcdSeconds = 0x00;
Time.bcdMinutes = 0x00;
Time.bcdHours = 0x12;
RTC_Write_Time();
}


//-----------------------------------------------------------------------------
// Procedura zapisu czasu do RTC

void RTC_Write_Time (void)
{
tI2CBuffer[0] = Time.bcdSeconds;
tI2CBuffer[1] = Time.bcdMinutes;
tI2CBuffer[2] = Time.bcdHours;
I2C_Xmit (3, PCF_Seconds, tI2CBuffer); // zapis czasu
}

//-----------------------------------------------------------------------------
// Procedura odczytu daty z RTC
// Wykonywany jest test poprawności odczytanej daty (format BCD + zakresy)
// W przypadku b??du zapisywana jest do RTC data = 01:01:10

void RTC_Read_Date (void)
{
I2C_Recv (2, PCF_Date, tI2CBuffer); // odczyt daty
I2C_Recv (1, PCF_Year, & tI2CBuffer[2]); // odczyt roku

// " rozpakowanie " danych
Time.bcdDay = tI2CBuffer[0] & 0x3F;
Time.bWeekDay = tI2CBuffer[1] & gt; & gt; 5;
Time.bcdMonth = tI2CBuffer[1] & 0x1F;
Time.bcdYear = tI2CBuffer[2];

// test poprawności formatu daty
if (Test_BCD (Time.bcdDay,0x01,0x31) == OK)
if (Test_BCD (Time.bcdMonth,0x01,0x12) == OK)
if (Test_BCD (Time.bcdYear,0x00,0x99) == OK)
if (Time.bWeekDay & lt; 7)
if (Time.bcdDay & lt; = MonthTable[Time.bcdMonth])
return;

// w przypadku b??du odczytu ustawiamy 1:01:2010 pi?tek
Time.bcdDay = 0x01;
Time.bWeekDay = 5;
Time.bcdMonth = 0x01;
Time.bcdYear = 0x10;
RTC_Write_Date();
}

//-----------------------------------------------------------------------------
// Procedura zapisu daty do RTC

void RTC_Write_Date (void)
{
// " spakowanie danych
tI2CBuffer[0] = Time.bcdDay;
tI2CBuffer[1] = (Time.bWeekDay & lt; & lt; 5) | Time.bcdMonth;
tI2CBuffer[2] = Time.bcdYear;

I2C_Xmit (2, PCF_Date, tI2CBuffer); // zapis daty
I2C_Xmit (1, PCF_Year, & tI2CBuffer[2]); // zapis roku
}

//-----------------------------------------------------------------------------
// Procedura testu formatu i zakresu BCD
// Wej: bcdData - dana do testów
// bcdMin - dolny dozwolony zakres
// bcdMax - górny dozwolony zakres
// Wyj: wynik testu OK/ERROR

uint8_t Test_BCD (uint8_t bcdData, uint8_t bcdMin, uint8_t bcdMax)
{
if ((bcdData & 0x0F) & lt; 0x0A & & (bcdData & 0xF0) & lt; 0xA0) // test formatu
if ( bcdData & gt; = bcdMin & & bcdData & lt; = bcdMax) // test zakresu
return (OK);

return (ERROR);
}

//-----------------------------------------------------------------------------
// Procedura zwi?kszaj?ca dan? w formacie BCD o 1
// Wej: pData - wskaźnik na dan?
// bcdMin, bcdMax - dozwolony zakres danej

void Dec_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax)
{
if (*pData == bcdMin)
*pData = bcdMax;
else
{
if ((*pData & 0x0F) == 0x00)
*pData-=7;
else
*pData-=1;
}
}
//-----------------------------------------------------------------------------
// Procedura zwi?kszaj?ca dan? w formacie BCD o 1
// Wej: pData - wskaźnik na dan?
// bcdMin, bcdMax - dozwolony zakres danej

void Inc_BCD (uint8_t *pData, uint8_t bcdMin, uint8_t bcdMax)
{
if (*pData == bcdMax)
*pData = bcdMin;
else
{
if ((*pData & 0x0F) == 0x09)
*pData+=7;
else
*pData+=1;
}
}


vga-rtc.zip > VGA.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi karty VGA
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.01
// Data 24.11.2010
// Kompilator C-IAR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

// Zmiany w stosunku do wersji 1.00
// - zmiana nazwy koloru z MAGNETA na MAGENTA

#include & lt; ioavr.h & gt;
#include & lt; intrinsics.h & gt;
#include " typedef.h "
#include " spi.h "
#include " vga.h "

//------------------------------------------------------------------------------
// Kasowanie pami?ci obrazu.
// Kasowanie polega na wype?nieniu strony " spacjami " .
// Wej: bPageNr - numer strony Video

void VGA_Video_Page_Clear (uint8_t bPageNr)
{
uint16_t wCounter=VPAGE_SIZE; // rozmiar strony pami?ci

// ustawienie adresu na pocz?tek strony
VGA_Write_Addr_Set ((bPageNr)?VPAGE1_ADDR:VPAGE0_ADDR);

do
{
VGA_Transmit (VGA_DATA_WR, ' '); // spacja
VGA_Transmit (VGA_DATA_WR, WHITE | (BLACK & lt; & lt; 3)); // atrybut
}
while (--wCounter);
}

//------------------------------------------------------------------------------
// Zainicjowanie pami?ci generatora znaków
// Wej: bCharGenNr - numer generatora
// bCharStart - numer pierwszego definiowanego znaku (0-255)
// bCharEnd - numer ostatniego definiowanego znaku (0-255)
// pCharDef - wskaźnik na dane opisujace wygl?d znaków

void VGA_CharGen_Init (uint8_t bCharGenNr, uint8_t bCharStart, uint8_t bCharEnd, uint8_t __flash * pCharDef)
{
uint16_t wAddr;
uint16_t wCounter;

if (bCharStart & gt; bCharEnd) // test poprawności parametrów
return;

switch (bCharGenNr) // wyznaczenie adresu pocz?tku pami?ci
{ // dla wybranego generatora znaków
case 0:
wAddr=CHARGEN0_ADDR;
break;

case 1:
wAddr=CHARGEN1_ADDR;
break;

case 2:
wAddr=CHARGEN2_ADDR;
break;

case 3:
wAddr=CHARGEN3_ADDR;
break;

default:
return; // niedozwolony numer generatora
// break;
}

wAddr=wAddr+(uint16_t)(bCharStart & lt; & lt; 4); // wyznaczenie adresu pierwszego
VGA_Write_Addr_Set (wAddr); // zedfiniowanego znaku
wCounter = (uint16_t)((bCharEnd-bCharStart)+1) & lt; & lt; 4; // wyznaczenie ilości bajtów
// do przes?ania (16 bajtów na znak)
do
{
VGA_Transmit (VGA_DATA_WR, *pCharDef++); // przepisanie definicji znaków
} // do pami?ci karty
while (--wCounter);
}

//------------------------------------------------------------------------------
// Wyświetlenie znaku na aktualnej pozycji kursora.
// Wej: bChar - kod znaku
// bAttr - atrybut znaku

void VGA_Put_Char (uint8_t bChar, uint8_t bAttr)
{
VGA_Transmit (VGA_DATA_WR, bChar);
VGA_Transmit (VGA_DATA_WR, bAttr);
}

//------------------------------------------------------------------------------
// Zapis adresu do pary rejestrów VGA ADDR_WR
// Wej: wData - adres

void VGA_Write_Addr_Set (uint16_t wData)
{
VGA_Transmit (VGA_ADDR_WR_LO, wData & 0xFF);
VGA_Transmit (VGA_ADDR_WR_HI, (wData & gt; & gt; 8) & 0xFF);
}

//------------------------------------------------------------------------------
// Zapis adresu do pary rejestrów VGA_ADDR_RD
// Wej: wData - adres

void VGA_Read_Addr_Set (uint16_t wData)
{
VGA_Transmit (VGA_ADDR_RD_LO, wData & 0xFF);
VGA_Transmit (VGA_ADDR_RD_HI, (wData & gt; & gt; 8) & 0xFF);
}

//------------------------------------------------------------------------------
// Zapis rejestru karty VGA
// Wej: bRegAdrr - adres rejestru
// bData - dana do zapisu

void VGA_Transmit (uint8_t bRegAddr, uint8_t bData)
{
SPI_CS = 1;
SPI_Transmit (bRegAddr);
SPI_Transmit (bData);
SPI_CS = 0;

while (SPI_MISO); // oczekiwanie na koniec cyklu zapisu
} // karta sygnalizuje gotowośae poprzez wystawienie '0' na linii MISO

//------------------------------------------------------------------------------
// Odczyt rejestru karty VGA
// Mozliwy jjest odczyt tylko jednego rejestru VGA_DATA)RD
// Wej:
// Wyj: odczytana dana

uint8_t VGA_Receive (void)
{
uint8_t bData;

SPI_CS = 1;
SPI_Transmit (VGA_DATA_RD);
bData= SPI_Receive ();
SPI_CS = 0;

while (SPI_MISO); // oczekiwanie na koniec cyklu odczytu
// karta sygnalizuje gotowośae poprzez wystawienie '0' na linii MISO
return (bData);
}


vga-rtc.zip > DISPLAY.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury wyświetlania
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-IAR
// Uk?ad ATMega16 + PCF8583 + TeleVGA


#include " typedef.h "
#include " vga.h "
#include " font0.h "
#include " display.h "
#include " rtc.h "

// Znak ma wymiary 8x16 punktów
// Kropka ma wymiary 24x24 punkty czyli w poziomie 3 znaki w pione 1 i 1/2 znaku
// dlatego definijujemy zestaw dwóch kropek o rozmiarze 24x48 punktów czyli
// 3 znaki w poziomie i 2 znaki w pionie
const __flash uint8_t Bit2[4][3]=
{ // uk?ad w pionie
{BIG_DOT_00A, BIG_DOT_00B ,BIG_DOT_00C}, //  Kropka wygaszona, kropka wygaszona
{BIG_DOT_01A, BIG_DOT_01B ,BIG_DOT_01C}, //  Kropka wygaszona, kropka zapalona
{BIG_DOT_10A, BIG_DOT_10B ,BIG_DOT_10C}, //  Kropka zapalona, kropka wygaszona
{BIG_DOT_11A, BIG_DOT_11B ,BIG_DOT_11C}, //  Kropka zapalona, kropka zapalona
};

// Mini kropka ma wymiary 8x8 punktów czyli w poziomie 1 znak, w pione 1/2 znaku
// dlatego definijujemy zestaw dwóch kropek o rozmiarze 16x8 punktów czyli 1 znak
const __flash uint8_t MiniBit2[4]=
{ MINI_DOT_00, MINI_DOT_01, MINI_DOT_10, MINI_DOT_11};

// Definicja fontu 5x7 kropek
const __flash uint8_t Font58[11+26+2+9][20]=
{
{0,1,1,1,0, 3,0,0,1,3, 3,1,2,0,3, 2,1,1,1,2}, // 0 cyfry 0-9
{0,0,1,0,0, 0,2,3,0,0, 0,0,3,0,0, 0,1,3,1,0}, // 1
{0,1,1,1,0, 2,0,0,0,3, 0,0,1,2,0, 1,3,1,1,1}, // 2
{1,1,1,1,1, 0,0,1,2,0, 0,0,0,2,1, 2,1,1,1,2}, // 3
{0,0,0,1,0, 0,1,2,3,0, 3,1,1,3,1, 0,0,0,3,0}, // 4
{1,1,1,1,1, 3,1,1,1,0, 0,0,0,0,3, 2,1,1,1,2}, // 5
{0,0,1,1,0, 1,2,0,0,0, 3,2,2,2,1, 2,1,1,1,2}, // 6
{1,1,1,1,1, 0,0,0,1,2, 0,1,2,0,0, 0,3,0,0,0}, // 7
{0,1,1,1,0, 3,0,0,0,3, 1,2,2,2,1, 2,1,1,1,2}, // 8
{0,1,1,1,0, 3,0,0,0,3, 0,2,2,2,3, 0,1,1,2,0}, // 9
{0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0}, // BLANK

{0,1,1,1,0, 3,0,0,0,3, 3,1,1,1,3, 3,0,0,0,3}, // A znaki A-Z
{1,1,1,1,0, 3,0,0,0,3, 3,2,2,2,1, 3,1,1,1,2}, // B
{0,1,1,1,0, 3,0,0,0,3, 3,0,0,0,0, 2,1,1,1,2}, // C
{1,1,1,0,0, 3,0,0,2,1, 3,0,0,0,3, 3,1,1,2,0}, // D
{1,1,1,1,1, 3,0,0,0,0, 3,2,2,2,0, 3,1,1,1,1}, // E
{1,1,1,1,1, 3,0,0,0,0, 3,2,2,2,0, 3,0,0,0,0}, // F
{0,1,1,1,0, 3,0,0,0,2, 3,0,2,2,3, 2,1,1,1,3}, // G
{1,0,0,0,1, 3,0,0,0,3, 3,2,2,2,3, 3,0,0,0,3}, // H
{0,1,1,1,0, 0,0,3,0,0, 0,0,3,0,0, 0,1,3,1,0}, // I
{0,0,1,1,1, 0,0,0,3,0, 0,0,0,3,0, 2,1,1,2,0}, // J
{1,0,0,0,1, 3,0,1,2,0, 3,2,1,0,0, 3,0,0,2,1}, // K
{1,0,0,0,0, 3,0,0,0,0, 3,0,0,0,0, 3,1,1,1,1}, // L
{1,0,0,0,1, 3,2,1,2,3, 3,0,3,0,3, 3,0,0,0,3}, // M
{1,0,0,0,1, 3,1,0,0,3, 3,0,2,1,3, 3,0,0,0,3}, // N
{0,1,1,1,0, 3,0,0,0,3, 3,0,0,0,3, 2,1,1,1,2}, // O
{1,1,1,1,0, 3,0,0,0,3, 3,2,2,2,0, 3,0,0,0,0}, // P
{0,1,1,1,0, 3,0,0,0,3, 3,0,1,0,3, 2,1,1,2,1}, // Q
{1,1,1,1,0, 3,0,0,0,3, 3,2,3,2,0, 3,0,0,2,1}, // R
{0,1,1,1,1, 3,0,0,0,0, 0,2,2,2,1, 1,1,1,1,2}, // S
{1,1,1,1,1, 0,0,3,0,0, 0,0,3,0,0, 0,0,3,0,0}, // T
{1,0,0,0,1, 3,0,0,0,3, 3,0,0,0,3, 2,1,1,1,2}, // U
{1,0,0,0,1, 3,0,0,0,3, 3,0,0,0,3, 0,2,1,2,0}, // V
{1,0,0,0,1, 3,0,0,0,3, 3,0,3,0,3, 2,1,2,1,2}, // W
{1,0,0,0,1, 2,1,0,1,2, 1,0,2,0,1, 3,0,0,0,3}, // X
{1,0,0,0,1, 3,0,0,0,3, 0,2,1,2,0, 0,0,3,0,0}, // Y
{1,1,1,1,1, 0,0,0,1,2, 0,1,2,0,0, 3,1,1,1,1}, // Z

{0,1,1,1,0, 3,0,0,0,3, 3,1,1,1,3, 3,0,0,1,3}, // CHAR_PLA ?
{0,1,1,3,1, 3,2,0,0,0, 0,2,2,2,1, 1,1,1,1,2}, // CHAR_PLS Ś

// zaw??ony font dla napisu " PONIEDZIA?EK "
{1,1,1,0,0, 3,0,0,3,0, 3,2,2,0,0, 3,0,0,0,0}, // CHAR_PP
{0,1,1,0,0, 3,0,0,3,0, 3,0,0,3,0, 2,1,1,2,0}, // CHAR_PO
{1,0,0,1,0, 3,1,0,3,0, 3,0,2,3,0, 3,0,0,3,0}, // CHAR_PN
{1,1,1,1,0, 3,0,0,0,0, 3,2,2,0,0, 3,1,1,1,0}, // CHAR_PE
{1,1,1,0,0, 3,0,0,3,0, 3,0,0,3,0, 3,1,1,2,0}, // CHAR_PD
{1,1,1,1,0, 0,0,0,3,0, 0,1,2,0,0, 3,1,1,1,0}, // CHAR_PZ
{0,1,1,0,0, 3,0,0,3,0, 3,1,1,3,0, 3,0,0,3,0}, // CHAR_PA
{1,0,0,0,0, 3,0,1,0,0, 3,2,0,0,0, 3,1,1,1,0}, // CHAR_PLL ?
{1,0,0,1,0, 3,0,1,2,0, 3,2,1,0,0, 3,0,0,3,0} // CHAR_PK
};

const __flash uint8_t DigitsSmall[12][7]=
{
{0x70, 0x88, 0x98, 0xA8, 0xC8, 0x88, 0x70}, // 0
{0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70}, // 1
{0x70, 0x88, 0x08, 0x10, 0x20, 0x40, 0xF8}, // 2
{0xF8, 0x10, 0x20, 0x10, 0x08, 0x88, 0x70}, // 3
{0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10}, // 4
{0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70}, // 5
{0x30, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70}, // 6
{0xF8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x40}, // 7
{0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70}, // 8
{0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60}, // 9
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // BLANK
{0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00} // -
};

// definicje nazw dni tygodnia
const __flash uint8_t WeekDayName[7][13]=
{
{'N', 'I', 'E', 'D', 'Z', 'I', 'E', 'L', 'A', 0x00},
{CHAR_PP,CHAR_PO,CHAR_PN,'I',CHAR_PE,CHAR_PD,CHAR_PZ,'I',CHAR_PA,CHAR_PLL,CHAR_PE,CHAR_PK, 0x00},
{'W', 'T', 'O', 'R', 'E', 'K', 0x00},
{CHAR_PLS, 'R', 'O', 'D', 'A', 0x00},
{'C', 'Z', 'W', 'A', 'R', 'T', 'E', 'K', 0x00},
{'P', 'I', CHAR_PLA, 'T', 'E', 'K', 0x00},
{'S', 'O', 'B', 'O', 'T', 'A', 0x00}
};

//-----------------------------------------------------------------------------
// Procedura wyświetlania sekund
// Wej: bColorS - kolor sekund

void Show_Seconds (uint8_t bColorS)
{
Show_Digit_Mini (Time.bcdSeconds & gt; & gt; 4, 65, 15, bColorS);
Show_Digit_Mini (Time.bcdSeconds & 0x0F, 71, 15, bColorS);
Show_Frame (62,14,17,6, bColorS);
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania bie??cego czasu
// Wej: bColorH, bColorM - kolor godzin i minut
// bColorF - kolor ramki

void Show_Time (uint8_t bColorH, uint8_t bColorM, uint8_t bColorF)
{
Show_Digit_Big ((Time.bcdHours & gt; & gt; 4)?Time.bcdHours & gt; & gt; 4:BLANK,3, 2, bColorH);
Show_Digit_Big (Time.bcdHours & 0x0F, 21, 2, bColorH);
Show_Digit_Big (Time.bcdMinutes & gt; & gt; 4, 45, 2, bColorM);
Show_Digit_Big (Time.bcdMinutes & 0x0F, 63, 2, bColorM);

Show_Frame (2, 1,77,13, bColorF); // pojedyncza ramka

// Show_Frame (2, 1,17,13, bColorF); // ramki dla poszczególnych cyfr
// Show_Frame (20,1,17,13, bColorF);
// Show_Frame (44,1,17,13, bColorF);
// Show_Frame (62,1,17,13, bColorF);
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania bie??cej daty
// Wej: bColorD, bColorM, bColorY - kolory dnia, miesi?ca i roku
// bColorF - kolor ramki i myślników

#define YPOS 21
void Show_Date (uint8_t bColorD, uint8_t bColorM, uint8_t bColorY, uint8_t bColorF)
{
Show_Digit_Small ((Time.bcdDay & gt; & gt; 4)?Time.bcdDay & gt; & gt; 4:BLANK,4, YPOS, bColorD);
Show_Digit_Small (Time.bcdDay & 0x0F, 14, YPOS, bColorD);
Show_Dot_Small (DOT_ON,25,YPOS+3, bColorF);
Show_Dot_Small (DOT_ON,27,YPOS+3, bColorF);
Show_Digit_Small (Time.bcdMonth & gt; & gt; 4, 30, YPOS, bColorM);
Show_Digit_Small (Time.bcdMonth & 0x0F,40, YPOS, bColorM);
Show_Dot_Small (DOT_ON,51,YPOS+3, bColorF);
Show_Dot_Small (DOT_ON,53,YPOS+3, bColorF);
Show_Digit_Small (Time.bcdYear & gt; & gt; 4, 56, YPOS, bColorY);
Show_Digit_Small (Time.bcdYear & 0x0F,66, YPOS, bColorY);
Show_Frame (2, YPOS-1,77,9 , bColorF);
}
#undef YPOS

//-----------------------------------------------------------------------------
// Procedura wyświetlania nazwy dnia tygodnia
// Wej: bColorF - kolor napisu

#define XPOS 2
#define YPOS 15

void Show_WeekDay_Name (uint8_t bColor)
{
uint8_t i,j,bChar,bCurX;

// Skasowanie poprzedniego napisu
for (i=0;i & lt; 4;i++)
{
VGA_Write_Addr_Set ((uint16_t)((YPOS+i) & lt; & lt; 8) | XPOS & lt; & lt; 1);
for (j=0;j & lt; 60;j++)
VGA_Put_Char (' ', bColor);
}

i=0;
bCurX=XPOS;
while (bChar=WeekDayName[Time.bWeekDay][i++])
{
if (bChar==' ')
Show_Digit_Mini (BLANK, bCurX, YPOS, bColor);
else
Show_Digit_Mini (bChar-'A'+CHAR_A, bCurX, YPOS, bColor);

// zaw??enie fontu dla napisu poniedzia?ek
if(Time.bWeekDay ==1)
bCurX+=5;
else
bCurX+=6;
};
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania ramki
// Wej: bCurX, bCurY - pozycja lewego górnego naro?nika
// bSizeX, bSizeY - rozmiar ramki
// bColor - kolor ramki

void Show_Frame (uint8_t bCurX, uint8_t bCurY, uint8_t bSizeX, uint8_t bSizeY, uint8_t bColor)
{
uint8_t i;

// ustawienie adresu lewego górnego naro?nika
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);

// górna cz?śae ramki
VGA_Put_Char (LT_TP_CORNER, bColor); // lewy-górny naro?nik
for (i=0;i & lt; bSizeX-2;i++)
VGA_Put_Char (TP_LINE, bColor); // górna kreska
VGA_Put_Char (RT_TP_CORNER, bColor); // prawy-górny naro?nik

// lewa i prawa cz?śae ramki
for (i=0;i & lt; bSizeY-2;i++)
{
bCurY++;
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
VGA_Put_Char (LT_LINE, bColor); // lewa kreska pionowa
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | (bCurX+bSizeX-1) & lt; & lt; 1);
VGA_Put_Char (RT_LINE, bColor); // prawa kreska pionowa
}

// dolna cz?śae ramki
bCurY++;
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
VGA_Put_Char (LT_BM_CORNER, bColor); // lewy-dolny naro?nik
for (i=0;i & lt; bSizeX-2;i++)
VGA_Put_Char (BM_LINE, bColor); // dolna kreska
VGA_Put_Char (RT_BM_CORNER, bColor); // prawy-dolny naro?nik

}

//-----------------------------------------------------------------------------
// Wyświetlenie elementu sk?adajacego si? z dwóch punktów.
// Element taki zajmuje pole 3x2 znaki.
// Wej: bDots - typ punktów
// bCurX,bCurY - pozycja kursora
// bColor - kolor punktów

void Show_Dots (uint8_t bDots, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,k;

for (i=0;i & lt; 3;i++)
{
// ustawienie pozycji kursora
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;

k=Bit2[bDots][i];
for (j=0;j & lt; 3;j++)
VGA_Put_Char (k++, bColor);
}
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania cyfry du?ej (matryca 5x7 punktów)
// Wej: bDigit - cyfra do wyświetlenia
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Digit_Big (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,k,l,bTmp1,bTmp2;

if (bDigit & gt; BLANK)
return;

j=1;
for (i=1; i & lt; 12; i++)
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;

for (k=0;k & lt; 5;k++) // 5 kolumn
{
bTmp1=Font58[bDigit][((i/3)*5)+k];
bTmp2=Bit2[bTmp1][j%3];
for (l=0;l & lt; 3;l++) // 3 znaki = 1 kolumna
VGA_Put_Char (bTmp2++, bColor);
}
j++;
}
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania ma?ego punktu
// Wej: bDot - stan kropki
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Dot_Small (uint8_t bDot, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
if (bDot)
{
VGA_Put_Char (SMALL_DOT_LEFT, bColor);
VGA_Put_Char (SMALL_DOT_RIGHT, bColor);
}
else
{
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
}
}

//-----------------------------------------------------------------------------
// Procedura wyświetlania cyfry ma?ej (matryca 5x7 punktów)
// Wej: bDigit - cyfra do wyświetlenia
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Digit_Small (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,bTmp1;

for (i=0;i & lt; 7;i++) // 7 wierszy
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;

bTmp1=DigitsSmall[bDigit][i];
for (j=0;j & lt; 5;j++) // 5 kolumn
{
if (bTmp1 & 0x80)
{
VGA_Put_Char (SMALL_DOT_LEFT, bColor);
VGA_Put_Char (SMALL_DOT_RIGHT, bColor);
}
else
{
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
VGA_Put_Char (SMALL_DOT_BLANK, bColor);
}
bTmp1 & lt; & lt; =1;
}
}
}


//-----------------------------------------------------------------------------
// Procedura wyświetlania cyfry ma?ej (matryca 5x7 punktów)
// Wej: bDigit - cyfra do wyświetlenia
// bCurX, bCurY - pozycja kursora
// bColor - kolor cyfry

void Show_Digit_Mini (uint8_t bDigit, uint8_t bCurX, uint8_t bCurY, uint8_t bColor)
{
uint8_t i,j,bTmp1;

for (i=0;i & lt; 4;i++) // 4 wiersze
{
VGA_Write_Addr_Set ((uint16_t)(bCurY & lt; & lt; 8) | bCurX & lt; & lt; 1);
bCurY+=1;
for (j=0;j & lt; 5;j++) // 5 kolumn
{
bTmp1=Font58[bDigit][i*5+j];
VGA_Put_Char (MiniBit2[bTmp1], bColor);
}
}
}


vga-rtc.zip > version.txt

Wersja 1.01

Main 1.00
Display 1.00
Rtc 1.00
Vga 1.01
Spi 1.00
I2C 1.01
Font0 1.00


vga-rtc.zip > SPI.H

#ifndef _SPI_H_
#define _SPI_H_

// definicja pod??cze? portu SPI dla procesora ATMEGA16
#define SPI_Port PORTB
#define SPI_Port_Dir DDRB
#define SPI_Port_Pin PINB

#define SPI_RESET_Bit PB2
#define SPI_SLEEP_Bit PB3
#define SPI_CS_Bit PB4
#define SPI_MOSI_Bit PB5
#define SPI_MISO_Bit PB6
#define SPI_SCK_Bit PB7

#define SPI_RESET PORTB_Bit2
#define SPI_SLEEP PORTB_Bit3
#define SPI_CS PORTB_Bit4
#define SPI_MOSI PORTB_Bit5
#define SPI_MISO PINB_Bit6
#define SPI_SCK PORTB_Bit7

// prototypy funkcji
void SPI_Init (void);
void SPI_Transmit (uint8_t bData);
uint8_t SPI_Receive (void);

#endif


vga-rtc.zip > I2C.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - procedury obs?ugi portu I2C
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.01
// Data 24.11.2010
// Kompilator C-IAR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

// Zmiany w stosunku do wersji 1.00
// - poprawa inicjalizacji modu?u I2C
// (by? inicjowany rejster TWBR zamiast TWSR)

#include & lt; ioavr.h & gt;
#include & lt; intrinsics.h & gt;
#include " typedef.h "
#include " i2c.h "

uint8_t tI2CBuffer[4]; // bufor i2C

//------------------------------------------------------------------------------
// Inicjalizacja interfejsu I2C.
// Tryb MASTER, rezystory Pull-Up

void I2C_Master_Init (void)
{
SDA = 1; // Pull-Up dla linii SDA i SCL
SCL = 1;

TWBR = TWI_TWBR; // ustawienie BitRate
TWSR = TWI_TWPS;

TWDR = 0xFF;
TWCR = (1 & lt; & lt; TWEN); // TWI odblokowany, odpi?ty od szyny, przerwania zablokowane
}

//------------------------------------------------------------------------------
// Procedura transmisji danych po szynie I2C
// Wej: bDataCnt - ilośae danych do wys?ania
// bAddr - adres
// pDataPtr - wskaźnik na dane
// Wyj: Status transmisji OK/ERROR

uint8_t I2C_Xmit (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr)
{
if (I2C_Send_Start () == TWI_START) // wys?anie START
if (I2C_Send_Byte (SLAVE_ADDR_WR) == TWI_MTX_ADR_ACK) // wys?anie SLAVE_ADDR + WR
if (I2C_Send_Byte (bAddr) == TWI_MTX_DATA_ACK) // wys?anie adresu
{
// transmsja danych
while (bDataCnt--)
{
if (I2C_Send_Byte (*pDataPtr++) != TWI_MTX_DATA_ACK)
{
I2C_Send_Stop();
return (ERROR);
}
};
I2C_Send_Stop();
return (OK);
}

I2C_Send_Stop();
return (ERROR);
}

//------------------------------------------------------------------------------
// Procedura odbioru danych po szynie I2C
// Wej: bDataCnt - ilośae danych do odebrania
// pDataPtr - wskaźnik na bufor
// Status odbioru OK/ERROR

uint8_t I2C_Recv (uint8_t bDataCnt, uint8_t bAddr, uint8_t *pDataPtr)
{
if (I2C_Send_Start () == TWI_START) // wys?anie START
if (I2C_Send_Byte (SLAVE_ADDR_WR) == TWI_MTX_ADR_ACK) // wys?anie SLAVE_ADDR + WR
if (I2C_Send_Byte (bAddr) == TWI_MTX_DATA_ACK) // wys?anie adresu
if (I2C_Send_Start () == TWI_REP_START) // wys?anie REP_START
if (I2C_Send_Byte (SLAVE_ADDR_RD) == TWI_MRX_ADR_ACK)// wys?anie SLAVE_ADDR + RD
{
// odbiór danych
while (bDataCnt--)
{
if (bDataCnt)
{
if (I2C_Get_Byte (pDataPtr++) != TWI_MRX_DATA_ACK)
{
I2C_Send_Stop();
return (ERROR);
}
}
else
if (I2C_Get_ByteLast (pDataPtr++) != TWI_MRX_DATA_NACK)
{
I2C_Send_Stop();
return (ERROR);
}
};

I2C_Send_Stop();
return (OK);
}

I2C_Send_Stop();
return (ERROR);
}

//------------------------------------------------------------------------------
// Wys?anie bitu START
// Wej:
// Wyj: Status wykonania operacji

uint8_t I2C_Send_Start (void)
{
TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWSTA)|(1 & lt; & lt; TWEN);
return (I2C_Ready());
}

//------------------------------------------------------------------------------
// Odbiór bajtu + bit NACK
// Wej: pDataPtr - wskaźnik na bufor
// Wyj: Status wykonania operacji

uint8_t I2C_Get_ByteLast (uint8_t* pDataPtr)
{
uint8_t bStatus;

TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWEN);
if ((bStatus=I2C_Ready()) == TWI_MRX_DATA_NACK)
*pDataPtr=TWDR;

return (bStatus);
}

//------------------------------------------------------------------------------
// Odbiór bajtu + bit ACK
// Wej: pDataPtr - wskaźnik na bufor
// Wyj: Status wykonania operacji

uint8_t I2C_Get_Byte (uint8_t* pDataPtr)
{
uint8_t bStatus;

TWCR=(1 & lt; & lt; TWINT)|(1 & lt; & lt; TWEN)|(1 & lt; & lt; TWEA);
if ((bStatus=I2C_Ready()) == TWI_MRX_DATA_ACK)
*pDataPtr=TWDR;

return (bStatus);
}

//------------------------------------------------------------------------------
// Wys?anie bajtu
// Wej: bData - dna do wys?ania
// Wyj: Status wykonania operacji

uint8_t I2C_Send_Byte (uint8_t bData)
{
TWDR = bData;
TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWEN);
return (I2C_Ready());
}

//------------------------------------------------------------------------------
// Wys?anie bitu STOP

void I2C_Send_Stop (void)
{
TWCR = (1 & lt; & lt; TWINT)|(1 & lt; & lt; TWSTO)|(1 & lt; & lt; TWEN); // wys?anie STOP
}

//------------------------------------------------------------------------------
// Oczekiwanie na zako?czenie operacji
// Wyj: Status wykonania operacji

uint8_t I2C_Ready (void)
{
while (!(TWCR & (1 & lt; & lt; TWINT))); // oczekiwanie na zako?czenie operacji
return (TWSR & 0xF8); // wydzielenie Status
}

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


vga-rtc.zip > TYPEDEF.H

#ifndef _TYPEDEF_H
#define _TYPEDEF_H

typedef unsigned char uint8_t;
typedef unsigned int uint16_t;

#define OK 0
#define ERROR 1

#endif


vga-rtc.zip > FONT0.H

#ifndef _FONT0_H_
#define _FONT0_H_

// definicja znaków dla du?ych punktów
#define BIG_DOT_00A 0x00
#define BIG_DOT_00B 0x00
#define BIG_DOT_00C 0x00

#define BIG_DOT_10A 0x03
#define BIG_DOT_10B 0x06
#define BIG_DOT_10C 0x00

#define BIG_DOT_01A 0x00
#define BIG_DOT_01B 0x09
#define BIG_DOT_01C 0x0C

#define BIG_DOT_11A 0x03
#define BIG_DOT_11B 0x0F
#define BIG_DOT_11C 0x0C

#define MINI_DOT_00 0x00
#define MINI_DOT_01 0x1A
#define MINI_DOT_10 0x1B
#define MINI_DOT_11 0x1C

// definicja elementów ramki
#define LT_LINE 0x12
#define RT_LINE 0x12
#define TP_LINE 0x13
#define BM_LINE 0x13
#define LT_TP_CORNER 0x14
#define LT_BM_CORNER 0x15
#define RT_TP_CORNER 0x16
#define RT_BM_CORNER 0x17

// definicja znaków dla ma?ych punktów
#define SMALL_DOT_BLANK 0x00
#define SMALL_DOT_LEFT 0x18
#define SMALL_DOT_RIGHT 0x19

extern const __flash uint8_t Font0_8_16 [528];

#endif


vga-rtc.zip > MAIN.C

// (C) 2010 JarekC.DIY & TeleVox
// Program w ca?ości lub jego framgmenty mog? byae wykorzystane i modyfikowane
// tylko w celach hobbystycznych.
// Komercyjne wykorzystanie bez zgody autora jest niedozwolone.

// Program zegara VGA - cześae g?ówna
// Autor: JarekC
// Email: JarekC.DIY@gmail.com
// Wersja 1.00
// Data 24.11.2010
// Kompilator C-IAR
// Uk?ad ATMega16 + PCF8583 + TeleVGA

// Wymagane ustawienia w IAR IDE
// - Genaral Opitions
// -Target
// - --cpu=m16
// - zaznaczyae opcj? " Configure system using dialogs "
// - System
// - CSTACK=0x40, RSTASK=16
// - zaznaczyae opcj? " Enable bit definition in I/O include files "


#include & lt; ioavr.h & gt;
#include & lt; intrinsics.h & gt;
#include " typedef.h "
#include " spi.h "
#include " vga.h "
#include " font0.h "
#include " display.h "
#include " i2c.h "
#include " rtc.h "

#define XTAL 8000000
#define COLOR1 WHITE | BLACK & lt; & lt; 3 // kolor dla czasu
#define COLOR2 GREEN | BLACK & lt; & lt; 3 // kolor dla daty
#define COLOR3 YELLOW | BLACK & lt; & lt; 3 // kolor dla dnia tygodnia
#define COLOR_PRG RED | BLACK & lt; & lt; 3 // kolor dla trybu programownia

volatile uint8_t bFlags;
#define SEC_F 0x01 // znacznik zmiany sekund
#define TIME_F 0x02 // znacznik zmiany czasu (minuty, godziny)
#define DATE_F 0x04 // znacznik zmiany daty
#define COLON_F 0x08 // znacznik wygaszenia dwukropka

volatile uint8_t bKey; // stan klawiszy po eliminacji drga?
volatile uint8_t bKeyPrev; // poprzedni stan klawiszy po eliminacji drga?
volatile uint8_t bKeySample; // próbka stanu portu klawiatury
#define KEY_ENTER 0x01
#define KEY_MINUS 0x02
#define KEY_PLUS 0x04

volatile uint8_t bPresc05; // dzielnik dla 0.5 sekundy
#define PRESC05_LOAD 20 // 20*25ms

#define KEY_Port PORTA // klawiatura na porcie A
#define KEY_Port_Pin PINA
#define KEY_Port_Dir DDRA
#define KEY_MASK 0x07 // KEY1=PA0, KEY2=PA1,KEY3=PA2

uint8_t Get_Key (void);

void main( void )
{
uint8_t bKeyPress;

// zainicjowanie portu SPI i I2C
SPI_Init();
I2C_Master_Init();

// zako?czenie sygna?u RESET dla karty VGA
SPI_RESET=1;

// zainicjowanie 0 generatora znaków (33 znaki)
VGA_CharGen_Init (0, 0, 33,(uint8_t __flash *) Font0_8_16);

// zainicjowanie 0 strony pami?ci Video
VGA_Video_Page_Clear (0);

// za??czenie karty, kusor podkreślenie, video z??czone
// tryb z miganiem i podświetleniem
VGA_Transmit (VGA_CONTROL, CTRL_VEN);

// zainicjowanie zegara RTC
RTC_Init();

// konfiguracja przerwania INT0
PORTD_Bit2=1; // pull-up na linii INT0
DDRD_Bit2=0; // INT0 jako wejście
MCUCR |= 1 & lt; & lt; ISC00 | 1 & lt; & lt; ISC01; // reakcja na zbocze opadaj?ce
GICR |= 1 & lt; & lt; INT0; // odblokowanie przerwania

// zainicjowanie portu klawiatury
KEY_Port = KEY_MASK; // pull-up dla klawiszy
KEY_Port_Dir =0x00; // wszystkie linie jako wejścia

// zainicjowanie Timera 0, cykliczne przerwanie co 25ms
// Timer clock = system clock / 1024, CTC mode
TCCR0 = (1 & lt; & lt; CS02)|(1 & lt; & lt; CS00)|(1 & lt; & lt; WGM01);
OCR0 = (XTAL/1024/40)-1; // 24.96ms
TIFR |= (1 & lt; & lt; OCF0); // skasowanie znacznika przerwania
TIMSK |= (1 & lt; & lt; OCIE0); // odblokowanie przerwania od Timera 0

// odczyt czasu i daty
RTC_Read_Time();
RTC_Read_Date();

// wymuszenie wyświetlenia czasu i daty
bFlags = SEC_F | TIME_F | DATE_F;

// odblokowanie przerwa?
__enable_interrupt();

while (1)
{
if (Get_Key() == KEY_ENTER) // wejście w tryb programowania zegara
{
GICR & = ~(1 & lt; & lt; INT0); // zablokowanie przerwania od RTC

// wyzerowanie sekund
Time.bcdSeconds=0x00;
Show_Seconds (COLOR1);

// ustawianie godzin
Show_Dots (DOTS_TOP_ONLY, 40, 4, COLOR1); // zapalenie dwukropka
Show_Dots (DOTS_TOP_ONLY, 38,10, COLOR1);
do
{
Show_Time (COLOR_PRG, COLOR1, COLOR1); // wyświetlenie czasu
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdHours,0x00,0x23);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdHours,0x00,0x23);
} while (!(bKeyPress & KEY_ENTER));

// ustawianie minut
do
{
Show_Time (COLOR1, COLOR_PRG, COLOR1); // wyświetlenie czasu
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdMinutes,0x00,0x59);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdMinutes,0x00,0x59);
} while (!(bKeyPress & KEY_ENTER));

Show_Time (COLOR1, COLOR1, COLOR1); // wyświetlenie czasu

// ustawianie dnia miesi?ca
do
{
Show_Date (COLOR_PRG,COLOR2,COLOR2,COLOR2); // wyświetlenie daty
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdDay,0x01,0x31);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdDay,0x01,0x31);
} while (!(bKeyPress & KEY_ENTER));

// ustawianie miesi?ca
do
{
Show_Date (COLOR2,COLOR_PRG,COLOR2,COLOR2); // wyświetlenie daty
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdMonth,0x01,0x12);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdMonth,0x01,0x12);
} while (!(bKeyPress & KEY_ENTER));

// ustawianie roku
do
{
Show_Date (COLOR2,COLOR2,COLOR_PRG,COLOR2); // wyświetlenie daty
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bcdYear,0x00,0x99);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bcdYear,0x00,0x99);
} while (!(bKeyPress & KEY_ENTER));

Show_Date (COLOR2,COLOR2,COLOR2,COLOR2); // wyświetlenie daty

// ustawianie dnia tygodnia
do
{
Show_WeekDay_Name (COLOR_PRG); // wyświetlenie dnia tygodnia
while (!(bKeyPress=Get_Key())); // oczekiwanie na klawisz
if (bKeyPress & KEY_PLUS)
Inc_BCD ( & Time.bWeekDay,0x00,0x06);
else if (bKeyPress & KEY_MINUS)
Dec_BCD ( & Time.bWeekDay,0x00,0x06);
} while (!(bKeyPress & KEY_ENTER));

// sprawdzenie poprawności dnia miesi?ca
if (Time.bcdDay & gt; MonthTable[Time.bcdMonth])
Time.bcdDay = MonthTable[Time.bcdMonth];

// zapis nowego czasu i daty do PCF8583
RTC_Write_Time();
RTC_Write_Date();

GICR |= 1 & lt; & lt; INT0; // odblokowanie przerwania od RTC

// wymuszenie wyświetlenia czasu i daty
bFlags |= SEC_F | TIME_F | DATE_F;
}

// odświerzanie sekund
if (bFlags & SEC_F)
{
bFlags & = ~(SEC_F | COLON_F); // skasowanie znaczników zmiany sekund
Show_Seconds (COLOR1);
Show_Dots (DOTS_TOP_ONLY, 40, 4, COLOR1); // zapalenie dwukropka
Show_Dots (DOTS_TOP_ONLY, 38,10, COLOR1);
bPresc05 = PRESC05_LOAD;
}

// odświerzanie godzin i minut
if (bFlags & TIME_F)
{
bFlags & = ~TIME_F; // skasowanie znacznika zmiany czasu
Show_Time (COLOR1, COLOR1, COLOR1); // wyświetlenie czasu
}

// odświerzanie daty
if (bFlags & DATE_F)
{
bFlags & = ~DATE_F ; // skasowanie znacznika
Show_Date (COLOR2,COLOR2,COLOR2,COLOR2); // wyświetlenie daty
Show_WeekDay_Name (COLOR3);
}

// miganie dwukropkiem
if (bFlags & COLON_F)
{
bFlags & = ~(COLON_F); // skasowanie znacznika wygaszenia dwukropka
Show_Dots (DOTS_NONE, 40, 4, COLOR1); // zgaszenie dwukropka
Show_Dots (DOTS_NONE, 38,10, COLOR1);
}
};

}

//*****************************************************************************
// obs?uga przerwania od RTC (co 1 sekund?)
// - odczyt czasu i daty

#pragma vector=INT0_vect
__interrupt void INT0_service(void)
{
RTC_Read_Time();
bFlags |= SEC_F; // znacznik zmiany sekund

if (!Time.bcdSeconds)
{
bFlags |= TIME_F; // znacznik zmiany czasu
if (!Time.bcdHours & & !Time.bcdMinutes)
{
RTC_Read_Date();
bFlags |= DATE_F; // znacznik zmiany daty
}
}
}

//*****************************************************************************
// obs?uga przerwania od TIMER0 (co 25ms)
// - obs?uga klawiatury
// - obs?uga migania dwukropkiem

#pragma vector=TIMER0_COMP_vect
__interrupt void TIMER0_COMP_service(void)
{
uint8_t bTemp1,bTemp2;

// obs?uga klawiatury
bTemp1 = bKeySample;
bTemp2 = KEY_Port_Pin;
bKeySample = bTemp2;
bKey=(~((bTemp1^bTemp2) | bTemp2)) & KEY_MASK;

if (bPresc05--)
if (!bPresc05)
bFlags |= COLON_F;
}

//*****************************************************************************
//-----------------------------------------------------------------------------
// Procedura odczytu stanu klawiatury (bez repetycji)

uint8_t Get_Key (void)
{
uint8_t bTemp1,bTemp2;

bTemp1 = bKeyPrev;
bTemp2 = bKey;
bKeyPrev = bTemp2;
bTemp1= (bTemp1 ^ bTemp2) & bTemp2;

return (bTemp1);
}
//-----------------------------------------------------------------------------