--- /dev/null
+/*-------------------------------------------------------------------------
+ lcd.c - lcd routines for the DS80C390 (tested on TINI)
+
+ Written By - Johan Knol, johan.knol@iduna.nl
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "lcd.h"
+
+#define LCD_ROWS 4
+#define LCD_COLLUMNS 20
+
+xdata at 0x380002 static unsigned char lcdIwr;
+xdata at 0x38000a static unsigned char lcdDwr;
+
+#ifdef LCD_RW
+
+xdata at 0x380003 static unsigned char lcdIrd;
+xdata at 0x38000b static unsigned char lcdDrd;
+
+#define LcdWait { while (lcdIrd&0x80) ; }
+
+#else ifdef LCD_RW
+
+// wait for 100us
+#define LcdWait { ClockMicroSecondsDelay(100) ; }
+
+#endif ifdef LCD_RW
+
+// set the dd ram addresses for the rows
+// this one is for a 20x4 LCD
+xdata static unsigned char lcdLinesStart[LCD_ROWS]={0, 0x40, 0x14, 0x54};
+
+void LcdInit() {
+
+ ClockMilliSecondsDelay(16); // >15 ms
+
+ lcdIwr=0x38 ;
+ ClockMilliSecondsDelay(5); // >4.1 ms
+
+ lcdIwr=0x38;
+ ClockMicroSecondsDelay(101); // >100 us
+
+ lcdIwr=0x38;
+ ClockMicroSecondsDelay(101); // >100 us
+
+ lcdIwr=0x38; // interface 8 bit
+ ClockMicroSecondsDelay(41); // >40 us
+
+ lcdIwr=0x0c; // display on
+ ClockMicroSecondsDelay(41); // >40 us
+
+ LcdClear();
+}
+
+void LcdOn() {
+ lcdIwr=0x0c; // display on
+ LcdWait;
+}
+
+void LcdOff() {
+ lcdIwr=0x08; // display off
+ LcdWait;
+}
+
+void LcdCursorOn() {
+ // TODO
+}
+
+void LcdCursorOff() {
+ // TODO
+}
+
+void LcdScrollOn() {
+ // TODO
+}
+
+void LcdScrollOff() {
+ // TODO
+}
+
+void LcdCharDefine() {
+ // TODO
+}
+
+void LcdClear() {
+ lcdIwr=0x01; // display clear
+ ClockMilliSecondsDelay(6); // > 5ms
+}
+
+void LcdHome() {
+ lcdIwr=0x80; // set dd ram address 0
+ LcdWait;
+}
+
+void LcdGoto(unsigned int collumnRow) { // msb=collumn, lsb=row
+ lcdIwr=0x80 + \
+ lcdLinesStart[collumnRow&0xff] + (collumnRow>>8);
+ LcdWait;
+}
+
+void LcdPutChar(char c) {
+ lcdDwr=c;
+ LcdWait;
+}
+
+void LcdPutString (char *string) {
+ char c;
+ while (c=*string++) {
+ LcdPutChar (c);
+ }
+}
+
+void LcdLPutString (unsigned int collumnRow, char *string) {
+ LcdGoto(collumnRow);
+ LcdPutString(string);
+}
+
+// let's hope that no one ever printf's more than the display width,
+// however they will :), so to be sure
+static char lcdPrintfBuffer[LCD_COLLUMNS*4];
+
+void LcdPrintf (xdata const char *format, ...) reentrant {
+ va_list arg;
+
+ va_start (arg, format);
+ vsprintf (lcdPrintfBuffer, format, arg);
+ puts (lcdPrintfBuffer);
+ LcdPutString(lcdPrintfBuffer);
+
+ va_end (arg);
+}
+
+void LcdLPrintf (unsigned int collumnRow, xdata const char *format, ...) reentrant {
+ va_list arg;
+
+ LcdGoto(collumnRow);
+
+ // we can not just call LcdPrintf since we have no idea what is on the stack,
+ // so we have to do it all over again
+ va_start (arg, format);
+ vsprintf (lcdPrintfBuffer, format, arg);
+
+ LcdPutString(lcdPrintfBuffer);
+
+ va_end (arg);
+}
--- /dev/null
+/*-------------------------------------------------------------------------
+ rtc390.c - rtc routines for the DS1315 (tested on TINI)
+
+ Written By - Johan Knol, johan.knol@iduna.nl
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
+-------------------------------------------------------------------------*/
+
+#include <tinibios.h>
+
+#include <stdio.h>
+#include <ctype.h>
+
+//#define USE_LCD
+
+#ifdef USE_LCD
+#include "lcd.h"
+#endif
+
+/* this is the address of the ds1315 phantom time chip, although
+ it doesn't really matter as long as it's in the 300000-3ffff
+ range since the chip only uses CE3*
+*/
+
+xdata at 0x310000 static volatile unsigned char rtc;
+
+// this is the 64bit pattern that has to be recognized by the ds1315
+code unsigned char rtcMagic[8]={0xc5,0x3a,0xa3,0x5c,0xc5,0x3a,0xa3,0x5c};
+
+static struct RTCDate{
+ int year;
+ unsigned char month, day, weekDay, hour, minute, second, hundredth;
+};
+
+#define BCDtoINT(x) (((x)&0x0f)+((x)>>4)*10)
+#define INTtoBCD(x) (((x)%10)+(((x)/10)<<4))
+
+void RtcSync(void) {
+ unsigned char dummy, byte,bitMask;
+
+ // reset rtc chip
+ dummy=rtc;
+
+ // say the magic word
+ for (byte=0; byte<8; byte++) {
+ for (bitMask=0x01; bitMask; bitMask<<=1) {
+ rtc = (rtcMagic[byte]&bitMask) ? 0xff : 0x00;
+ }
+ }
+}
+
+unsigned char RtcRead(struct RTCDate *rtcDate) {
+ unsigned char rtcBytes[8];
+ unsigned char byte,bitMask;
+
+ RtcSync();
+
+ for (byte=0; byte<8; byte++) {
+ rtcBytes[byte]=0;
+ for (bitMask=0x01; bitMask; bitMask<<=1) {
+ if (rtc&1) {
+ rtcBytes[byte]|=bitMask;
+ }
+ }
+ }
+ rtcDate->year=2000 + BCDtoINT(rtcBytes[7]);
+ rtcDate->month=BCDtoINT(rtcBytes[6]);
+ rtcDate->day=BCDtoINT(rtcBytes[5]);
+ rtcDate->weekDay=rtcBytes[4]&0x07;
+ rtcDate->hour=BCDtoINT(rtcBytes[3]);
+ rtcDate->minute=BCDtoINT(rtcBytes[2]);
+ rtcDate->second=BCDtoINT(rtcBytes[1]);
+ rtcDate->hundredth=BCDtoINT(rtcBytes[0]);
+ if ((rtcBytes[4]&0x30) || (rtcBytes[3]&0x80)) {
+ //oscillator not running, reset not active or in 12h mode
+ return 0;
+ }
+ return 1;
+}
+
+void RtcWrite(struct RTCDate *rtcDate) {
+ unsigned char rtcBytes[8];
+ unsigned char byte,bitMask;
+
+ rtcBytes[7]=INTtoBCD(rtcDate->year-2000);
+ rtcBytes[6]=INTtoBCD(rtcDate->month);
+ rtcBytes[5]=INTtoBCD(rtcDate->day);
+ rtcBytes[4]=INTtoBCD(rtcDate->weekDay)&0x07; //set 24h mode
+ rtcBytes[3]=INTtoBCD(rtcDate->hour)&0x3f; // oscilator on, reset on
+ rtcBytes[2]=INTtoBCD(rtcDate->minute);
+ rtcBytes[1]=INTtoBCD(rtcDate->second);
+ rtcBytes[0]=INTtoBCD(rtcDate->hundredth);
+
+ RtcSync();
+
+ for (byte=0; byte<8; byte++) {
+ for (bitMask=0x01; bitMask; bitMask<<=1) {
+ rtc = (rtcBytes[byte]&bitMask) ? 0xff : 0x00;
+ }
+ }
+}
+
+int ScanInt(int current) {
+ char reply[32], *r;
+
+ gets(reply);
+ if (isdigit(*(r=reply))) {
+ current=0;
+ do {
+ current*=10;
+ current+=(*r++)-'0';
+ } while (isdigit(*r));
+ }
+ return current;
+}
+
+char GetTime(struct RTCDate *rtcDate) {
+ printf ("Enter year [%d]: ", rtcDate->year);
+ rtcDate->year=ScanInt(rtcDate->year);
+ printf ("Enter month [%d]: ", rtcDate->month);
+ rtcDate->month=ScanInt(rtcDate->month);
+ printf ("Enter day [%d]: ", rtcDate->day);
+ rtcDate->day=ScanInt(rtcDate->day);
+ printf ("Enter hour [%d]: ", rtcDate->hour);
+ rtcDate->hour=ScanInt(rtcDate->hour);
+ printf ("Enter minute [%d]: ", rtcDate->minute);
+ rtcDate->minute=ScanInt(rtcDate->minute);
+ printf ("Enter second [%d]: ", rtcDate->second);
+ rtcDate->second=ScanInt(rtcDate->second);
+ rtcDate->hundredth=0;
+}
+
+void PrintTime(struct RTCDate *rtcDate) {
+ printf ("%04d-%02bd-%02bd %02bd:%02bd:%02bd.%02bd\n",
+ rtcDate->year, rtcDate->month, rtcDate->day,
+ rtcDate->hour, rtcDate->minute, rtcDate->second,
+ rtcDate->hundredth);
+}
+
+unsigned int intmul(unsigned int a, unsigned int b) {
+ return a*b;
+}
+
+long longmul(long a, long b) {
+ return a*b;
+}
+
+void main (void) {
+ struct RTCDate rtcDate;
+ unsigned char seconds=0xff;
+
+ printf ("\nStarting RTC demo.\n");
+
+#ifdef USE_LCD
+ LcdInit();
+ LcdLPrintf (0, "Starting RTC demo.");
+#endif
+
+ while(1) {
+ RtcRead(&rtcDate);
+
+#ifdef USE_LCD
+ // if lcd is enabled it only syncs the second time
+ RtcRead(&rtcDate);
+#endif
+
+#ifdef USE_LCD
+ LcdLPrintf (2,"%04d-%02bd-%02bd",
+ rtcDate.year, rtcDate.month, rtcDate.day);
+ LcdLPrintf (3, "%02bd:%02bd:%02bd.%02bd",
+ rtcDate.hour, rtcDate.minute, rtcDate.second,
+ rtcDate.hundredth);
+#endif
+ if (rtcDate.second!=seconds) {
+ PrintTime(&rtcDate);
+ seconds=rtcDate.second;
+ }
+
+ if (Serial0CharArrived()) {
+ switch (getchar())
+ {
+ case 0:
+ break;
+ case 'q':
+ printf ("Ok.\n");
+ return;
+ default:
+ if (GetTime(&rtcDate)) {
+#ifndef USE_LCD
+ PrintTime(&rtcDate);
+ RtcWrite(&rtcDate);
+ printf ("Time written.\n");
+#endif
+ }
+ }
+ }
+ }
+
+}