241 lines
5.7 KiB
C
241 lines
5.7 KiB
C
|
/*
|
||
|
* ds1302.c:
|
||
|
* Real Time clock
|
||
|
*
|
||
|
* Copyright (c) 2013 Gordon Henderson.
|
||
|
***********************************************************************
|
||
|
* This file is part of wiringPi:
|
||
|
* https://projects.drogon.net/raspberry-pi/wiringpi/
|
||
|
*
|
||
|
* wiringPi is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* wiringPi 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 Lesser General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU Lesser General Public License
|
||
|
* along with wiringPi. If not, see <http://www.gnu.org/licenses/>.
|
||
|
***********************************************************************
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <stdint.h>
|
||
|
#include <stdarg.h>
|
||
|
|
||
|
#include <wiringPi.h>
|
||
|
|
||
|
#include "ds1302.h"
|
||
|
|
||
|
// Register defines
|
||
|
|
||
|
#define RTC_SECS 0
|
||
|
#define RTC_MINS 1
|
||
|
#define RTC_HOURS 2
|
||
|
#define RTC_DATE 3
|
||
|
#define RTC_MONTH 4
|
||
|
#define RTC_DAY 5
|
||
|
#define RTC_YEAR 6
|
||
|
#define RTC_WP 7
|
||
|
#define RTC_TC 8
|
||
|
#define RTC_BM 31
|
||
|
|
||
|
|
||
|
// Locals
|
||
|
|
||
|
static int dPin, cPin, sPin ;
|
||
|
|
||
|
/*
|
||
|
* dsShiftIn:
|
||
|
* Shift a number in from the chip, LSB first. Note that the data is
|
||
|
* sampled on the trailing edge of the last clock, so it's valid immediately.
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static unsigned int dsShiftIn (void)
|
||
|
{
|
||
|
uint8_t value = 0 ;
|
||
|
int i ;
|
||
|
|
||
|
pinMode (dPin, INPUT) ; delayMicroseconds (1) ;
|
||
|
|
||
|
for (i = 0 ; i < 8 ; ++i)
|
||
|
{
|
||
|
value |= (digitalRead (dPin) << i) ;
|
||
|
digitalWrite (cPin, HIGH) ; delayMicroseconds (1) ;
|
||
|
digitalWrite (cPin, LOW) ; delayMicroseconds (1) ;
|
||
|
}
|
||
|
|
||
|
return value;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* dsShiftOut:
|
||
|
* A normal LSB-first shift-out, just slowed down a bit - the Pi is
|
||
|
* a bit faster than the chip can handle.
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static void dsShiftOut (unsigned int data)
|
||
|
{
|
||
|
int i ;
|
||
|
|
||
|
pinMode (dPin, OUTPUT) ;
|
||
|
|
||
|
for (i = 0 ; i < 8 ; ++i)
|
||
|
{
|
||
|
digitalWrite (dPin, data & (1 << i)) ; delayMicroseconds (1) ;
|
||
|
digitalWrite (cPin, HIGH) ; delayMicroseconds (1) ;
|
||
|
digitalWrite (cPin, LOW) ; delayMicroseconds (1) ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ds1302regRead: ds1302regWrite:
|
||
|
* Read/Write a value to an RTC Register or RAM location on the chip
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
static unsigned int ds1302regRead (const int reg)
|
||
|
{
|
||
|
unsigned int data ;
|
||
|
|
||
|
digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ;
|
||
|
dsShiftOut (reg) ;
|
||
|
data = dsShiftIn () ;
|
||
|
digitalWrite (sPin, LOW) ; delayMicroseconds (1) ;
|
||
|
|
||
|
return data ;
|
||
|
}
|
||
|
|
||
|
static void ds1302regWrite (const int reg, const unsigned int data)
|
||
|
{
|
||
|
digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ;
|
||
|
dsShiftOut (reg) ;
|
||
|
dsShiftOut (data) ;
|
||
|
digitalWrite (sPin, LOW) ; delayMicroseconds (1) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ds1302rtcWrite: ds1302rtcRead:
|
||
|
* Writes/Reads the data to/from the RTC register
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
unsigned int ds1302rtcRead (const int reg)
|
||
|
{
|
||
|
return ds1302regRead (0x81 | ((reg & 0x1F) << 1)) ;
|
||
|
}
|
||
|
|
||
|
void ds1302rtcWrite (int reg, unsigned int data)
|
||
|
{
|
||
|
ds1302regWrite (0x80 | ((reg & 0x1F) << 1), data) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ds1302ramWrite: ds1302ramRead:
|
||
|
* Writes/Reads the data to/from the RTC register
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
unsigned int ds1302ramRead (const int addr)
|
||
|
{
|
||
|
return ds1302regRead (0xC1 | ((addr & 0x1F) << 1)) ;
|
||
|
}
|
||
|
|
||
|
void ds1302ramWrite (const int addr, const unsigned int data)
|
||
|
{
|
||
|
ds1302regWrite ( 0xC0 | ((addr & 0x1F) << 1), data) ;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* ds1302clockRead:
|
||
|
* Read all 8 bytes of the clock in a single operation
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
void ds1302clockRead (int clockData [8])
|
||
|
{
|
||
|
int i ;
|
||
|
unsigned int regVal = 0x81 | ((RTC_BM & 0x1F) << 1) ;
|
||
|
|
||
|
digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ;
|
||
|
|
||
|
dsShiftOut (regVal) ;
|
||
|
for (i = 0 ; i < 8 ; ++i)
|
||
|
clockData [i] = dsShiftIn () ;
|
||
|
|
||
|
digitalWrite (sPin, LOW) ; delayMicroseconds (1) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ds1302clockWrite:
|
||
|
* Write all 8 bytes of the clock in a single operation
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
void ds1302clockWrite (const int clockData [8])
|
||
|
{
|
||
|
int i ;
|
||
|
unsigned int regVal = 0x80 | ((RTC_BM & 0x1F) << 1) ;
|
||
|
|
||
|
digitalWrite (sPin, HIGH) ; delayMicroseconds (1) ;
|
||
|
|
||
|
dsShiftOut (regVal) ;
|
||
|
for (i = 0 ; i < 8 ; ++i)
|
||
|
dsShiftOut (clockData [i]) ;
|
||
|
|
||
|
digitalWrite (sPin, LOW) ; delayMicroseconds (1) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ds1302trickleCharge:
|
||
|
* Set the bits on the trickle charger.
|
||
|
* Probably best left alone...
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
void ds1302trickleCharge (const int diodes, const int resistors)
|
||
|
{
|
||
|
if (diodes + resistors == 0)
|
||
|
ds1302rtcWrite (RTC_TC, 0x5C) ; // Disabled
|
||
|
else
|
||
|
ds1302rtcWrite (RTC_TC, 0xA0 | ((diodes & 3) << 2) | (resistors & 3)) ;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* ds1302setup:
|
||
|
* Initialise the chip & remember the pins we're using
|
||
|
*********************************************************************************
|
||
|
*/
|
||
|
|
||
|
void ds1302setup (const int clockPin, const int dataPin, const int csPin)
|
||
|
{
|
||
|
dPin = dataPin ;
|
||
|
cPin = clockPin ;
|
||
|
sPin = csPin ;
|
||
|
|
||
|
digitalWrite (dPin, LOW) ;
|
||
|
digitalWrite (cPin, LOW) ;
|
||
|
digitalWrite (sPin, LOW) ;
|
||
|
|
||
|
pinMode (dPin, OUTPUT) ;
|
||
|
pinMode (cPin, OUTPUT) ;
|
||
|
pinMode (sPin, OUTPUT) ;
|
||
|
|
||
|
ds1302rtcWrite (RTC_WP, 0) ; // Remove write-protect
|
||
|
}
|