173 lines
5.6 KiB
C
173 lines
5.6 KiB
C
|
|
|
|
// ------- Preamble -------- //
|
|
#include <avr/io.h>
|
|
#include <util/delay.h>
|
|
#include <avr/interrupt.h>
|
|
#include <avr/power.h>
|
|
|
|
#include "pinDefines.h"
|
|
#include "USART.h"
|
|
|
|
#include "i2c.h" /* for i2c functions */
|
|
#include "25LC256.h" /* for EEPROM specific */
|
|
|
|
// -------- Defines --------- //
|
|
|
|
#define LM75_ADDRESS_W 0b10010000
|
|
#define LM75_ADDRESS_R 0b10010001
|
|
#define LM75_TEMP_REGISTER 0b00000000
|
|
#define LM75_CONFIG_REGISTER 0b00000001
|
|
#define LM75_THYST_REGISTER 0b00000010
|
|
#define LM75_TOS_REGISTER 0b00000011
|
|
|
|
#define CURRENT_LOCATION_POINTER 0
|
|
/* where to store a pointer to the current reading in EEPROM */
|
|
#define SECONDS_POINTER 2
|
|
/* store seconds-delay value here */
|
|
#define MEMORY_START 4
|
|
/* where to start logging temperature values */
|
|
#define MENU_DELAY 5
|
|
/* seconds to wait before bypassing main menu */
|
|
|
|
// -------- Functions --------- //
|
|
|
|
static inline void printTemperature(uint8_t tempReading) {
|
|
/* temperature stored as 2x Celcius */
|
|
printByte((tempReading >> 1));
|
|
if (tempReading & 1) {
|
|
printString(".5\r\n");
|
|
}
|
|
else {
|
|
printString(".0\r\n");
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
uint16_t secondsDelay; /* how long to wait between readings */
|
|
uint16_t currentMemoryLocation; /* where are we in EEPROM? */
|
|
uint16_t i; /* used to count memory locations */
|
|
uint8_t tempHighByte, tempLowByte, temperatureByte; /* from LM75 */
|
|
uint8_t enterMenu; /* logical flag */
|
|
|
|
// -------- Inits --------- //
|
|
clock_prescale_set(clock_div_1); /* 8 MHz */
|
|
initSPI();
|
|
initI2C();
|
|
initUSART();
|
|
LED_DDR |= (1 << LED0);
|
|
|
|
/* Load up last values from EEPROM */
|
|
secondsDelay = EEPROM_readWord(SECONDS_POINTER);
|
|
|
|
/* Delay to allow input to enter main menu */
|
|
printString("*** Press [m] within ");
|
|
printByte(MENU_DELAY);
|
|
printString(" seconds to enter menu. ***\r\n ");
|
|
|
|
for (i = 0; i < MENU_DELAY; i++) {
|
|
_delay_ms(1000);
|
|
}
|
|
|
|
if (bit_is_set(UCSR0A, RXC0) && (UDR0 == 'm')) {
|
|
enterMenu = 1;
|
|
}
|
|
else {
|
|
enterMenu = 0;
|
|
}
|
|
|
|
while (enterMenu) {
|
|
printString("\r\n====[ Logging Thermometer ]====\r\n ");
|
|
currentMemoryLocation = EEPROM_readWord(CURRENT_LOCATION_POINTER);
|
|
printWord(currentMemoryLocation - MEMORY_START);
|
|
printString(" readings in log.\r\n ");
|
|
printWord(secondsDelay);
|
|
printString(" seconds between readings.\r\n");
|
|
printString(" [<] to shorten sample delay time\r\n");
|
|
printString(" [>] to increase sample delay time\r\n");
|
|
printString(" [?] to reset delay time to 60 sec\r\n");
|
|
printString(" [d] to print out log over serial\r\n");
|
|
printString(" [e] to erase memory\r\n");
|
|
printString(" [s] to start logging\r\n\r\n");
|
|
|
|
switch (receiveByte()) {
|
|
case 'd':
|
|
SLAVE_SELECT;
|
|
SPI_tradeByte(EEPROM_READ);
|
|
EEPROM_send16BitAddress(MEMORY_START);
|
|
for (i = MEMORY_START; i < currentMemoryLocation; i++) {
|
|
SPI_tradeByte(0);
|
|
printTemperature(SPDR);
|
|
}
|
|
SLAVE_DESELECT;
|
|
break;
|
|
case '<':
|
|
if (secondsDelay >= 10) {
|
|
secondsDelay -= 5;
|
|
EEPROM_writeWord(SECONDS_POINTER, secondsDelay);
|
|
}
|
|
break;
|
|
case '>':
|
|
if (secondsDelay < 65000) {
|
|
secondsDelay += 5;
|
|
EEPROM_writeWord(SECONDS_POINTER, secondsDelay);
|
|
}
|
|
break;
|
|
case '?':
|
|
secondsDelay = 60;
|
|
EEPROM_writeWord(SECONDS_POINTER, secondsDelay);
|
|
break;
|
|
case 'e':
|
|
printString("Clearing EEPROM, this could take a few seconds.\r\n");
|
|
EEPROM_clearAll();
|
|
EEPROM_writeWord(CURRENT_LOCATION_POINTER, MEMORY_START);
|
|
EEPROM_writeWord(SECONDS_POINTER, secondsDelay);
|
|
break;
|
|
case 's':
|
|
printString("OK, logging...\r\n");
|
|
enterMenu = 0;
|
|
break;
|
|
default:
|
|
printString("Sorry, didn't understand that.\r\n");
|
|
}
|
|
}
|
|
|
|
// ------ Event loop ------ //
|
|
while (1) {
|
|
|
|
currentMemoryLocation = EEPROM_readWord(CURRENT_LOCATION_POINTER);
|
|
|
|
/* Make sure in temperature mode */
|
|
i2cStart();
|
|
i2cSend(LM75_ADDRESS_W);
|
|
i2cSend(LM75_TEMP_REGISTER);
|
|
/* Get Temp from thermometer */
|
|
i2cStart(); /* Setup and send address, with read bit */
|
|
i2cSend(LM75_ADDRESS_R);
|
|
tempHighByte = i2cReadAck(); /* two bytes of temperature */
|
|
tempLowByte = i2cReadNoAck();
|
|
i2cStop();
|
|
temperatureByte = (tempHighByte << 1) | (tempLowByte >> 7);
|
|
/* temperatureByte now contains 2x the temperature in Celcius */
|
|
printTemperature(temperatureByte); /* serial output */
|
|
|
|
/* Save the new temperature value */
|
|
EEPROM_writeByte(currentMemoryLocation, temperatureByte);
|
|
|
|
/* move on to next location and record new position
|
|
if not already at the end of memory */
|
|
if (currentMemoryLocation < EEPROM_BYTES_MAX) {
|
|
currentMemoryLocation++;
|
|
EEPROM_writeWord(CURRENT_LOCATION_POINTER, currentMemoryLocation);
|
|
}
|
|
|
|
/* delay */
|
|
for (i = 0; i < secondsDelay; i++) {
|
|
_delay_ms(1000);
|
|
LED_PORT ^= (1 << LED0); /* blink to show working */
|
|
}
|
|
|
|
} /* End event loop */
|
|
return 0; /* This line is never reached */
|
|
}
|