Merge pull request #6 from madcow/atmega1284p
Update project to run on atmega1284p hardware
This commit is contained in:
18
Makefile
18
Makefile
@@ -9,17 +9,16 @@
|
|||||||
# ==============================================================================
|
# ==============================================================================
|
||||||
|
|
||||||
VERBOSE := false
|
VERBOSE := false
|
||||||
#ARCH := m1284p
|
ARCH := m1284
|
||||||
ARCH := m32
|
|
||||||
#FREQ := 18432000UL
|
#FREQ := 18432000UL
|
||||||
FREQ := 8000000UL
|
FREQ := 8000000UL
|
||||||
#MCU := atmega1284p
|
MCU := atmega1284p
|
||||||
MCU := atmega32a
|
|
||||||
ASP := usbasp
|
ASP := usbasp
|
||||||
CC := avr-gcc
|
CC := avr-gcc
|
||||||
LD := $(CC)
|
LD := $(CC)
|
||||||
OBJCOPY := avr-objcopy
|
OBJCOPY := avr-objcopy
|
||||||
AVD := avrdude
|
AVD := avrdude
|
||||||
|
SIM := simavr
|
||||||
MKDIR := mkdir -p
|
MKDIR := mkdir -p
|
||||||
RMR := rm -rf
|
RMR := rm -rf
|
||||||
GIT := git
|
GIT := git
|
||||||
@@ -59,10 +58,17 @@ flash: $(TARGET)
|
|||||||
$(E) "[AVD] Flashing..."
|
$(E) "[AVD] Flashing..."
|
||||||
$(Q) $(AVD) -l $(LOGFILE) \
|
$(Q) $(AVD) -l $(LOGFILE) \
|
||||||
-c $(ASP) -p $(ARCH) \
|
-c $(ASP) -p $(ARCH) \
|
||||||
-U lfuse:w:0xff:m \
|
-U lfuse:w:0xC2:m \
|
||||||
-U hfuse:w:0x91:m \
|
-U hfuse:w:0x9F:m \
|
||||||
|
-U efuse:w:0xFF:m \
|
||||||
|
-U lock:w:0xFF:m \
|
||||||
-U flash:w:$<
|
-U flash:w:$<
|
||||||
|
|
||||||
|
.PHONY: run
|
||||||
|
run: $(TARGET)
|
||||||
|
$(E) "[SIM] $<"
|
||||||
|
$(Q) $(SIM) -m $(MCU) -f $(FREQ) $<
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
$(E) "[REM] $(TARGET)"
|
$(E) "[REM] $(TARGET)"
|
||||||
|
|||||||
@@ -1,23 +1,15 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "bus/pwm.h"
|
#include "bus/pwm.h"
|
||||||
|
|
||||||
|
// TODO: Add documentation for timer3: TCCR3A, TCCR3B, etc.
|
||||||
|
|
||||||
int PWM_Init(void)
|
int PWM_Init(void)
|
||||||
{
|
{
|
||||||
// PD4: PWM NF-12 Fan Peltier Hot Side
|
// PD4: PWM NF-12 Fan Peltier Hot Side
|
||||||
// PD5: PWM NF-A8 Fan Peltier Cold Side
|
// PD5: PWM NF-A8 Fan Peltier Cold Side
|
||||||
// PD7: PWM NF-R8 Fan Heating Element
|
// PD7: PWM NF-R8 Fan Heating Element
|
||||||
|
|
||||||
// ATMega32A does not have more than two outputs for the
|
|
||||||
// 16-bit timer and the other 8-bit timers don't have modes
|
|
||||||
// where the value of TOP can be changed. We can only get
|
|
||||||
// 25 KHz with software PWM on this chip as far as I know.
|
|
||||||
|
|
||||||
// The 328P would allow us to use OCR2A as top but with
|
|
||||||
// 8-bit this gives us a really low duty step size of 2.5%.
|
|
||||||
// Ideal would be two 16-bit timers with two outputs each.
|
|
||||||
|
|
||||||
DDRD |= BIT(PD4) | BIT(PD5) | BIT(PD7);
|
DDRD |= BIT(PD4) | BIT(PD5) | BIT(PD7);
|
||||||
// PORTD &= ~BIT(PD7); // Turn off PD7
|
|
||||||
|
|
||||||
// TCCR1A Timer1 Control Register A
|
// TCCR1A Timer1 Control Register A
|
||||||
// 7 6 5 4 3 2 1 0
|
// 7 6 5 4 3 2 1 0
|
||||||
@@ -67,7 +59,6 @@ int PWM_Init(void)
|
|||||||
// Register, these bits control the counting sequence of
|
// Register, these bits control the counting sequence of
|
||||||
// the counter, the source for maximum (TOP) counter
|
// the counter, the source for maximum (TOP) counter
|
||||||
// value, and what type of waveform generation to be used.
|
// value, and what type of waveform generation to be used.
|
||||||
// See page 115 of the ATMega32A data sheet for all modes.
|
|
||||||
|
|
||||||
// Mode WGM13 WGM12 WGM11 WGM10 Timer Mode TOP
|
// Mode WGM13 WGM12 WGM11 WGM10 Timer Mode TOP
|
||||||
// 14 1 1 1 0 Fast PWM ICR1
|
// 14 1 1 1 0 Fast PWM ICR1
|
||||||
@@ -89,14 +80,16 @@ int PWM_Init(void)
|
|||||||
TCCR1A = BIT(WGM11) | BIT(COM1A1) | BIT(COM1B1);
|
TCCR1A = BIT(WGM11) | BIT(COM1A1) | BIT(COM1B1);
|
||||||
TCCR1B = BIT(WGM12) | BIT(WGM13) | BIT(CS10);
|
TCCR1B = BIT(WGM12) | BIT(WGM13) | BIT(CS10);
|
||||||
ICR1 = PWM_CYCLE_TOP; // 8000 MHz / 25000 KHz
|
ICR1 = PWM_CYCLE_TOP; // 8000 MHz / 25000 KHz
|
||||||
|
|
||||||
|
// TIMER3: Fast mode, non-inverting, top=ICR3, prescale /1
|
||||||
|
|
||||||
|
TCCR3A = BIT(WGM31) | BIT(COM3A1) | BIT(COM3B1);
|
||||||
|
TCCR3B = BIT(WGM32) | BIT(WGM33) | BIT(CS30);
|
||||||
|
ICR3 = PWM_CYCLE_TOP; // 8000 MHz / 25000 KHz
|
||||||
|
|
||||||
OCR1B = FAN01_MIN_DUTY; // PD4
|
OCR1B = FAN01_MIN_DUTY; // PD4
|
||||||
OCR1A = FAN02_MIN_DUTY; // PD5
|
OCR1A = FAN02_MIN_DUTY; // PD5
|
||||||
|
OCR2A = FAN03_MIN_DUTY; // PD7
|
||||||
// TIMER2: Fast mode, non-inverting, top=0xFF, prescale /1
|
|
||||||
|
|
||||||
TCCR2 = BIT(WGM20) | BIT(WGM21) | BIT(COM21) | BIT(CS20);
|
|
||||||
OCR2 = FAN03_MIN_DUTY;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -104,24 +97,23 @@ int PWM_Init(void)
|
|||||||
// Value in range 0-100 is expected
|
// Value in range 0-100 is expected
|
||||||
void PWM_SetValue(int port, int value)
|
void PWM_SetValue(int port, int value)
|
||||||
{
|
{
|
||||||
int n, m;
|
int n;
|
||||||
|
|
||||||
if (port != FAN01 && port != FAN02 && port != FAN03)
|
if (port != FAN01 && port != FAN02 && port != FAN03)
|
||||||
return; // Invalid port
|
return; // Invalid port
|
||||||
|
|
||||||
// Workaround: Missing third 16-bit timer output
|
// Workaround: Missing third 16-bit timer output
|
||||||
m = (port != FAN03) ? PWM_CYCLE_TOP : 0xFF;
|
n = CLAMP(value, 100, 0) * PWM_CYCLE_TOP / 100.0f;
|
||||||
n = CLAMP(value, 100, 0) * m / 100.0f;
|
|
||||||
|
|
||||||
Info("Setting duty cycle for %s to %d/%d...",
|
Info("Setting duty cycle for %s to %d/%d...",
|
||||||
(port == FAN01) ? "FAN01" :
|
(port == FAN01) ? "FAN01" :
|
||||||
(port == FAN02) ? "FAN02" :
|
(port == FAN02) ? "FAN02" :
|
||||||
(port == FAN03) ? "FAN03" :
|
(port == FAN03) ? "FAN03" :
|
||||||
"UNKNOWN", n, m);
|
"UNKNOWN", n, PWM_CYCLE_TOP);
|
||||||
|
|
||||||
switch (port) {
|
switch (port) {
|
||||||
case PD4: OCR1B = n; break;
|
case PD4: OCR1B = n; break;
|
||||||
case PD5: OCR1A = n; break;
|
case PD5: OCR1A = n; break;
|
||||||
case PD7: OCR2 = n; break;
|
case PD7: OCR2A = n; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,11 @@ int USART_Init(void)
|
|||||||
txhead = 0;
|
txhead = 0;
|
||||||
txtail = 0;
|
txtail = 0;
|
||||||
|
|
||||||
UCSRB = BIT(RXCIE); // Handle RXC interrupts
|
UCSR0B = BIT(RXCIE0); // Handle RXC interrupts
|
||||||
UCSRB |= BIT(RXEN) | BIT(TXEN); // Enable RX and TX circuitry
|
UCSR0B |= BIT(RXEN0) | BIT(TXEN0); // Enable RX and TX circuitry
|
||||||
UCSRC = BIT(URSEL) | BIT(UCSZ0) | BIT(UCSZ1); // Using 8-bit chars
|
UCSR0C = BIT(UCSZ01) | BIT(UCSZ00); // 8-bit data, 1-bit stop, no parity
|
||||||
UBRRH = (USART_BAUD_PRESCALE >> 8); // Set baud rate upper byte
|
UBRR0H = (USART_BAUD_PRESCALE >> 8); // Set baud rate upper byte
|
||||||
UBRRL = USART_BAUD_PRESCALE; // Set baud rate lower byte
|
UBRR0L = USART_BAUD_PRESCALE; // Set baud rate lower byte
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -57,16 +57,16 @@ void USART_Putc(char ch)
|
|||||||
txhead = head;
|
txhead = head;
|
||||||
|
|
||||||
// Enable interrupt
|
// Enable interrupt
|
||||||
UCSRB |= BIT(UDRIE);
|
UCSR0B |= BIT(UDRIE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// INT: Rx complete
|
// INT: Rx complete
|
||||||
ISR(USART_RXC_vect)
|
ISR(USART0_RX_vect)
|
||||||
{
|
{
|
||||||
short head;
|
short head;
|
||||||
byte data;
|
byte data;
|
||||||
|
|
||||||
data = UDR; // Next byte ready
|
data = UDR0; // Next byte ready
|
||||||
|
|
||||||
// Wrap around if end of buffer reached
|
// Wrap around if end of buffer reached
|
||||||
head = (rxhead + 1) & USART_RXBUF_MASK;
|
head = (rxhead + 1) & USART_RXBUF_MASK;
|
||||||
@@ -80,7 +80,7 @@ ISR(USART_RXC_vect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// INT: Data register empty
|
// INT: Data register empty
|
||||||
ISR(USART_UDRE_vect)
|
ISR(USART0_UDRE_vect)
|
||||||
{
|
{
|
||||||
short tail;
|
short tail;
|
||||||
|
|
||||||
@@ -88,10 +88,10 @@ ISR(USART_UDRE_vect)
|
|||||||
if (txhead != txtail) {
|
if (txhead != txtail) {
|
||||||
// Write next byte to data register
|
// Write next byte to data register
|
||||||
tail = (txtail + 1) & USART_TXBUF_MASK;
|
tail = (txtail + 1) & USART_TXBUF_MASK;
|
||||||
UDR = txbuf[tail];
|
UDR0 = txbuf[tail];
|
||||||
txtail = tail;
|
txtail = tail;
|
||||||
} else {
|
} else {
|
||||||
// Disable interrupt
|
// Disable interrupt
|
||||||
UCSRB &= ~BIT(UDRIE);
|
UCSR0B &= ~BIT(UDRIE0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#define MEM_SIZE 1024
|
#define MEM_SIZE 4096
|
||||||
#define MEM_START 0x00
|
#define MEM_START 0x00
|
||||||
#define MEM_BLOCK_SIZE ((int) sizeof(mem_block_t))
|
#define MEM_BLOCK_SIZE ((int) sizeof(mem_block_t))
|
||||||
#define MEM_MAX_BLOCKS (MEM_SIZE / MEM_BLOCK_SIZE)
|
#define MEM_MAX_BLOCKS (MEM_SIZE / MEM_BLOCK_SIZE)
|
||||||
@@ -189,14 +189,14 @@ static void ReadBlock(int n, mem_block_t *out)
|
|||||||
|
|
||||||
static void WriteRaw(int addr, byte data)
|
static void WriteRaw(int addr, byte data)
|
||||||
{
|
{
|
||||||
// The EEMWE bit determines whether setting EEWE to
|
// The EEMPE bit determines whether setting EEPE to
|
||||||
// one causes the EEPROM to be written. When EEMWE
|
// one causes the EEPROM to be written. When EEMPE
|
||||||
// is set, setting EEWE within four clock cycles
|
// is set, setting EEPE within four clock cycles
|
||||||
// will write data to the EEPROM at the selected
|
// will write data to the EEPROM at the selected
|
||||||
// address.
|
// address.
|
||||||
|
|
||||||
// If EEMWE is zero, setting EEWE will have no
|
// If EEMPE is zero, setting EEPE will have no
|
||||||
// effect. When EEMWE has been written to one by
|
// effect. When EEMPE has been written to one by
|
||||||
// software, hardware clears the bit to zero after
|
// software, hardware clears the bit to zero after
|
||||||
// four clock cycles.
|
// four clock cycles.
|
||||||
|
|
||||||
@@ -206,33 +206,40 @@ static void WriteRaw(int addr, byte data)
|
|||||||
|
|
||||||
// If an interrupt routine accessing the EEPROM is
|
// If an interrupt routine accessing the EEPROM is
|
||||||
// interrupting another EEPROM Access, the EEAR or
|
// interrupting another EEPROM Access, the EEAR or
|
||||||
// EEDR reGister will be modified, causing the
|
// EEDR register will be modified, causing the
|
||||||
// interrupted EEPROM Access to fail.
|
// interrupted EEPROM Access to fail.
|
||||||
|
|
||||||
// It is recommended to have the Global Interrupt
|
// It is recommended to have the Global Interrupt
|
||||||
// Flag cleared during all the steps to avoid these
|
// Flag cleared during all the steps to avoid these
|
||||||
// problems.
|
// problems.
|
||||||
|
|
||||||
|
// When the write access time has elapsed, the EEPE
|
||||||
|
// bit is cleared by hardware. The user software can
|
||||||
|
// poll this bit and wait for a zero before writing
|
||||||
|
// the next byte. When EEPE has been set, the CPU is
|
||||||
|
// halted for two cycles before the next instruction
|
||||||
|
// is executed.
|
||||||
|
|
||||||
// No interrupts during EEPROM write
|
// No interrupts during EEPROM write
|
||||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
|
||||||
// Wait until ready
|
// Wait until ready
|
||||||
while (EECR & BIT(EEWE));
|
while (EECR & BIT(EEPE));
|
||||||
|
|
||||||
// The EEPROM Address Registers – EEARH and
|
// The EEPROM Address Registers – EEARH and
|
||||||
// EEARL – specify the EEPROM address in the
|
// EEARL specify the EEPROM address in the
|
||||||
// 1024bytes EEPROM space. The EEPROM data
|
// 512/1K/2K/4Kbytes EEPROM space. The EEPROM
|
||||||
// bytes are addressed linearly between 0
|
// data bytes are addressed linearly between 0
|
||||||
// and 1023. The initial value of EEAR is
|
// and 511/1023/2047/4096. The initial value
|
||||||
// undefined. A proper value must be written
|
// of EEAR is undefined. A proper value must be
|
||||||
// before the EEPROM may be accessed.
|
// written before the EEPROM may be accessed.
|
||||||
|
|
||||||
EEAR = addr;
|
EEAR = addr;
|
||||||
EEDR = data;
|
EEDR = data;
|
||||||
|
|
||||||
// Write to address
|
// Write to address
|
||||||
EECR |= BIT(EEMWE);
|
EECR |= BIT(EEMPE);
|
||||||
EECR |= BIT(EEWE);
|
EECR |= BIT(EEPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +263,7 @@ static byte ReadRaw(int addr)
|
|||||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
|
||||||
// Wait until ready
|
// Wait until ready
|
||||||
while (EECR & BIT(EEWE));
|
while (EECR & BIT(EEPE));
|
||||||
|
|
||||||
EEAR = addr;
|
EEAR = addr;
|
||||||
|
|
||||||
|
|||||||
@@ -6,53 +6,79 @@ void WDT_Enable(void)
|
|||||||
{
|
{
|
||||||
Info("Enabling watchdog timer...");
|
Info("Enabling watchdog timer...");
|
||||||
|
|
||||||
// WDTCR: Watchdog Timer Control Register
|
// WDTCSR: Watchdog Timer Control Register
|
||||||
|
|
||||||
// 7 6 5 4 3 2 1 0
|
// 7 6 5 4 3 2 1 0
|
||||||
// – – - WDTOE WDE WDP2 WDP1 WDP0
|
// WDIF WDIE WDP3 WDCE WDE WDP2 WDP1 WDP0
|
||||||
|
|
||||||
// When the WDE is written to logic one, the
|
// WDP3:0: Watchdog Timer Prescaler
|
||||||
// Watchdog Timer is enabled, and if the WDE is
|
// The WDP3:0 bits determine the Watchdog Timer
|
||||||
// written to logic zero, the Watchdog Timer
|
// prescaling when the Watchdog Timer is running.
|
||||||
// function is disabled.
|
// The different prescaling values and their
|
||||||
|
// corresponding time-out periods are
|
||||||
|
|
||||||
// WDP2, WDP1, WDP0: Watchdog Timer Prescaler
|
// WDP3 WDP2 WDP1 WDP0 Cycles Timeout5V
|
||||||
// The WDP2, WDP1, and WDP0 bits determine the
|
// 0 0 0 0 2K 16ms
|
||||||
// Watchdog Timer prescaling when the Watchdog
|
// 0 0 0 1 4K 32ms
|
||||||
// Timer is enabled. The different prescaling
|
// 0 0 1 0 8K 64ms
|
||||||
// values and their corresponding Timeout
|
// 0 0 1 1 16K 125ms
|
||||||
// Periods are:
|
// 0 1 0 0 32K 250ms
|
||||||
|
// 0 1 0 1 64K 500ms
|
||||||
|
// 0 1 1 0 128K 1000ms
|
||||||
|
// 0 1 1 1 256K 2000ms
|
||||||
|
// 1 0 0 0 512K 4000ms
|
||||||
|
// 1 0 0 1 1024K 8000ms
|
||||||
|
|
||||||
// WDP2 WDP1 WDP0 Cycles Timeout3V Timeout5V
|
// WDCE: Watchdog Change Enable
|
||||||
// 0 0 0 16K 17.10ms 16.30ms
|
// This bit is used in timed sequences for changing
|
||||||
// 0 0 1 32K 34.30ms 32.50ms
|
// WDE and prescaler bits. To clear the WDE bit,
|
||||||
// 0 1 0 64K 68.50ms 65.00ms
|
// and/or change the prescaler bits, WDCE must be
|
||||||
// 0 1 1 128K 0.14s 0.13s
|
// set. Once written to one, hardware will clear
|
||||||
// 1 0 0 256K 0.27s 0.26s
|
// WDCE after four clock cycles.
|
||||||
// 1 0 1 512K 0.55s 0.52s
|
|
||||||
// 1 1 0 1,024K 1.10s 1.00s
|
|
||||||
// 1 1 1 2,048K 2.20s 2.10s
|
|
||||||
|
|
||||||
// WDTOE: Watchdog Turn-off Enable This bit must
|
// Setting WDCE before enabling the watchdog should
|
||||||
// be set when the WDE bit is written to logic zero.
|
// not be necessary according to the data sheet but
|
||||||
// Otherwise, the Watchdog will not be disabled.
|
// it does not seem to work otherwise.
|
||||||
// Once written to one, hardware will clear this
|
|
||||||
// bit after four clock cycles.
|
|
||||||
|
|
||||||
// 00001111: Watchdog enabled, 2sec timeout
|
// Disable interrupts
|
||||||
WDTCR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0);
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
MCUSR &= ~BIT(WDRF);
|
||||||
|
WDTCSR = BIT(WDCE) | BIT(WDE);
|
||||||
|
// 00001111: Watchdog enabled, 2sec timeout
|
||||||
|
WDTCSR = BIT(WDE) | BIT(WDP2) | BIT(WDP1) | BIT(WDP0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WDT_SetTimeoutFlag(byte flag)
|
void WDT_SetTimeoutFlag(byte flag)
|
||||||
{
|
{
|
||||||
|
// Currently only support for a maximum of 2 seconds
|
||||||
|
// timeout because there is no need for more and the
|
||||||
|
// bit location of WDP3 requires conditional logic.
|
||||||
|
|
||||||
|
// The sequence for clearing WDE and changing timeout
|
||||||
|
// configuration is as follows:
|
||||||
|
|
||||||
|
// 1. In the same operation, write a logic one to the
|
||||||
|
// Watchdog change enable bit (WDCE) and WDE. A logic
|
||||||
|
// one must be written to WDE regardless of the
|
||||||
|
// previous value of the WDE bit.
|
||||||
|
|
||||||
|
// 2. Within the next four clock cycles, write the WDE
|
||||||
|
// and Watchdog prescaler bits (WDP) as desired, but
|
||||||
|
// with the WDCE bit cleared. This must be done in one
|
||||||
|
// operation.
|
||||||
|
|
||||||
flag = CLAMP(flag, 7, 0);
|
flag = CLAMP(flag, 7, 0);
|
||||||
|
|
||||||
Info("Setting watchdog prescalar to %02X...", flag);
|
Info("Setting watchdog prescalar to %02X...", flag);
|
||||||
|
|
||||||
// Clear timer prescalar flags
|
// Disable interrupts
|
||||||
WDTCR &= 0xF8; // 11111000
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
WDT_Reset();
|
||||||
WDTCR |= flag;
|
WDTCSR = BIT(WDCE) | BIT(WDE);
|
||||||
|
// Set new timer prescalar flag
|
||||||
|
WDTCSR = BIT(WDE) | flag;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WDT_HasTriggered(void)
|
bool WDT_HasTriggered(void)
|
||||||
@@ -61,48 +87,40 @@ bool WDT_HasTriggered(void)
|
|||||||
|
|
||||||
// To make use of the Reset Flags to identify a reset
|
// To make use of the Reset Flags to identify a reset
|
||||||
// condition, the user should read and then reset the
|
// condition, the user should read and then reset the
|
||||||
// MCUCSR as early as possible in the program. If the
|
// MCUSR as early as possible in the program. If the
|
||||||
// register is cleared before another reset occurs,
|
// register is cleared before another reset occurs,
|
||||||
// the source of the reset can be found by examining
|
// the source of the reset can be found by examining
|
||||||
// the Reset Flags.
|
// the Reset Flags.
|
||||||
|
|
||||||
// MCUCSR: MCU Control and Status Register
|
// MCUSR: MCU Status Register
|
||||||
// The MCU Control and Status Register provides
|
// The MCU Status Register provides information on
|
||||||
// information on which reset source caused an MCU
|
// which reset source caused an MCU reset.
|
||||||
// Reset.
|
|
||||||
|
|
||||||
// 7 6 5 4 3 2 1 0
|
// 7 6 5 4 3 2 1 0
|
||||||
// JTD ISC2 – JTRF WDRF BORF EXTRF PORF
|
// - - – JTRF WDRF BORF EXTRF PORF
|
||||||
|
|
||||||
// Is watchdog reset flag set?
|
// Is watchdog reset flag set?
|
||||||
isreset = ((MCUCSR & BIT(WDRF)) != 0);
|
isreset = ((MCUSR & BIT(WDRF)) != 0);
|
||||||
|
|
||||||
// XXX: Reset flag detection should be a separate
|
// XXX: Reset flag detection should be a separate
|
||||||
// module to handle the different types.
|
// module to handle the different types.
|
||||||
|
|
||||||
MCUCSR = 0;
|
MCUSR = 0;
|
||||||
|
|
||||||
return isreset;
|
return isreset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WDT_Disable(void)
|
void WDT_Disable(void)
|
||||||
{
|
{
|
||||||
// WDE can only be cleared if the WDTOE bit has
|
// See WDT_SetTimeoutFlag for an explanation of the
|
||||||
// logic level one. To disable an enabled watchdog
|
// necessary sequence for clearing WDE and changing
|
||||||
// timer, the following procedure must be followed:
|
// timeout configuration.
|
||||||
|
|
||||||
// 1. In the same operation, write a logic one to
|
// Disable interrupts
|
||||||
// WDTOE and WDE. A logic one must be written to WDE
|
|
||||||
// even though it is set to one before the disable
|
|
||||||
// operation starts.
|
|
||||||
|
|
||||||
// 2. Within the next four clock cycles, write a
|
|
||||||
// logic 0 to WDE. This disables the watchdog.
|
|
||||||
|
|
||||||
// No interrupts while we set WDTCR;
|
|
||||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
WDTCR = BIT(WDTOE) | BIT(WDE);
|
WDT_Reset();
|
||||||
WDTCR = 0;
|
WDTCSR = BIT(WDCE) | BIT(WDE);
|
||||||
|
WDTCSR = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#define WDT1000 0x6 // 1000 ms
|
#define WDT1000 0x6 // 1000 ms
|
||||||
#define WDT500 0x5 // 500 ms
|
#define WDT500 0x5 // 500 ms
|
||||||
#define WDT250 0x4 // 250 ms
|
#define WDT250 0x4 // 250 ms
|
||||||
#define WDT100 0x3 // 100 ms
|
#define WDT125 0x3 // 125 ms
|
||||||
#define WDT64 0x2 // 64 ms
|
#define WDT64 0x2 // 64 ms
|
||||||
#define WDT32 0x1 // 32 ms
|
#define WDT32 0x1 // 32 ms
|
||||||
#define WDT16 0x0 // 16 ms
|
#define WDT16 0x0 // 16 ms
|
||||||
|
|||||||
11
src/main.c
11
src/main.c
@@ -12,7 +12,6 @@
|
|||||||
// TODO: Config header for chip specifics like EEPROM size.
|
// TODO: Config header for chip specifics like EEPROM size.
|
||||||
// TODO: Check thermistor conversion results /w thermometer.
|
// TODO: Check thermistor conversion results /w thermometer.
|
||||||
// TODO: Implement primary state machine for update loop.
|
// TODO: Implement primary state machine for update loop.
|
||||||
// TODO: Migrate to ATMega 1284P-PU for 2nd 16-bit timer.
|
|
||||||
// TODO: Use 18.432MHz quarz crystal, burn required fuses.
|
// TODO: Use 18.432MHz quarz crystal, burn required fuses.
|
||||||
// TODO: Implement optional CRC8 sensor measurement check.
|
// TODO: Implement optional CRC8 sensor measurement check.
|
||||||
// TODO: Proper error handling and recovery (after testing).
|
// TODO: Proper error handling and recovery (after testing).
|
||||||
@@ -108,16 +107,6 @@ static int Init(void)
|
|||||||
// MOS_Enable(MOS01); // Peltier
|
// MOS_Enable(MOS01); // Peltier
|
||||||
// MOS_Disable(MOS02); // Heating
|
// MOS_Disable(MOS02); // Heating
|
||||||
|
|
||||||
// Only FAN01 and FAN02 are receiving the correct
|
|
||||||
// frequency (25 KHz) right now. The 16-bit timer on
|
|
||||||
// the ATMega32A has two outputs so it would require
|
|
||||||
// software PWM to have a variable frequency on PD7.
|
|
||||||
|
|
||||||
// A simple implementation will take up around 30-50
|
|
||||||
// percent of CPU time. Faster approaches are quite
|
|
||||||
// complicated so it might be worth it to switch to
|
|
||||||
// something like an ATmega328PB.
|
|
||||||
|
|
||||||
PWM_SetValue(FAN01, 50); // Fan Peltier Hot side
|
PWM_SetValue(FAN01, 50); // Fan Peltier Hot side
|
||||||
PWM_SetValue(FAN02, 50); // Fan Peltier Cold Side
|
PWM_SetValue(FAN02, 50); // Fan Peltier Cold Side
|
||||||
PWM_SetValue(FAN03, 50); // Fan Heating
|
PWM_SetValue(FAN03, 50); // Fan Heating
|
||||||
|
|||||||
Reference in New Issue
Block a user