Skip to content

Instantly share code, notes, and snippets.

@raphaelschaad
Last active November 25, 2015 18:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raphaelschaad/39b1aee15d8aab48e73a to your computer and use it in GitHub Desktop.
Save raphaelschaad/39b1aee15d8aab48e73a to your computer and use it in GitHub Desktop.
//
// att44_schaad1.c
//
// Created by Raphael Schaad on 2015-11-03.
// This is free and unencumbered software released into the public domain.
//
// Import headers installed with CrossPack-AVR (/usr/local/CrossPack-AVR/)
#include "stdbool.h" // So we have 'true' and 'false' instead of 1 and 0 (might have memory implications) -- lib/gcc/avr/4.8.1/include/
#include <avr/io.h> // Umbrella header including e.g. iotn44a.h for our chip, defining PORTx/DDRx/Pxn etc. (mapping to addresses from data sheet) -- avr/include/avr/
#include <util/delay.h> // _delay_us/ms convenience functions for actual time values rather than number of cycles -- avr/include/util
// Hardware:
// Based on Neil Gershenfeld's board: http://academy.cba.mit.edu/classes/embedded_programming/index.html#echo
// With my redesign and enhancements: http://fab.cba.mit.edu/classes/863.15/section.CBA/people/Schaad/week6-electronics-design.html
#define LED1 (1 << PB2) // red (pin 5)
#define LED2 (1 << PA2) // green (pin 11)
#define LED3 (1 << PA3) // green (pin 10)
#define BTN1 (1 << PA7) // (pin 6)
// Convenience macros
#define output(directions, pin) (directions |= pin) // set port direction for output
#define input(directions, pin) (directions &= (~pin)) // set port direction for input
#define set(port, pin) (port |= pin) // set port pin
#define clear(port, pin) (port &= (~pin)) // clear port pin
#define pin_test(pins, pin) (pins & pin) // test for port pin
#define bit_test(byte, bit) (byte & (1 << bit)) // test for bit set
// Copied configuration defines -- but I find this abstraction more confusing
// #define input_port PORTA // BTN1 is on port A
// #define input_direction DDRA // DDRA defines input/output for port A
// #define input_pin (1 << PA7) // BTN1 is on pin 7 of port A
// #define input_pins PINA // PINA is the register that is read to detect input high or low.
// #define output_port PORTB // Port B will be used for the LED
// #define output_direction DDRB // DDRB defines input/output for port B
// #define output_pin (1 << PB2) // LED1 is on pin 2 of port B
// Bootloader calls main(void) when the chip gets power
int main() {
// Set clock divider to 1 (default is 8, from CKDIV8 LFuse).
// The internal clock of t44/45 is max 8MHz but on this board we configure LFuse to use an external 20MHz resonator.
// This needs to be reflected in the Makefile with F_CPU = 20000000.
CLKPR = (1 << CLKPCE);
CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0);
// Configure digital I/O pins DDRA & DDRB (bits are 0-based index)
output(DDRB, LED1); // PB2 as output by setting bit 2 in register DDRB (= 0b00000100)
output(DDRA, LED2);
output(DDRA, LED3);
input(DDRA, BTN1); // PB7 as input by setting bit 7 in register DDRA (= 0b10000000) ...
set(PORTA, BTN1); // ... and on PORTA (= 0b10000000; turns on pullup resistor)
// Turn LED1 ON by default
set(PORTB, LED1); // PORTB = 0b00000100;
// Spin event loop
while (true) {
// Blink LED2/3 on button press
if (pin_test(PINA, BTN1)) { // (PINA & 0b10000000) == 1
set(PORTB, LED1);
clear(PORTA, LED2);
clear(PORTA, LED3);
} else {
clear(PORTB, LED1);
if (pin_test(PINA, LED2)) {
set(PORTA, LED3);
clear(PORTA, LED2);
} else {
set(PORTA, LED2);
clear(PORTA, LED3);
}
_delay_ms(1000.0);
}
}
// When main(void) exits, the chip goes idle
return 0;
}
#
# att44_schaad1.make
#
# Created by Raphael Schaad on 2015-11-03.
# This is free and unencumbered software released into the public domain.
#
PROJECT=att44_schaad1
SOURCES=$(PROJECT).c
MMCU=attiny44
F_CPU = 20000000
CFLAGS=-mmcu=$(MMCU) -Wall -Os -DF_CPU=$(F_CPU)
$(PROJECT).hex: $(PROJECT).out
avr-objcopy -O ihex $(PROJECT).out $(PROJECT).c.hex;\
avr-size --mcu=$(MMCU) --format=avr $(PROJECT).out
$(PROJECT).out: $(SOURCES)
avr-gcc $(CFLAGS) -I./ -o $(PROJECT).out $(SOURCES)
program-usbtiny: $(PROJECT).hex
avrdude -p t44 -P usb -c usbtiny -U flash:w:$(PROJECT).c.hex
program-usbtiny-fuses: $(PROJECT).hex
avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x5E:m
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment