Created
August 16, 2020 15:04
The changes needed to rewrite Birch Books to ATmega
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 8051/birch-books.c 2020-08-16 16:01:28.250218679 +0100 | |
+++ atmega48/birch-books.c 2020-08-16 15:27:32.893862293 +0100 | |
@@ -1,38 +1,25 @@ | |
// SPDX-FileCopyrightText: © 2020 The birch-books-smarthome Authors | |
// SPDX-License-Identifier: MIT | |
-// | |
-// Based on CC-0 licensed demo at | |
-// http://www.colecovision.eu/mcs51/STC89%20DEMO%20BOARD%20LED.shtml | |
+ | |
+#define F_CPU 1000000 | |
#include <stdbool.h> | |
-#include <stdint.h> | |
-#include <at89x52.h> | |
+#include <avr/interrupt.h> | |
+#include <avr/io.h> | |
+#include <util/delay.h> | |
#include "schedule.h" | |
-/* We can't use C constants for all of this because SDCC is not able to tell | |
- * that they are static constants, and sets them in RAM instead. | |
- */ | |
- | |
volatile uint16_t ticktime = 0; | |
volatile bool fastclock = false; | |
-volatile bool rsttestmode = false; | |
volatile bool testmode = false; | |
-#define CFG_P0OUT 0xFF | |
-// Only 6 bits are configured for output on P2, the other two are inputs. | |
-#define CFG_P2OUT 0x3F | |
- | |
-/* Use a very naive approach for the pressed states — sdcc miscompiles complex | |
- * boolean operations */ | |
-#define TEST_PRESSED P2_7 | |
-#define FF_PRESSED P2_6 | |
- | |
-void clockinc(void) __interrupt(5) { | |
- /* Debounce the Firing flag. */ | |
- TF2 = 0; | |
+#define TEST_PRESSED (PINB & (1 << PINB1)) | |
+#define FF_PRESSED (PINB & (1 << PINB0)) | |
+ | |
+ISR(TIMER1_COMPA_vect) { | |
/* If the main loop set the fastclock flag, increase the tick count by 64. | |
* | |
@@ -40,24 +27,12 @@ | |
* passed. This "fast forward" should complete the schedule within a minute | |
* rather than an hour. | |
*/ | |
- uint8_t tickvalue = 1; | |
- if (fastclock) { | |
- tickvalue = 64; | |
- } | |
+ uint8_t tickvalue = fastclock ? 64 : 1; | |
/* We let the ticktime overflow transparently, from 65535 back to 0. | |
* This simplifies our code quite a bit as we don't need to divide anything. | |
*/ | |
ticktime += tickvalue; | |
- | |
- /* Use the P1 port for debugging, by setting up the output flags based on some | |
- * of the firmware's internal flags. | |
- */ | |
- P1_0 = (bool)fastclock; | |
- P1_1 = (bool)FF_PRESSED; | |
- P1_2 = (bool)TEST_PRESSED; | |
- P1_3 = (bool)rsttestmode; | |
- P1_4 = (bool)testmode; | |
} | |
/* Return the internal timer in ticks (1/16th of a second). | |
@@ -66,59 +41,47 @@ | |
* while interrupts are disabled, to avoid it changing during access. | |
*/ | |
static uint16_t ticks() { | |
- EA = 0; | |
+ cli(); | |
uint16_t ctmp = ticktime; | |
- EA = 1; | |
+ sei(); | |
return ctmp; | |
} | |
-void main(void) { | |
- /* Set Timer 2 for auto-reload every 62.5ms. | |
- * | |
- * Timer 2 is the only timer with 16-bit auto-reload, making it much easier to | |
- * set up the timer, as we don't need to manually re-set it. | |
- * | |
- * The way you set the T2 timer in 8051-compatible is that you need to set the | |
- * counter to (65536 - usec), assuming the default behaviour of the timer | |
- * running at 1MHz (sys_clock/12). | |
- * | |
- * The chosen constant (0x0BDB) should execute the timer every 62.5msec, which | |
- * means it tickets at 1/16th of a second. This allows for a cleaner | |
- * conversion between ticks and seconds by dividing by 16. | |
- * | |
- * You need to set both TH2,TL2 (the current timer) and RCAP2H,RCAP2L (the | |
- * auto-reset values), to make sure that the timer runs smoothly. | |
- * | |
- * Then you need to clear TF2 ("Firing"), both here and in the interrupt | |
- * routine, and set ET2 ("Enable"), TR2 ("Run"), and EA ("Interrupt Enable"). | |
- */ | |
- TH2 = 0x0B; | |
- TL2 = 0xDB; | |
- RCAP2H = 0x0B; | |
- RCAP2L = 0xDB; | |
- | |
- TF2 = 0; | |
- ET2 = 1; | |
- TR2 = 1; | |
- EA = 1; | |
- | |
- /* Set the basic output ports to zero, to make sure everything starts off. | |
- */ | |
- P0 = 0x00; | |
- P1 = 0x00; | |
- P2 = 0x00; | |
+int main() { | |
+ /* Set ports C (0~5) and D (0~7) for output. */ | |
+ DDRC |= ((1 << DDC0) | (1 << DDC1) | (1 << DDC2) | (1 << DDC3) | (1 << DDC4) | | |
+ (1 << DDC5)); | |
+ DDRD |= ((1 << DDD0) | (1 << DDD1) | (1 << DDD2) | (1 << DDD3) | (1 << DDD4) | | |
+ (1 << DDD5) | (1 << DDD6) | (1 << DDD7)); | |
+ | |
+ /* Run a LED self-test at start, for just a second. Do this before setting up | |
+ * timers, so that the timer starts counting from 0. */ | |
+ PORTC = 0xFF; | |
+ PORTD = 0xFF; | |
+ _delay_ms(1000); | |
+ | |
+ /* Set ports to zero. */ | |
+ PORTC = 0; | |
+ PORTD = 0; | |
+ | |
+ /* Set up Timer 1 for 62.5ms. */ | |
+ OCR1A = 62499; // 1/16th of a second at 1MHz clock. | |
+ TCCR1B |= ((1 << CS10) // Fcpu prescale = 1 | |
+ | (1 << WGM12) // CTC mode | |
+ ); | |
+ TIMSK1 |= (1 << OCIE1A); // Enable CTC Interrupt | |
+ sei(); // Enable global interrupts | |
/* If TEST is pressed at start, consider us in 'self-test mode': chase a | |
* single room through the output port. | |
*/ | |
while (TEST_PRESSED) { | |
- rsttestmode = true; | |
uint16_t clock_secs = ticks() >> 4; | |
uint8_t test_index = clock_secs % 10; | |
- P0 = test_schedule[test_index] & 0xFF; | |
- P2 = test_schedule[test_index] >> 8; | |
+ PORTC = test_schedule[test_index] & 0xFF; | |
+ PORTD = test_schedule[test_index] >> 8; | |
} | |
/* This is the main loop for the firmware. | |
@@ -146,8 +109,8 @@ | |
} | |
if (testmode) { | |
- P0 = CFG_P0OUT; | |
- P2 = CFG_P2OUT; | |
+ PORTC = 0xFF; | |
+ PORTD = 0xFF; | |
} else { | |
/* The schedule is a 16 "hours" schedule with the two ports setting | |
* separate environment. | |
@@ -162,8 +125,8 @@ | |
uint16_t clock_ticks = ticks(); | |
uint8_t virtual_hour = (clock_ticks >> 12) & 0x0F; | |
- P0 = schedule[virtual_hour] & 0xFF; | |
- P2 = schedule[virtual_hour] >> 8; | |
+ PORTC = schedule[virtual_hour] & 0xFF; | |
+ PORTD = schedule[virtual_hour] >> 8; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment