#include <avr/io.h>
#include <util/delay.h>
#include <avr/power.h>
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
// ds1307,
#define DS3231_I2C_ADDRESS 0x68
#define LCD_PORT PORTD
#define LCD_DDR DDRD
#define LCD_DATA1 PD0
#define LCD_DATA2 PD1
#define LCD_DATA3 PD2
#define LCD_DATA4 PD3
#define LCD_SCLK PD4
#define LCD_OE PD5
#define LCD_COM PD6
#define KEY1_PORT PORTB
#define KEY1_DDR DDRB
#define KEY1_PIN PINB
#define KEY1 PB0
#define KEY2_PORT PORTD
#define KEY2_DDR DDRD
#define KEY2_PIN PIND
#define KEY2 PD7
#define DS1307SQ PB1
#define DS1307SQ_INT PCIE0
#define DS1307SQ_PORT PORTB
#define DS1307SQ_DDR DDRB
#define DS1307SQ_PIN PINB
#define DS1307SQ_VEC PCINT0_vect
#define DS1307SQ_MSK PCMSK0
// . , -, , -
#define LM335_PORT PORTC
#define LM335_DDR DDRC
#define LM335 PC3
//
unsigned char lcd_buf[4];
#define MODE_MAIN 0
#define MODE_CALENDAR 1
#define MODE_YEAR 2
#define MODE_TERMOMETER 3 //
#define MODE_VOLTMETER 4 //
#define MODE_SET_MINUTE 5
#define MODE_SET_HOUR 6
#define MODE_SET_DAY 7
#define MODE_SET_MONTH 8
#define MODE_SET_YEAR 9
#define MODE_SECOND 10
#define MODE_DEBUG 11 //
// 10ms ()
#define MODE_TIMEOUT 20 // 2
#define MODE_TIMEOUT_SET 100 // 10
#define KEY_TIMEOUT 10 // 1
byte mode = MODE_MAIN;
byte mode_timeout = 0;
byte key1_press = 0;
byte key1_time = 0;
byte key2_press = 0;
byte key2_time = 0;
byte cycle_count_10 = 0; //
byte even_10 = 0; // 1/10
// ds1307
byte second;
byte minute;
byte hour;
byte dayOfWeek;
byte dayOfMonth;
byte month;
byte year;
volatile byte need_render_int = 1;
uint8_t porthistory = 0xFF;
volatile uint8_t debug_value = 0;
byte twi_problems = 0;
// ds1307 SQ
// ,
ISR(DS1307SQ_VEC) {
uint8_t changedbits = DS1307SQ_PIN ^ porthistory;
porthistory = DS1307SQ_PIN;
if (changedbits & _BV(DS1307SQ) && porthistory & _BV(DS1307SQ)) {
need_render_int = 1;
}
}
//
void lcd_num(char pos, char num) {
unsigned char buf = 0b01110110;
if (pos < 1 || pos > 3) {
return;
}
switch (num) {
case 0:
// 3- , ?
// , ,
// :-(
if (pos == 3) {
buf = 0b11101110;
} else {
buf = 0b11100111;
}
break;
case 1:
if (pos == 3) {
buf = 0b10001000;
} else {
buf = 0b10000001;
}
break;
case 2:
buf = 0b11010110;
break;
case 3:
if (pos == 3) {
buf = 0b11011100;
} else {
buf = 0b11010011;
}
break;
case 4:
if (pos == 3) {
buf = 0b10111000;
} else {
buf = 0b10110001;
}
break;
case 5:
if (pos == 3) {
buf = 0b01111100;
} else {
buf = 0b01110011;
}
break;
case 6:
if (pos == 3) {
buf = 0b01111110;
} else {
buf = 0b01110111;
}
break;
case 7:
if (pos == 3) {
buf = 0b11001000;
} else {
buf = 0b11000001;
}
break;
case 8:
if (pos == 3) {
buf = 0b11111110;
} else {
buf = 0b11110111;
}
break;
case 9:
if (pos == 3) {
buf = 0b11111100;
} else {
buf = 0b11110011;
}
break;
}
lcd_buf[pos] = buf;
}
//
void lcd_one(bool e) {
if (e) {
lcd_buf[0] |= (1 << 0);
} else {
lcd_buf[0] &= ~(1 << 0);
}
}
void lcd_sec(bool e) {
if (e) {
lcd_buf[0] |= (1 << 7);
} else {
lcd_buf[0] &= ~(1 << 7);
}
}
void lcd_minus(bool e) {
if (e) {
lcd_buf[0] |= (1 << 1);
} else {
lcd_buf[0] &= ~(1 << 1);
}
}
void lcd_plus(bool e) {
if (e) {
lcd_buf[0] |= (1 << 6);
} else {
lcd_buf[0] &= ~(1 << 6);
}
}
void lcd_lo(bool e) {
if (e) {
lcd_buf[0] |= (1 << 5);
} else {
lcd_buf[0] &= ~(1 << 5);
}
}
void lcd_over(bool e) {
if (e) {
lcd_buf[0] |= (1 << 4);
} else {
lcd_buf[0] &= ~(1 << 4);
}
}
void lcd_dot(int pos, bool e) {
int pos_buf;
if (pos == 1) {
pos_buf = 3;
} else if (pos == 2) {
pos_buf = 2;
} else if (pos == 3) {
pos_buf = 1;
} else {
return;
}
if (pos_buf == 3) {
if (e) {
lcd_buf[pos_buf] |= (1 << 0);
} else {
lcd_buf[pos_buf] &= ~(1 << 0);
}
} else {
if (e) {
lcd_buf[pos_buf] |= (1 << 3);
} else {
lcd_buf[pos_buf] &= ~(1 << 3);
}
}
}
// 100
// 595-,
void lcd_refresh() {
unsigned char data1 = lcd_buf[0];
unsigned char data2 = lcd_buf[1];
unsigned char data3 = lcd_buf[2];
unsigned char data4 = lcd_buf[3];
byte reverse = data1 & (1 << 3); //
if (reverse) { // ,
data1 = ~data1;
data2 = ~data2;
data3 = ~data3;
data4 = ~data4;
}
for (int i = 0; i < 8; i++) {
//
if (data1 & (1 << i)) {
LCD_PORT |= _BV(LCD_DATA1);
} else {
LCD_PORT &= ~_BV(LCD_DATA1);
}
if (data2 & (1 << i)) {
LCD_PORT |= _BV(LCD_DATA2);
} else {
LCD_PORT &= ~_BV(LCD_DATA2);
}
if (data3 & (1 << i)) {
LCD_PORT |= _BV(LCD_DATA3);
} else {
LCD_PORT &= ~_BV(LCD_DATA3);
}
if (data4 & (1 << i)) {
LCD_PORT |= _BV(LCD_DATA4);
} else {
LCD_PORT &= ~_BV(LCD_DATA4);
}
// SCLK 595-
sbi(LCD_PORT, LCD_SCLK);
// SCLK 595-
cbi(LCD_PORT, LCD_SCLK);
}
// SCLK
// SCLK RCLK ,
// .
// , -, .
// SCLK RCLK, OE (. 74HC595)
// .
sbi(LCD_PORT, LCD_SCLK);
cbi(LCD_PORT, LCD_SCLK);
// -
// - - , 1 40
// (- ; )
// 4 595-,
// ,
if (reverse) {
sbi(LCD_PORT, LCD_COM);
} else {
cbi(LCD_PORT, LCD_COM);
}
//
lcd_buf[0] ^= (1 << 3);
}
// ,
void do_render() {
lcd_buf[0] = 0;
lcd_buf[1] = 0;
lcd_buf[2] = 0;
lcd_buf[3] = 0;
if (twi_problems) {
lcd_lo(1);
}
if (mode == MODE_MAIN) {
lcd_num(3, minute % 10);
lcd_num(2, minute / 10);
byte hour1 = (hour <= 12) ? hour : (hour % 12);
lcd_num(1, hour1 % 10);
if (hour1 >= 10) {
lcd_one(1);
}
// , . .
// SQ ,
// ,
//
if (second % 2) {
lcd_sec(1);
}
} else if (mode == MODE_CALENDAR) {
lcd_num(3, dayOfMonth % 10);
lcd_num(2, dayOfMonth / 10);
lcd_num(1, month % 10);
if (month >= 10) {
lcd_one(1);
} else {
lcd_one(0);
}
lcd_dot(2, 1);
} else if (mode == MODE_YEAR) {
lcd_num(3, year % 10);
lcd_num(2, year / 10);
lcd_buf[1] = 0b10110011; // y.
} else if (mode == MODE_TERMOMETER) {
} else if (mode == MODE_VOLTMETER) {
} else if (mode == MODE_SET_MINUTE) {
if (even_10) {
lcd_num(3, minute % 10);
lcd_num(2, minute / 10);
}
byte hour1 = (hour <= 12) ? hour : (hour % 12);
lcd_num(1, hour1 % 10);
if (hour1 >= 10) {
lcd_one(1);
} else {
lcd_one(0);
}
lcd_sec(1);
} else if (mode == MODE_SET_HOUR) {
lcd_num(3, minute % 10);
lcd_num(2, minute / 10);
if (even_10) {
byte hour1 = (hour <= 12) ? hour : (hour % 12);
lcd_num(1, hour1 % 10);
if (hour1 >= 10) {
lcd_one(1);
} else {
lcd_one(0);
}
if (hour > 12) {
lcd_over(1);
} else {
lcd_over(0);
}
}
lcd_sec(1);
} else if (mode == MODE_SET_DAY) {
if (even_10) {
lcd_num(3, dayOfMonth % 10);
lcd_num(2, dayOfMonth / 10);
}
lcd_num(1, month % 10);
if (month >= 10) {
lcd_one(1);
} else {
lcd_one(0);
}
lcd_dot(2, 1);
} else if (mode == MODE_SET_MONTH) {
lcd_num(3, dayOfMonth % 10);
lcd_num(2, dayOfMonth / 10);
if (even_10) {
lcd_num(1, month % 10);
if (month >= 10) {
lcd_one(1);
} else {
lcd_one(0);
}
}
lcd_dot(2, 1);
} else if (mode == MODE_SET_YEAR) {
if (even_10) {
lcd_num(3, year % 10);
lcd_num(2, year / 10);
}
lcd_buf[1] = 0b10110011;
} else if (mode == MODE_SECOND) {
lcd_sec(1);
lcd_num(3, second % 10);
lcd_num(2, second / 10);
} else if (mode == MODE_DEBUG) {
byte d = debug_value;
lcd_num(3, d % 10);
d /= 10;
lcd_num(2, d % 10);
lcd_num(2, d / 10);
}
}
int main(void)
{
// - .
// , , .
// ACSR = (1<<ACD);
ADCSRA = (0<<ADEN);
PRR = (1<<PRTIM0) | (1<<PRTIM1) | (1<<PRTIM2) | (1<<PRSPI) | (1<<PRADC) | (1<<PRUSART0);
//
DDRB = 0x00;
PORTB = 0xff;
DDRC = 0x00;
PORTC = 0xff;
DDRD = 0x00;
PORTD = 0xff;
lcd_buf[0] = 0x0;
lcd_buf[1] = 0x0;
lcd_buf[2] = 0x0;
lcd_buf[3] = 0x0;
twi_begin();
// . usbasp,
// , ,
// DDRB |= _BV(PB7);
// PORTB |= _BV(PB7); // off
// -
LCD_DDR |= (_BV(LCD_DATA1) | _BV(LCD_DATA2) | _BV(LCD_DATA3) | _BV(LCD_DATA4) | _BV(LCD_SCLK) | _BV(LCD_OE) | _BV(LCD_COM));
cbi(LCD_PORT, LCD_SCLK);
cbi(LCD_PORT, LCD_OE);
//
KEY1_DDR &= ~(_BV(KEY1));
KEY1_PORT |= _BV(KEY1);
KEY2_DDR &= ~(_BV(KEY2));
KEY2_PORT |= _BV(KEY2);
// ds1307
DS1307SQ_DDR &= ~_BV(DS1307SQ);
DS1307SQ_PORT |= _BV(DS1307SQ);
PCICR |= _BV(DS1307SQ_INT);
DS1307SQ_MSK |= _BV(DS1307SQ);
sei();
// ds1307 , ,
// , -
// setDS3231time(30,40,21,6,11,3,18);
while(1)
{
byte need_render = 0;
byte need_date_set = 0;
// ds1307,
//
if (need_render_int) {
byte rc;
if (mode == MODE_MAIN) {
rc = readDS3231time_hms(&second, &minute, &hour);
} else {
rc = readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, &year);
}
if ( ! rc && twi_problems) {
twi_problems -= 1;
} else {
twi_problems += rc;
}
need_render = 1;
need_render_int = 0;
}
// 1/10
if ( ! cycle_count_10) {
even_10 = ! even_10;
// ,
if (mode_timeout > 0) {
mode_timeout -= 1;
}
// ,
if (mode != MODE_MAIN && ! mode_timeout) {
mode = MODE_MAIN;
need_render = 1;
}
// , 10
if (mode == MODE_SET_MINUTE || mode == MODE_SET_HOUR || mode == MODE_SET_DAY || mode == MODE_SET_MONTH || mode == MODE_SET_YEAR) {
need_render = 1;
}
//
byte key1_down = (KEY1_PIN & _BV(KEY1)) ? 0 : 1;
byte key2_down = (KEY2_PIN & _BV(KEY2)) ? 0 : 1;
if (key1_down || key2_down || key1_press || key2_press) {
need_render = 1;
}
if (key1_down && key1_press) {
key1_time += 1;
}
if (key2_down && key2_press) {
key2_time += 1;
}
//
if (key1_down && ! key1_press) {
if (mode == MODE_SET_MINUTE) {
mode = MODE_SET_HOUR;
mode_timeout = MODE_TIMEOUT_SET;
} else if (mode == MODE_SET_HOUR) {
mode = MODE_SET_DAY;
mode_timeout = MODE_TIMEOUT_SET;
} else if (mode == MODE_SET_DAY) {
mode = MODE_SET_MONTH;
mode_timeout = MODE_TIMEOUT_SET;
} else if (mode == MODE_SET_MONTH) {
mode = MODE_SET_YEAR;
mode_timeout = MODE_TIMEOUT_SET;
} else if (mode == MODE_SET_YEAR) {
mode = MODE_MAIN;
} else if (mode == MODE_MAIN) {
mode = MODE_SECOND;
mode_timeout = MODE_TIMEOUT_SET;
} else if (mode == MODE_SECOND) {
mode = MODE_MAIN;
mode_timeout = 0;
}
} else if ( ! key1_down && key1_press) {
if (key1_time >= KEY_TIMEOUT) {
} else {
}
} else if (key1_down && key1_press) {
if (key1_time >= KEY_TIMEOUT) {
if (mode == MODE_MAIN || mode == MODE_SECOND) {
mode = MODE_SET_MINUTE;
mode_timeout = MODE_TIMEOUT_SET;
}
} else {
}
}
if (key2_down && ! key2_press) {
if (mode == MODE_MAIN) {
mode = MODE_CALENDAR;
mode_timeout = MODE_TIMEOUT;
} else if (mode == MODE_CALENDAR) {
mode = MODE_YEAR;
mode_timeout = MODE_TIMEOUT;
} else if (mode == MODE_YEAR) {
mode = MODE_MAIN;
mode_timeout = 0;
} else if (mode == MODE_SET_MINUTE) {
minute += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_HOUR) {
hour += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_DAY) {
dayOfMonth += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_MONTH) {
month += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_YEAR) {
year += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SECOND) {
second = 0;
need_date_set = 1;
mode_timeout = MODE_TIMEOUT_SET;
}
} else if ( ! key2_down && key2_press) {
if (key2_time >= KEY_TIMEOUT) {
} else {
}
} else if (key2_down && key2_press) {
if (key2_time >= KEY_TIMEOUT) {
if (mode == MODE_SET_MINUTE) {
minute += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_HOUR) {
hour += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_DAY) {
dayOfMonth += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_MONTH) {
month += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
} else if (mode == MODE_SET_YEAR) {
year += 1;
mode_timeout = MODE_TIMEOUT_SET;
need_date_set = 1;
}
} else {
}
}
key1_press = key1_down;
if ( ! key1_press) {
key1_time = 0;
}
key2_press = key2_down;
if ( ! key2_press) {
key2_time = 0;
}
}
if (need_date_set) {
//
// ds1307 ,
// , ,
if (minute > 59) {
minute = 0;
}
if (hour > 23) {
hour = 0;
}
if (dayOfMonth > 31) {
dayOfMonth = 1;
}
if (month > 12) {
month = 1;
}
if (year > 99) {
year = 0;
}
// ds1307
setDS3231time(second, minute, hour, dayOfWeek, dayOfMonth, month, year);
}
// ,
if (need_render) {
do_render();
}
//
cli();
lcd_refresh();
sei();
_delay_ms(10);
cycle_count_10 += 1;
if (cycle_count_10 >= 10) {
cycle_count_10 = 0;
}
}
return 0;
}
// -
byte decToBcd(byte val)
{
return( (val/10*16) + (val%10) );
}
byte bcdToDec(byte val)
{
return( (val/16*10) + (val%16) );
}
// ds1307
void setDS3231time(byte second,
byte minute,
byte hour,
byte dayOfWeek,
byte dayOfMonth,
byte month,
byte year)
{
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 0, (uint8_t) decToBcd(second));
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 1, (uint8_t) decToBcd(minute));
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 2, (uint8_t) decToBcd(hour));
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 3, (uint8_t) decToBcd(dayOfWeek));
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 4, (uint8_t) decToBcd(dayOfMonth));
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 5, (uint8_t) decToBcd(month));
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 6, (uint8_t) decToBcd(year));
// SQ 1Hz
// , ds1307
// 8kHz
twi_write((uint8_t) DS3231_I2C_ADDRESS, (uint8_t) 7, (uint8_t) 0b00010000);
}
// ds1307
byte readDS3231time(byte *second,
byte *minute,
byte *hour,
byte *dayOfWeek,
byte *dayOfMonth,
byte *month,
byte *year)
{
byte rc = twi_read(DS3231_I2C_ADDRESS, 0, 7);
if (rc) return 1;
*second = bcdToDec(twi_receive() & 0x7f);
*minute = bcdToDec(twi_receive());
*hour = bcdToDec(twi_receive() & 0x3f);
*dayOfWeek = bcdToDec(twi_receive());
*dayOfMonth = bcdToDec(twi_receive());
*month = bcdToDec(twi_receive());
*year = bcdToDec(twi_receive());
}
// , , ,
byte readDS3231time_hms(byte *second, byte *minute, byte *hour) {
byte rc = twi_read(DS3231_I2C_ADDRESS, 0, 3);
if (rc) return 1;
*second = bcdToDec(twi_receive() & 0x7f);
*minute = bcdToDec(twi_receive());
*hour = bcdToDec(twi_receive() & 0x3f);
}
/*
* , , : http://dsscircuits.com/articles/arduino-i2c-master-library
* , 4k .
*/
/*
This library 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 2.1 of the License, or (at your option) any later version.
This library 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 this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#define START 0x08
#define REPEATED_START 0x10
#define MT_SLA_ACK 0x18
#define MT_SLA_NACK 0x20
#define MT_DATA_ACK 0x28
#define MT_DATA_NACK 0x30
#define MR_SLA_ACK 0x40
#define MR_SLA_NACK 0x48
#define MR_DATA_ACK 0x50
#define MR_DATA_NACK 0x58
#define LOST_ARBTRTN 0x38
#define TWI_STATUS (TWSR & 0xF8)
#define SLA_W(address) (address << 1)
#define SLA_R(address) ((address << 1) + 0x01)
#define MAX_BUFFER_SIZE 32
uint8_t twi_bytesAvailable = 0;
uint8_t twi_bufferIndex = 0;
uint8_t twi_totalBytes = 0;
uint16_t twi_timeOutDelay = 0;
uint8_t twi_returnStatus;
uint8_t twi_nack;
uint8_t twi_data[MAX_BUFFER_SIZE];
void twi_begin()
{
sbi(PORTC, 4);
sbi(PORTC, 5);
cbi(TWSR, TWPS0);
cbi(TWSR, TWPS1);
TWBR = ((F_CPU / 100000) - 16) / 2;
TWCR = _BV(TWEN) | _BV(TWEA);
}
uint8_t twi_read(uint8_t address, uint8_t registerAddress, uint8_t numberBytes)
{
twi_bytesAvailable = 0;
twi_bufferIndex = 0;
if(numberBytes == 0){numberBytes++;}
twi_nack = numberBytes - 1;
twi_returnStatus = 0;
twi_returnStatus = twi_start();
if(twi_returnStatus){return(twi_returnStatus);}
twi_returnStatus = twi_sendAddress(SLA_W(address));
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(2);}
return(twi_returnStatus);
}
twi_returnStatus = twi_sendByte(registerAddress);
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(3);}
return(twi_returnStatus);
}
twi_returnStatus = twi_start();
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(4);}
return(twi_returnStatus);
}
twi_returnStatus = twi_sendAddress(SLA_R(address));
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(5);}
return(twi_returnStatus);
}
for(uint8_t i = 0; i < numberBytes; i++)
{
if( i == twi_nack )
{
twi_returnStatus = twi_receiveByte(0);
if(twi_returnStatus == 1){return(6);}
if(twi_returnStatus != MR_DATA_NACK){return(twi_returnStatus);}
}
else
{
twi_returnStatus = twi_receiveByte(1);
if(twi_returnStatus == 1){return(6);}
if(twi_returnStatus != MR_DATA_ACK){return(twi_returnStatus);}
}
twi_data[i] = TWDR;
twi_bytesAvailable = i+1;
twi_totalBytes = i+1;
}
twi_returnStatus = twi_stop();
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(7);}
return(twi_returnStatus);
}
return(twi_returnStatus);
}
uint8_t twi_write(uint8_t address, uint8_t registerAddress, uint8_t data)
{
twi_returnStatus = 0;
twi_returnStatus = twi_start();
if(twi_returnStatus){return(twi_returnStatus);}
twi_returnStatus = twi_sendAddress(SLA_W(address));
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(2);}
return(twi_returnStatus);
}
twi_returnStatus = twi_sendByte(registerAddress);
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(3);}
return(twi_returnStatus);
}
twi_returnStatus = twi_sendByte(data);
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(3);}
return(twi_returnStatus);
}
twi_returnStatus = twi_stop();
if(twi_returnStatus)
{
if(twi_returnStatus == 1){return(7);}
return(twi_returnStatus);
}
return(twi_returnStatus);
}
uint8_t twi_receive()
{
twi_bufferIndex = twi_totalBytes - twi_bytesAvailable;
if(!twi_bytesAvailable)
{
twi_bufferIndex = 0;
return(0);
}
twi_bytesAvailable--;
return(twi_data[twi_bufferIndex]);
}
uint8_t twi_start()
{
unsigned long startingTime = millis();
TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
if(!twi_timeOutDelay){continue;}
if((millis() - startingTime) >= twi_timeOutDelay)
{
twi_lockUp();
return(1);
}
}
if ((TWI_STATUS == START) || (TWI_STATUS == REPEATED_START))
{
return(0);
}
if (TWI_STATUS == LOST_ARBTRTN)
{
uint8_t bufferedStatus = TWI_STATUS;
twi_lockUp();
return(bufferedStatus);
}
return(TWI_STATUS);
}
uint8_t twi_sendAddress(uint8_t i2cAddress)
{
TWDR = i2cAddress;
unsigned long startingTime = millis();
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
if(!twi_timeOutDelay){continue;}
if((millis() - startingTime) >= twi_timeOutDelay)
{
twi_lockUp();
return(1);
}
}
if ((TWI_STATUS == MT_SLA_ACK) || (TWI_STATUS == MR_SLA_ACK))
{
return(0);
}
uint8_t bufferedStatus = TWI_STATUS;
if ((TWI_STATUS == MT_SLA_NACK) || (TWI_STATUS == MR_SLA_NACK))
{
twi_stop();
return(bufferedStatus);
}
else
{
twi_lockUp();
return(bufferedStatus);
}
}
uint8_t twi_sendByte(uint8_t i2cData)
{
TWDR = i2cData;
unsigned long startingTime = millis();
TWCR = (1<<TWINT) | (1<<TWEN);
while (!(TWCR & (1<<TWINT)))
{
if(!twi_timeOutDelay){continue;}
if((millis() - startingTime) >= twi_timeOutDelay)
{
twi_lockUp();
return(1);
}
}
if (TWI_STATUS == MT_DATA_ACK)
{
return(0);
}
uint8_t bufferedStatus = TWI_STATUS;
if (TWI_STATUS == MT_DATA_NACK)
{
twi_stop();
return(bufferedStatus);
}
else
{
twi_lockUp();
return(bufferedStatus);
}
}
uint8_t twi_receiveByte(uint8_t ack)
{
unsigned long startingTime = millis();
if(ack)
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
}
else
{
TWCR = (1<<TWINT) | (1<<TWEN);
}
while (!(TWCR & (1<<TWINT)))
{
if(!twi_timeOutDelay){continue;}
if((millis() - startingTime) >= twi_timeOutDelay)
{
twi_lockUp();
return(1);
}
}
if (TWI_STATUS == LOST_ARBTRTN)
{
uint8_t bufferedStatus = TWI_STATUS;
twi_lockUp();
return(bufferedStatus);
}
return(TWI_STATUS);
}
uint8_t twi_stop()
{
unsigned long startingTime = millis();
TWCR = (1<<TWINT)|(1<<TWEN)| (1<<TWSTO);
while ((TWCR & (1<<TWSTO)))
{
if(!twi_timeOutDelay){continue;}
if((millis() - startingTime) >= twi_timeOutDelay)
{
twi_lockUp();
return(1);
}
}
return(0);
}
void twi_lockUp()
{
TWCR = 0;
TWCR = _BV(TWEN) | _BV(TWEA);
}