Skip to content
Snippets Groups Projects
Commit a5518ce0 authored by Giorgio Momigliano's avatar Giorgio Momigliano
Browse files

Game

parent 6374aaed
No related branches found
No related tags found
No related merge requests found
Makefile 0 → 100644
# Universal Makefile Version: 23.02.2016
#
# Appears to work under Linux, OSX, and Cygwin/Windows.
# Under OSX it should be named "Makefile".
#
# Requires GNU 'make' and 'find'.
# Target Architecture
BOARD := LaFortuna
MCU := at90usb1286
F_CPU := 8000000UL
# Tool Options
CFLAGS := -Os -mmcu=$(MCU) -DF_CPU=$(F_CPU)
# CFLAGS += -Wl,-u,vfprintf -lprintf_flt -lm # floating point support
CFLAGS += -fno-strict-aliasing # FATfs does not adhere to strict aliasing
CFLAGS += -Wno-main # main() will never return
CFLAGS += -Wall -Wextra -pedantic
CFLAGS += -Wstrict-overflow=5 -fstrict-overflow -Winline
CHKFLAGS :=
# CHKFLAGS += -fsyntax-only
BUILD_DIR := _build
# Ignoring hidden directories; sorting to drop duplicates:
CFILES := $(shell find . ! -path "*/\.*" -type f -name "*.c")
CPPFILES := $(shell find . ! -path "*/\.*" -type f -name "*.cpp")
CPATHS := $(sort $(dir $(CFILES)))
CPPATHS += $(sort $(dir $(CPPFILES)))
vpath %.c $(CPATHS)
vpath %.cpp $(CPPATHS)
HFILES := $(shell find . ! -path "*/\.*" -type f -name "*.h")
HPATHS := $(sort $(dir $(HFILES)))
vpath %.h $(HPATHS)
CFLAGS += $(addprefix -I ,$(HPATHS))
DEPENDENCIES := $(patsubst %.c,$(BUILD_DIR)/%.d,$(notdir $(CFILES)))
DEPENDENCIES += $(patsubst %.cpp,$(BUILD_DIR)/%.d,$(notdir $(CPPILES)))
OBJFILES := $(patsubst %.c,$(BUILD_DIR)/%.o,$(notdir $(CFILES)))
OBJFILES += $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(notdir $(CPPFILES)))
.PHONY: upld prom clean check-syntax ?
upld: $(BUILD_DIR)/main.hex
$(info )
$(info =========== ${BOARD} =============)
dfu-programmer $(MCU) erase
dfu-programmer $(MCU) flash $(BUILD_DIR)/main.hex
dfu-programmer $(MCU) launch --no-reset # requires dfu-programmer >= v0.7.0
prom: $(BUILD_DIR)/main.eep upld
$(info ======== EEPROM: ${BOARD} ========)
dfu-programmer $(MCU) flash-eeprom $(BUILD_DIR)/main.eep
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
@avr-gcc $(CFLAGS) -MMD -MP -c $< -o $@
$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
@avr-g++ $(CFLAGS) -MMD -MP -c $< -o $@
$(BUILD_DIR)/%.elf %.elf: $(OBJFILES)
@avr-gcc -mmcu=$(MCU) -o $@ $^
$(BUILD_DIR)/%.hex %.hex: $(BUILD_DIR)/%.elf
@avr-objcopy -R .eeprom -R .fuse -R .lock -R .signature -O ihex $< "$@"
$(BUILD_DIR)/%.eep %.eep: $(BUILD_DIR)/%.elf
@avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex $< "$@"
-include $(sort $(DEPENDENCIES))
$(BUILD_DIR):
@mkdir -p $(BUILD_DIR)
# Emacs flymake support
check-syntax:
@avr-gcc $(CFLAGS) $(CHKFLAGS) -o /dev/null -S $(CHK_SOURCES)
clean:
@$(RM) -rf $(BUILD_DIR)
?%:
@echo '$*=$($*)'
?:
$(info -------------------------------------------------)
$(info Usage:)
$(info Source files can be grouped into subdirectories.)
$(info To build an executable and attempt to upload it,)
$(info use just "make". If the executable requires EEPROM)
$(info initialization, use "make prom".)
$(info )
$(info make mymain.hex --> to build a hex-file for mymain.c)
$(info make mymain.eep --> for an EEPROM file for mymain.c)
$(info make mymain.elf --> for an elf-file for mymain.c)
$(info make ?CFILES --> show C source files to be used)
$(info make ?CPPFILES --> show C++ source files to be used)
$(info make ?HFILES --> show header files found)
$(info make ?HPATHS --> show header locations)
$(info make ?CFLAGS --> show compiler options)
$(info )
$(info See the Makefile for more variables that can be)
$(info displayed as above.)
$(info -------------------------------------------------)
@:
# The MIT License (MIT)
#
# Copyright (c) 2014-2015 Klaus-Peter Zauner
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
#===================================================================
//
// Created by platelminto on 2/11/20.
// Is one of the buttons pressed (only triggers once per press)
#include <avr/io.h>
#include "lib/rotary/rotary.h"
int up_pressed = 0;
int right_pressed = 0;
int down_pressed = 0;
int left_pressed = 0;
int is_up_pressed() {
if (!up_pressed && !((PINC >> SWN) & 1)) {
up_pressed = 1;
return 1;
} else if (!((PINC >> SWN) & 1)) {
return 0;
} else {
up_pressed = 0;
return 0;
}
}
int is_right_pressed() {
if (!right_pressed && !((PINC >> SWE) & 1)) {
right_pressed = 1;
return 1;
} else if (!((PINC >> SWE) & 1)) {
return 0;
} else {
right_pressed = 0;
return 0;
}
}
int is_down_pressed() {
if (!down_pressed && !((PINC >> SWS) & 1)) {
down_pressed = 1;
return 1;
} else if (!((PINC >> SWS) & 1)) {
return 0;
} else {
down_pressed = 0;
return 0;
}
}
int is_left_pressed() {
if (!left_pressed && !((PINC >> SWW) & 1)) {
left_pressed = 1;
return 1;
} else if (!((PINC >> SWW) & 1)) {
return 0;
} else {
left_pressed = 0;
return 0;
}
}
\ No newline at end of file
//
// Created by platelminto on 2/11/20.
//
#ifndef TESTING_BUTTONS_H
#define TESTING_BUTTONS_H
#endif //TESTING_BUTTONS_H
int is_up_pressed(void);
int is_right_pressed(void);
int is_down_pressed(void);
int is_left_pressed(void);
#!/bin/bash
#Arguments: flag and file
FLAG=$1
FILE=$2
FILE_HEAD=$(echo $FILE | cut -f1 -d".")
case $FLAG in
-hex)
echo "Compiling file '$FILE' and creating hex object:"
avr-gcc -mmcu=at90usb1286 -DF_CPU=8000000 -Wall -Os $FILE -o $FILE_HEAD.elf
avr-objcopy -O ihex $FILE_HEAD.elf $FILE_HEAD.hex
echo "DONE. Flash using flag -load"
;;
-load)
echo "Flashing hex program '$FILE' to board:"
dfu-programmer at90usb1286 erase
dfu-programmer at90usb1286 flash $FILE_HEAD.hex
dfu-programmer at90usb1286 reset
echo "DONE. Restart your LaFortuna board."
;;
-all)
echo "Compiling file '$FILE' and creating hex object:"
avr-gcc -mmcu=at90usb1286 -DF_CPU=8000000 -Wall -Os $FILE -o $FILE_HEAD.elf
avr-objcopy -O ihex $FILE_HEAD.elf $FILE_HEAD.hex
echo "Flashing hex program '$FILE_HEAD' to board:"
dfu-programmer at90usb1286 erase
dfu-programmer at90usb1286 flash $FILE_HEAD.hex
dfu-programmer at90usb1286 reset
echo "Delete temporary files"
rm $FILE_HEAD.elf
rm $FILE_HEAD.hex
echo "DONE. Power cycle your LaFortuna board."
;;
-info)
echo "------Compile & Flash script for LaFortuna------"
echo "--Adapted from ak6g12's script by ec6g13 2015--"
esac
# Libraries for the La Fortuna #
* `lcd`: LCD display library - Steve Gunn
* `led`: LED utility library - Steve Gunn
* `rotary`: Rotary encoder utility library - Steve Gunn
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*/
#include <avr/pgmspace.h>
const char font5x7[] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, // SPACE
0x00, 0x00, 0x5F, 0x00, 0x00, // !
0x00, 0x03, 0x00, 0x03, 0x00, // "
0x14, 0x3E, 0x14, 0x3E, 0x14, // #
0x24, 0x2A, 0x7F, 0x2A, 0x12, // $
0x43, 0x33, 0x08, 0x66, 0x61, // %
0x36, 0x49, 0x55, 0x22, 0x50, // &
0x00, 0x05, 0x03, 0x00, 0x00, // '
0x00, 0x1C, 0x22, 0x41, 0x00, // (
0x00, 0x41, 0x22, 0x1C, 0x00, // )
0x14, 0x08, 0x3E, 0x08, 0x14, // *
0x08, 0x08, 0x3E, 0x08, 0x08, // +
0x00, 0x50, 0x30, 0x00, 0x00, // ,
0x08, 0x08, 0x08, 0x08, 0x08, // -
0x00, 0x60, 0x60, 0x00, 0x00, // .
0x20, 0x10, 0x08, 0x04, 0x02, // /
0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
0x00, 0x04, 0x02, 0x7F, 0x00, // 1
0x42, 0x61, 0x51, 0x49, 0x46, // 2
0x22, 0x41, 0x49, 0x49, 0x36, // 3
0x18, 0x14, 0x12, 0x7F, 0x10, // 4
0x27, 0x45, 0x45, 0x45, 0x39, // 5
0x3E, 0x49, 0x49, 0x49, 0x32, // 6
0x01, 0x01, 0x71, 0x09, 0x07, // 7
0x36, 0x49, 0x49, 0x49, 0x36, // 8
0x26, 0x49, 0x49, 0x49, 0x3E, // 9
0x00, 0x36, 0x36, 0x00, 0x00, // :
0x00, 0x56, 0x36, 0x00, 0x00, // ;
0x08, 0x14, 0x22, 0x41, 0x00, // <
0x14, 0x14, 0x14, 0x14, 0x14, // =
0x00, 0x41, 0x22, 0x14, 0x08, // >
0x02, 0x01, 0x51, 0x09, 0x06, // ?
0x3E, 0x41, 0x59, 0x55, 0x5E, // @
0x7E, 0x09, 0x09, 0x09, 0x7E, // A
0x7F, 0x49, 0x49, 0x49, 0x36, // B
0x3E, 0x41, 0x41, 0x41, 0x22, // C
0x7F, 0x41, 0x41, 0x41, 0x3E, // D
0x7F, 0x49, 0x49, 0x49, 0x41, // E
0x7F, 0x09, 0x09, 0x09, 0x01, // F
0x3E, 0x41, 0x41, 0x49, 0x3A, // G
0x7F, 0x08, 0x08, 0x08, 0x7F, // H
0x00, 0x41, 0x7F, 0x41, 0x00, // I
0x30, 0x40, 0x40, 0x40, 0x3F, // J
0x7F, 0x08, 0x14, 0x22, 0x41, // K
0x7F, 0x40, 0x40, 0x40, 0x40, // L
0x7F, 0x02, 0x0C, 0x02, 0x7F, // M
0x7F, 0x02, 0x04, 0x08, 0x7F, // N
0x3E, 0x41, 0x41, 0x41, 0x3E, // O
0x7F, 0x09, 0x09, 0x09, 0x06, // P
0x1E, 0x21, 0x21, 0x21, 0x5E, // Q
0x7F, 0x09, 0x09, 0x09, 0x76, // R
0x26, 0x49, 0x49, 0x49, 0x32, // S
0x01, 0x01, 0x7F, 0x01, 0x01, // T
0x3F, 0x40, 0x40, 0x40, 0x3F, // U
0x1F, 0x20, 0x40, 0x20, 0x1F, // V
0x7F, 0x20, 0x10, 0x20, 0x7F, // W
0x41, 0x22, 0x1C, 0x22, 0x41, // X
0x07, 0x08, 0x70, 0x08, 0x07, // Y
0x61, 0x51, 0x49, 0x45, 0x43, // Z
0x00, 0x7F, 0x41, 0x00, 0x00, // [
0x02, 0x04, 0x08, 0x10, 0x20, // slash
0x00, 0x00, 0x41, 0x7F, 0x00, // ]
0x04, 0x02, 0x01, 0x02, 0x04, // ^
0x40, 0x40, 0x40, 0x40, 0x40, // _
0x00, 0x01, 0x02, 0x04, 0x00, // `
0x20, 0x54, 0x54, 0x54, 0x78, // a
0x7F, 0x44, 0x44, 0x44, 0x38, // b
0x38, 0x44, 0x44, 0x44, 0x44, // c
0x38, 0x44, 0x44, 0x44, 0x7F, // d
0x38, 0x54, 0x54, 0x54, 0x18, // e
0x04, 0x04, 0x7E, 0x05, 0x05, // f
0x08, 0x54, 0x54, 0x54, 0x3C, // g
0x7F, 0x08, 0x04, 0x04, 0x78, // h
0x00, 0x44, 0x7D, 0x40, 0x00, // i
0x20, 0x40, 0x44, 0x3D, 0x00, // j
0x7F, 0x10, 0x28, 0x44, 0x00, // k
0x00, 0x41, 0x7F, 0x40, 0x00, // l
0x7C, 0x04, 0x78, 0x04, 0x78, // m
0x7C, 0x08, 0x04, 0x04, 0x78, // n
0x38, 0x44, 0x44, 0x44, 0x38, // o
0x7C, 0x14, 0x14, 0x14, 0x08, // p
0x08, 0x14, 0x14, 0x14, 0x7C, // q
0x00, 0x7C, 0x08, 0x04, 0x04, // r
0x48, 0x54, 0x54, 0x54, 0x20, // s
0x04, 0x04, 0x3F, 0x44, 0x44, // t
0x3C, 0x40, 0x40, 0x20, 0x7C, // u
0x1C, 0x20, 0x40, 0x20, 0x1C, // v
0x3C, 0x40, 0x30, 0x40, 0x3C, // w
0x44, 0x28, 0x10, 0x28, 0x44, // x
0x0C, 0x50, 0x50, 0x50, 0x3C, // y
0x44, 0x64, 0x54, 0x4C, 0x44, // z
0x00, 0x08, 0x36, 0x41, 0x41, // {
0x00, 0x00, 0x7F, 0x00, 0x00, // |
0x41, 0x41, 0x36, 0x08, 0x00, // }
0x02, 0x01, 0x02, 0x04, 0x02};// ~
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*/
#define BLC 4
#define RESET 7
#define CMD_ADDR 0x4000
#define DATA_ADDR 0x4100
#define write_cmd(cmd) asm volatile("sts %0,%1" :: "i" (CMD_ADDR), "r" (cmd) : "memory");
#define write_data(data) asm volatile("sts %0,%1" :: "i" (DATA_ADDR), "r" (data) : "memory");
#define write_data16(data) asm volatile("sts %0,%B1 \n\t sts %0,%A1" :: "i" (DATA_ADDR), "r" (data) : "memory");
#define write_cmd_data(cmd, data) asm volatile("sts %0,%1 \n\t sts %2,%3" :: "i" (CMD_ADDR), "r" (cmd), "i" (DATA_ADDR), "r" (data) : "memory");
/* Basic Commands */
#define NO_OPERATION 0x00
#define SOFTWARE_RESET 0x01
#define READ_DISPLAY_IDENTIFICATION_INFORMATION 0x04
#define READ_DISPLAY_STATUS 0x09
#define READ_DISPLAY_POWER_MODE 0x0A
#define READ_DISPLAY_MADCTL 0x0B
#define READ_DISPLAY_PIXEL_FORMAT 0x0C
#define READ_DISPLAY_IMAGE_FORMAT 0x0D
#define READ_DISPLAY_SIGNAL_MODE 0x0E
#define READ_DISPLAY_SELF_DIAGNOSTIC_RESULT 0x0F
#define ENTER_SLEEP_MODE 0x10
#define SLEEP_OUT 0x11
#define PARTIAL_MODE_ON 0x12
#define NORMAL_DISPLAY_MODE_ON 0x13
#define DISPLAY_INVERSION_OFF 0x20
#define DISPLAY_INVERSION_ON 0x21
#define GAMMA_SET 0x26
#define DISPLAY_OFF 0x28
#define DISPLAY_ON 0x29
#define COLUMN_ADDRESS_SET 0x2A
#define PAGE_ADDRESS_SET 0x2B
#define MEMORY_WRITE 0x2C
#define COLOR_SET 0x2D
#define MEMORY_READ 0x2E
#define PARTIAL_AREA 0x30
#define VERTICAL_SCROLLING_DEFINITION 0x33
#define TEARING_EFFECT_LINE_OFF 0x34
#define TEARING_EFFECT_LINE_ON 0x35
#define MEMORY_ACCESS_CONTROL 0x36
#define VERTICAL_SCROLLING_START_ADDRESS 0x37
#define IDLE_MODE_OFF 0x38
#define IDLE_MODE_ON 0x39
#define PIXEL_FORMAT_SET 0x3A
#define WRITE_MEMORY_CONTINUE 0x3C
#define READ_MEMORY_CONTINUE 0x3E
#define SET_TEAR_SCANLINE 0x44
#define GET_SCANLINE 0x45
#define WRITE_DISPLAY_BRIGHTNESS 0x51
#define READ_DISPLAY_BRIGHTNESS 0x52
#define WRITE_CTRL_DISPLAY 0x53
#define READ_CTRL_DISPLAY 0x54
#define WRITE_CONTENT_ADAPTIVE_BRIGHTNESS_CONTROL 0x55
#define READ_CONTENT_ADAPTIVE_BRIGHTNESS_CONTROL 0x56
#define WRITE_CABC_MINIMUM_BRIGHTNESS 0x5E
#define READ_CABC_MINIMUM_BRIGHTNESS 0x5F
#define READ_ID1 0xDA
#define READ_ID2 0xDB
#define READ_ID3 0xDC
/* Extended Commands */
#define RGB_INTERFACE_SIGNAL_CONTROL 0xB0
#define FRAME_CONTROL_IN_NORMAL_MODE 0xB1
#define FRAME_CONTROL_IN_IDLE_MODE 0xB2
#define FRAME_CONTROL_IN_PARTIAL_MODE 0xB3
#define DISPLAY_INVERSION_CONTROL 0xB4
#define BLANKING_PORCH_CONTROL 0xB5
#define DISPLAY_FUNCTION_CONTROL 0xB6
#define ENTRY_MODE_SET 0xB7
#define BACKLIGHT_CONTROL_1 0xB8
#define BACKLIGHT_CONTROL_2 0xB9
#define BACKLIGHT_CONTROL_3 0xBA
#define BACKLIGHT_CONTROL_4 0xBB
#define BACKLIGHT_CONTROL_5 0xBC
#define BACKLIGHT_CONTROL_7 0xBE
#define BACKLIGHT_CONTROL_8 0xBF
#define POWER_CONTROL_1 0xC0
#define POWER_CONTROL_2 0xC1
#define POWER_CONTROL3_(FOR_NORMAL_MODE) 0xC2
#define POWER_CONTROL4_(FOR_IDLE_MODE) 0xC3
#define POWER_CONTROL5_(FOR_PARTIAL_MODE) 0xC4
#define VCOM_CONTROL_1 0xC5
#define VCOM_CONTROL_2 0xC7
#define NV_MEMORY_WRITE 0xD0
#define NV_MEMORY_PROTECTION_KEY 0xD1
#define NV_MEMORY_STATUS_READ 0xD2
#define READ_ID4 0xD3
#define POSITIVE_GAMM_CORRECTION 0xE0
#define NEGATIVE_GAMMA_CORRECTION 0xE1
#define DIGITAL_GAMMA_CONTROL 0xE2
#define DIGITAL_GAMMA_CONTROL2 0xE3
#define INTERFACE_CONTROL 0xF6
/* Undocumented commands */
#define INTERNAL_IC_SETTING 0xCB
#define GAMMA_DISABLE 0xF2
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*
*
* - Jan 2015 Modified for LaFortuna (Rev A, black edition) [KPZ]
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "font.h"
#include "ili934x.h"
#include "lcd.h"
lcd display;
void init_lcd()
{
/* Enable extended memory interface with 10 bit addressing */
XMCRB = _BV(XMM2) | _BV(XMM1);
XMCRA = _BV(SRE);
DDRC |= _BV(RESET);
DDRB |= _BV(BLC);
_delay_ms(1);
PORTC &= ~_BV(RESET);
_delay_ms(20);
PORTC |= _BV(RESET);
_delay_ms(120);
write_cmd(DISPLAY_OFF);
write_cmd(SLEEP_OUT);
_delay_ms(60);
write_cmd_data(INTERNAL_IC_SETTING, 0x01);
write_cmd(POWER_CONTROL_1);
write_data16(0x2608);
write_cmd_data(POWER_CONTROL_2, 0x10);
write_cmd(VCOM_CONTROL_1);
write_data16(0x353E);
write_cmd_data(VCOM_CONTROL_2, 0xB5);
write_cmd_data(INTERFACE_CONTROL, 0x01);
write_data16(0x0000);
write_cmd_data(PIXEL_FORMAT_SET, 0x55); /* 16bit/pixel */
set_orientation(West);
clear_screen();
display.x = 0;
display.y = 0;
display.background = BLACK;
display.foreground = WHITE;
write_cmd(DISPLAY_ON);
_delay_ms(50);
write_cmd_data(TEARING_EFFECT_LINE_ON, 0x00);
EICRB |= _BV(ISC61);
PORTB |= _BV(BLC);
}
void lcd_brightness(uint8_t i)
{
/* Configure Timer 2 Fast PWM Mode 3 */
TCCR2A = _BV(COM2A1) | _BV(WGM21) | _BV(WGM20);
TCCR2B = _BV(CS20);
OCR2A = i;
}
void set_orientation(orientation o)
{
display.orient = o;
write_cmd(MEMORY_ACCESS_CONTROL);
if (o==North) {
display.width = LCDWIDTH;
display.height = LCDHEIGHT;
write_data(0x48);
}
else if (o==West) {
display.width = LCDHEIGHT;
display.height = LCDWIDTH;
write_data(0xE8);
}
else if (o==South) {
display.width = LCDWIDTH;
display.height = LCDHEIGHT;
write_data(0x88);
}
else if (o==East) {
display.width = LCDHEIGHT;
display.height = LCDWIDTH;
write_data(0x28);
}
write_cmd(COLUMN_ADDRESS_SET);
write_data16(0);
write_data16(display.width-1);
write_cmd(PAGE_ADDRESS_SET);
write_data16(0);
write_data16(display.height-1);
}
void set_frame_rate_hz(uint8_t f)
{
uint8_t diva, rtna, period;
if (f>118)
f = 118;
if (f<8)
f = 8;
if (f>60) {
diva = 0x00;
} else if (f>30) {
diva = 0x01;
} else if (f>15) {
diva = 0x02;
} else {
diva = 0x03;
}
/* !!! FIXME !!! [KPZ-30.01.2015] */
/* Check whether this works for diva > 0 */
/* See ILI9341 datasheet, page 155 */
period = 1920.0/f;
rtna = period >> diva;
write_cmd(FRAME_CONTROL_IN_NORMAL_MODE);
write_data(diva);
write_data(rtna);
}
void fill_rectangle(rectangle r, uint16_t col)
{
write_cmd(COLUMN_ADDRESS_SET);
write_data16(r.left);
write_data16(r.right);
write_cmd(PAGE_ADDRESS_SET);
write_data16(r.top);
write_data16(r.bottom);
write_cmd(MEMORY_WRITE);
/* uint16_t x, y;
for(x=r.left; x<=r.right; x++)
for(y=r.top; y<=r.bottom; y++)
write_data16(col);
*/
uint16_t wpixels = r.right - r.left + 1;
uint16_t hpixels = r.bottom - r.top + 1;
uint8_t mod8, div8;
uint16_t odm8, odd8;
if (hpixels > wpixels) {
mod8 = hpixels & 0x07;
div8 = hpixels >> 3;
odm8 = wpixels*mod8;
odd8 = wpixels*div8;
} else {
mod8 = wpixels & 0x07;
div8 = wpixels >> 3;
odm8 = hpixels*mod8;
odd8 = hpixels*div8;
}
uint8_t pix1 = odm8 & 0x07;
while(pix1--)
write_data16(col);
uint16_t pix8 = odd8 + (odm8 >> 3);
while(pix8--) {
write_data16(col);
write_data16(col);
write_data16(col);
write_data16(col);
write_data16(col);
write_data16(col);
write_data16(col);
write_data16(col);
}
}
void fill_rectangle_indexed(rectangle r, uint16_t* col)
{
uint16_t x, y;
write_cmd(COLUMN_ADDRESS_SET);
write_data16(r.left);
write_data16(r.right);
write_cmd(PAGE_ADDRESS_SET);
write_data16(r.top);
write_data16(r.bottom);
write_cmd(MEMORY_WRITE);
for(x=r.left; x<=r.right; x++)
for(y=r.top; y<=r.bottom; y++)
write_data16(*col++);
}
void clear_screen()
{
display.x = 0;
display.y = 0;
rectangle r = {0, display.width-1, 0, display.height-1};
fill_rectangle(r, display.background);
}
void display_char(char c)
{
uint16_t x, y;
PGM_P fdata;
uint8_t bits, mask;
uint16_t sc=display.x, ec=display.x + 4, sp=display.y, ep=display.y + 7;
/* New line starts a new line, or if the end of the
display has been reached, clears the display.
*/
if (c == '\n') {
display.x=0; display.y+=8;
if (display.y >= display.height) { clear_screen(); }
return;
}
if (c < 32 || c > 126) return;
fdata = (c - ' ')*5 + font5x7;
write_cmd(PAGE_ADDRESS_SET);
write_data16(sp);
write_data16(ep);
for(x=sc; x<=ec; x++) {
write_cmd(COLUMN_ADDRESS_SET);
write_data16(x);
write_data16(x);
write_cmd(MEMORY_WRITE);
bits = pgm_read_byte(fdata++);
for(y=sp, mask=0x01; y<=ep; y++, mask<<=1)
write_data16((bits & mask) ? display.foreground : display.background);
}
write_cmd(COLUMN_ADDRESS_SET);
write_data16(x);
write_data16(x);
write_cmd(MEMORY_WRITE);
for(y=sp; y<=ep; y++)
write_data16(display.background);
display.x += 6;
if (display.x >= display.width) { display.x=0; display.y+=8; }
}
void display_string(char *str)
{
uint8_t i;
for(i=0; str[i]; i++)
display_char(str[i]);
}
void display_string_xy(char *str, uint16_t x, uint16_t y)
{
uint8_t i;
display.x = x;
display.y = y;
for(i=0; str[i]; i++)
display_char(str[i]);
}
void display_register(uint8_t reg)
{
uint8_t i;
for(i = 0; i < 8; i++) {
if((reg & (_BV(7) >> i)) != 0) {
display_char( '1' );
} else {
display_char( '.' );
}
}
}
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*/
#include <avr/io.h>
#include <stdint.h>
#define LCDWIDTH 240
#define LCDHEIGHT 320
/* Colour definitions RGB565 */
#define WHITE 0xFFFF
#define BLACK 0x0000
#define BLUE 0x001F
#define GREEN 0x07E0
#define CYAN 0x07FF
#define RED 0xF800
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
typedef enum {North, West, South, East} orientation;
typedef struct {
uint16_t width, height;
orientation orient;
uint16_t x, y;
uint16_t foreground, background;
} lcd;
extern lcd display;
typedef struct {
uint16_t left, right;
uint16_t top, bottom;
} rectangle;
void init_lcd();
void lcd_brightness(uint8_t i);
void set_orientation(orientation o);
void set_frame_rate_hz(uint8_t f);
void clear_screen();
void fill_rectangle(rectangle r, uint16_t col);
void fill_rectangle_indexed(rectangle r, uint16_t* col);
void display_char(char c);
void display_string(char *str);
void display_string_xy(char *str, uint16_t x, uint16_t y);
void display_register(uint8_t reg);
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*/
#include <avr/io.h>
#include "led.h"
void init_led()
{
DDRB |= _BV(LED);
PORTB &= ~_BV(LED);
}
void led_on()
{
PORTB |= _BV(LED);
}
void led_off()
{
TCCR0A = 0x00;
TCCR0B = 0x00;
PORTB &= ~_BV(LED);
}
void led_brightness(uint8_t i)
{
/* Configure Timer 0 Fast PWM Mode 3 */
TCCR0A = _BV(COM0A1) | _BV(WGM01) | _BV(WGM00);
TCCR0B = _BV(CS20);
OCR0A = i;
}
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*/
#include <stdint.h>
#define LED PB7
void init_led();
void led_on();
void led_off();
void led_brightness(uint8_t i);
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "rotary.h"
volatile int8_t rotary = 0;
void init_rotary()
{
/* Ensure all pins are inputs with pull-ups enabled */
DDRE &= ~_BV(ROTA) & ~_BV(ROTB) & ~_BV(SWC);
PORTE |= _BV(ROTA) | _BV(ROTB) | _BV(SWC);
DDRC &= ~_BV(SWN) & ~_BV(SWE) & ~_BV(SWS) & ~_BV(SWW);
PORTC |= _BV(SWN) | _BV(SWE) | _BV(SWS) | _BV(SWW);
/* Configure interrupt for any edge on rotary and falling edge for button */
EICRB |= _BV(ISC40) | _BV(ISC50) | _BV(ISC71);
}
int8_t get_rotary()
{
static uint8_t lastAB = 0x00;
uint8_t AB = PINE & (_BV(ROTA) | _BV(ROTB));
if ((AB == 0x00 && lastAB == 0x20) || (AB == 0x30 && lastAB == 0x10))
rotary--;
if ((AB == 0x30 && lastAB == 0x20) || (AB == 0x00 && lastAB == 0x10))
rotary++;
lastAB = AB;
return rotary;
}
uint8_t get_switch()
{
return PINC & (_BV(SWN) | _BV(SWE) | _BV(SWS) | _BV(SWW));
}
ISR(INT4_vect)
{
get_rotary();
_delay_us(100);
}
ISR(INT5_vect, ISR_ALIASOF(INT4_vect));
/* Author: Steve Gunn
* Licence: This work is licensed under the Creative Commons Attribution License.
* View this license at http://creativecommons.org/about/licenses/
*/
#include <stdint.h>
#define ROTA PE4
#define ROTB PE5
#define SWC PE7
#define SWN PC2
#define SWE PC3
#define SWS PC4
#define SWW PC5
extern volatile int8_t rotary;
void init_rotary();
int8_t get_rotary();
uint8_t get_switch();
main.c 0 → 100644
/* Configure I/O Ports */
/* For La Fortuna board
| Port | Pin | Function |
|------+-----+------------------|
| C | 2 | Up Button |
| C | 3 | Right Button |
| C | 4 | Down Button |
| C | 5 | Left Button |
*/
#include <stdio.h>
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <time.h>
#include <stdlib.h>
#include "lib/lcd/lcd.h"
#include "lib/rotary/rotary.h"
#include "buttons.h"
#include "main.h"
#define FPS 10
#define BLOCK_SIZE 8
#define SCREEN_WIDTH 320
#define DIFFICULTY_INTERVAL 130
#define SCREEN_HEIGHT 240
#define UP_BUFFER 0
#define RIGHT_BUFFER 1
#define DOWN_BUFFER 2
#define LEFT_BUFFER 3
#define MAX_ENEMIES ((SCREEN_WIDTH / BLOCK_SIZE) * (SCREEN_HEIGHT / BLOCK_SIZE)) / 2
#define max(x,y) ((x) >= (y)) ? (x) : (y)
#define min(x,y) ((x) <= (y)) ? (x) : (y)
/* Bits 0-3: Up, Right, Down, Left */
volatile uint8_t MOVEMENT_BUFFER = 0;
volatile uint16_t x = SCREEN_WIDTH/2;
volatile uint16_t y = SCREEN_HEIGHT/2;
volatile uint16_t apple_x;
volatile uint16_t apple_y;
volatile uint8_t enemy_spawn_chance = 1;
struct coord {uint16_t x; uint16_t y;};
volatile struct coord enemies[MAX_ENEMIES];
volatile uint16_t current_enemies = 0;
volatile uint16_t current_difficulty_time = 0;
volatile uint16_t score = 0;
rectangle snake_head = {SCREEN_WIDTH/2, SCREEN_WIDTH/2 + BLOCK_SIZE,
SCREEN_HEIGHT/2, SCREEN_HEIGHT/2 + BLOCK_SIZE};
rectangle previous_block;
rectangle apple;
volatile uint8_t tick = 0;
enum move{Up, Right, Down, Left};
// uint8_t moves_buffered = 0;
// uint8_t moves[NUMBER_MOVES_BUFFERED];
volatile enum move current_direction = Right;
void init(void) {
/* 8MHz clock, no prescaling (DS, p. 48) */
CLKPR = (1 << CLKPCE);
CLKPR = 0;
init_lcd();
set_frame_rate_hz(61);
/* Enable tearing interrupt to get flicker free display */
EIMSK |= _BV(INT6);
/* Set as input */
DDRC &= ~_BV(SWN) & ~_BV(SWE) & ~_BV(SWS) & ~_BV(SWW);
/* Enable direction buttons */
PORTC |= _BV(SWN) | _BV(SWE) | _BV(SWS) | _BV(SWW);
/* Timer 0 for button listening interrupt: */
TCCR0A = _BV(WGM01);
TCCR0B = _BV(CS02) | _BV(CS00); /* F_CPU / 1024 */
/* Timer 3 (16-bit) for frame counting */
TCCR3A = 0;
TCCR3B |= _BV(WGM32);
TCCR3B |= _BV(CS32) | _BV(CS30); /* F_CPU / 1024 */
OCR0A = 78; /* 8MHz clock / 1024 (from TCCR0B flags) / 100 (for ~10ms delay) */
OCR3A = 7812 / FPS; /* 8MHz clock / 1024 / FPS */
/* Enable timer interrupts */
TIMSK0 |= _BV(OCIE0A);
TIMSK3 |= _BV(OCIE3A);
/* Set seed for random numbers */
srand(time(NULL));
}
ISR(TIMER3_COMPA_vect) {
tick = 1;
}
ISR(TIMER0_COMPA_vect) {
if (is_up_pressed()) {
MOVEMENT_BUFFER |= _BV(UP_BUFFER);
} else if (is_right_pressed()) {
MOVEMENT_BUFFER |= _BV(RIGHT_BUFFER);
} else if (is_down_pressed()) {
MOVEMENT_BUFFER |= _BV(DOWN_BUFFER);
} else if (is_left_pressed()) {
MOVEMENT_BUFFER |= _BV(LEFT_BUFFER);
}
}
void redraw_apple(void) {
apple_x = (rand() % (SCREEN_WIDTH / 8)) * 8;
apple_y = (rand() % (SCREEN_HEIGHT / 8)) * 8;
if (apple_y == 0) {
apple_y = BLOCK_SIZE;
}
apple.left = apple_x;
apple.right = apple_x + BLOCK_SIZE;
apple.top = apple_y;
apple.bottom = apple_y + BLOCK_SIZE;
fill_rectangle(apple, 3000);
}
void clear_enemies(void) {
for (uint16_t i = 0; i < current_enemies; i++) {
rectangle enemy;
enemy.left = enemies[i].x;
enemy.right = enemies[i].x + BLOCK_SIZE;
enemy.top = enemies[i].y;
enemy.bottom = enemies[i].y + BLOCK_SIZE;
fill_rectangle(enemy, 0);
}
current_enemies = 0;
}
void reset(void) {
_delay_ms(1000);
fill_rectangle(apple, 0);
clear_enemies();
score = 0;
enemy_spawn_chance = 1;
current_direction = Right;
x = SCREEN_WIDTH/2;
y = SCREEN_HEIGHT/2;
redraw_apple();
info_redraw_logic();
}
void snake_move_logic(void) {
switch (current_direction) {
case Up:
y -= BLOCK_SIZE;
break;
case Right:
x += BLOCK_SIZE;
break;
case Down:
y += BLOCK_SIZE;
break;
case Left:
x -= BLOCK_SIZE;
break;
}
if (y > SCREEN_HEIGHT - BLOCK_SIZE || /* Don't need to handle < 0 as it's unsigned */
x > SCREEN_WIDTH - BLOCK_SIZE) {
reset();
}
previous_block = snake_head;
snake_head.left = x;
snake_head.right = x + BLOCK_SIZE;
snake_head.top = y;
snake_head.bottom = y + BLOCK_SIZE;
}
void snake_direction_logic(void) {
if ((MOVEMENT_BUFFER >> UP_BUFFER) & 1) {
current_direction = Up;
MOVEMENT_BUFFER = 0;
}
if ((MOVEMENT_BUFFER >> RIGHT_BUFFER) & 1) {
current_direction = Right;
MOVEMENT_BUFFER = 0;
}
if ((MOVEMENT_BUFFER >> DOWN_BUFFER) & 1) {
current_direction = Down;
MOVEMENT_BUFFER = 0;
}
if (((MOVEMENT_BUFFER >> LEFT_BUFFER) & 1)) {
current_direction = Left;
MOVEMENT_BUFFER = 0;
}
}
void enemy_spawn_logic(void) {
if (rand() % 180 <= enemy_spawn_chance) {
struct coord c = {(rand() % (SCREEN_WIDTH / 8)) * 8, (rand() % (SCREEN_HEIGHT / 8)) * 8};
while ((c.x == x && c.y == y) || (c.x == apple_x && c.y == apple_y)) {
c.x = (rand() % (SCREEN_WIDTH / 8)) * 8;
c.y = (rand() % (SCREEN_HEIGHT / 8)) * 8;
}
enemies[current_enemies++] = c;
rectangle enemy;
enemy.left = c.x;
enemy.right = c.x + BLOCK_SIZE;
enemy.top = c.y;
enemy.bottom = c.y + BLOCK_SIZE;
fill_rectangle(enemy, RED);
}
}
void snake_draw_logic(void) {
fill_rectangle(previous_block, 0);
fill_rectangle(snake_head, 5000);
}
void info_redraw_logic(void) {
char str[50];
sprintf(str, "Score: %05d Difficulty: %d", score, enemy_spawn_chance);
display_string_xy(str, 0, 0);
}
ISR(INT6_vect) {
snake_draw_logic();
info_redraw_logic();
}
void apple_draw_logic(void) {
if (apple_x == x && apple_y == y) {
clear_enemies();
score += 200;
redraw_apple();
}
}
void enemy_collision_logic(void) {
for (uint16_t i = 0; i < current_enemies; i++) {
if (enemies[i].x == x && enemies[i].y == y) {
reset();
}
}
}
int main() {
init();
sei();
reset();
for (;;) {
if (tick) {
snake_direction_logic();
snake_move_logic();
apple_draw_logic();
enemy_collision_logic();
enemy_spawn_logic();
if (current_difficulty_time++ >= DIFFICULTY_INTERVAL) {
enemy_spawn_chance++;
current_difficulty_time = 0;
}
score++;
tick = 0;
}
}
}
main.h 0 → 100644
//
// Created by platelminto on 5/20/20.
//
#ifndef SNAKE_MAIN_H
#define SNAKE_MAIN_H
#endif //SNAKE_MAIN_H
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment