Copy project

This commit is contained in:
schmelczerandras 2020-04-19 12:48:06 +02:00
parent ce7a467af7
commit 26a0fd884f
173 changed files with 157458 additions and 1 deletions

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
**/Debug
**/Release
**/__pycache__
**/.idea
**/.vs
**/bin

View file

@ -1 +1,7 @@
# ad_astra
# Ad astra
## Directories
- [sprite_generator](sprite_generator/)
> Contains a python script for transforming [Piskel](https://www.piskelapp.com/) sprites
> into C files.

19
ad_astra/AdAstra.atsln Normal file
View file

@ -0,0 +1,19 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Atmel Studio Solution File, Format Version 11.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "AdAstra", "AdAstra\AdAstra.cproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|AVR = Release|AVR
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Store xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="AtmelPackComponentManagement">
<ProjectComponents />
</Store>

View file

@ -0,0 +1,404 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.C</ToolchainName>
<ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
<avrdevice>ATtiny85</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>C</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>TestProject</AssemblyName>
<Name>TestProject</Name>
<RootNamespace>TestProject</RootNamespace>
<ToolchainFlavour>Native</ToolchainFlavour>
<KeepTimersRunning>false</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>false</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>true</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey />
<AsfFrameworkConfig>
<framework-data>
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.47.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
<avrtool>com.atmel.avrdbg.tool.ispmk2</avrtool>
<avrtoolserialnumber>000200212345</avrtoolserialnumber>
<avrdeviceexpectedsignature>0x1E930B</avrdeviceexpectedsignature>
<avrtoolinterface>ISP</avrtoolinterface>
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
<com_atmel_avrdbg_tool_ispmk2>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.ispmk2</ToolType>
<ToolNumber>000200212345</ToolNumber>
<ToolName>AVRISP mkII</ToolName>
</com_atmel_avrdbg_tool_ispmk2>
<com_atmel_avrdbg_tool_simulator>
<ToolOptions xmlns="">
<InterfaceProperties>
</InterfaceProperties>
<InterfaceName>
</InterfaceName>
</ToolOptions>
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
<ToolNumber xmlns="">
</ToolNumber>
<ToolName xmlns="">Simulator</ToolName>
</com_atmel_avrdbg_tool_simulator>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.SubroutinesFunctionPrologues>True</avrgcc.compiler.general.SubroutinesFunctionPrologues>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
<Value>../src/macros</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Undefined>True</avrgcc.compiler.warnings.Undefined>
<avrgcc.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
</AvrGcc>
</ToolchainSettings>
<OutputFileName>ad_astra</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
</AvrGcc>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'WithUART' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
<Value>UART_ENABLED</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Undefined>True</avrgcc.compiler.warnings.Undefined>
<avrgcc.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
</AvrGcc>
</ToolchainSettings>
<OutputFileName>ad_astra</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputPath>bin\WithUART\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="src\driver\redundant_storage\redundant_storage.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\redundant_storage\redundant_storage.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\sleep\sleep.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\eeprom\eeprom.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\eeprom\eeprom.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\hardware_access.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\hardware_access.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\output_pins\output_pins.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\output_pins\output_pins.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\power_saving\power_saving.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\spi\spi.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\spi\spi.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\timing\timing.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\timing\timing.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\display\display.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\display\display.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\infra\infra.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\infra\infra.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\sleep\sleep.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\macros\bitwise.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\macros\math.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\macros\null.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\main.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\mediator\mediator.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\mediator\mediator.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\ai\ai.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\ai\ai.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\commands\commands.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\commands\commands.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\event_generator\event_generator.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\event_generator\event_generator.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object_container\object_container.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object_container\object_container.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\prototype.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\asteroid\asteroid.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\asteroid\asteroid.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\astronaut\astronaut.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\astronaut\astronaut.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\background\background.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\background\background.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\bullet\bullet.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\bullet\bullet.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\heart\heart.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\heart\heart.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\spaceship\spaceship.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\spaceship\spaceship.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\sprites.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\sprites.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\random\random.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\random\random.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\rectangle\rectangle.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\rectangle\rectangle.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\vec2\vec2.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\vec2\vec2.h">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="src" />
<Folder Include="src\driver\" />
<Folder Include="src\driver\display\" />
<Folder Include="src\driver\infra\" />
<Folder Include="src\driver\redundant_storage" />
<Folder Include="src\driver\sleep\" />
<Folder Include="src\hardware_access\" />
<Folder Include="src\hardware_access\eeprom\" />
<Folder Include="src\hardware_access\output_pins" />
<Folder Include="src\hardware_access\power_saving\" />
<Folder Include="src\hardware_access\spi\" />
<Folder Include="src\hardware_access\timing\" />
<Folder Include="src\macros\" />
<Folder Include="src\mediator\" />
<Folder Include="src\objects\" />
<Folder Include="src\objects\ai\" />
<Folder Include="src\objects\commands\" />
<Folder Include="src\objects\event_generator\" />
<Folder Include="src\objects\object_container\" />
<Folder Include="src\objects\types\" />
<Folder Include="src\objects\types\asteroid\" />
<Folder Include="src\objects\types\astronaut\" />
<Folder Include="src\objects\types\background\" />
<Folder Include="src\objects\types\bullet\" />
<Folder Include="src\objects\types\heart\" />
<Folder Include="src\objects\types\spaceship\" />
<Folder Include="src\util\" />
<Folder Include="src\util\random\" />
<Folder Include="src\util\rectangle\" />
<Folder Include="src\util\vec2\" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Store xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="AtmelPackComponentManagement">
<ProjectComponents>
<ProjectComponent z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<CApiVersion></CApiVersion>
<CBundle></CBundle>
<CClass>Device</CClass>
<CGroup>Startup</CGroup>
<CSub></CSub>
<CVariant></CVariant>
<CVendor>Atmel</CVendor>
<CVersion>1.3.0</CVersion>
<DefaultRepoPath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs</DefaultRepoPath>
<DependentComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<Description></Description>
<Files xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\include</AbsolutePath>
<Attribute></Attribute>
<Category>include</Category>
<Condition>C</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>include</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\include\avr\iotn85.h</AbsolutePath>
<Attribute></Attribute>
<Category>header</Category>
<Condition>C</Condition>
<FileContentHash>RcYmivGpgsCGGCzeWAIjcA==</FileContentHash>
<FileVersion></FileVersion>
<Name>include/avr/iotn85.h</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\templates\main.c</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>9ptzGqB00V1zM0TC00KMag==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.c</Name>
<SelectString>Main file (.c)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\templates\main.cpp</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>YXFphlh0CtZJU+ebktABgQ==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.cpp</Name>
<SelectString>Main file (.cpp)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85</AbsolutePath>
<Attribute></Attribute>
<Category>libraryPrefix</Category>
<Condition>GCC</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>gcc/dev/attiny85</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
</Files>
<PackName>ATtiny_DFP</PackName>
<PackPath>C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATtiny_DFP/1.3.229/Atmel.ATtiny_DFP.pdsc</PackPath>
<PackVersion>1.3.229</PackVersion>
<PresentInProject>true</PresentInProject>
<ReferenceConditionId>ATtiny85</ReferenceConditionId>
<RteComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:string></d4p1:string>
</RteComponents>
<Status>Resolved</Status>
<VersionMode>Fixed</VersionMode>
<IsComponentInAtProject>true</IsComponentInAtProject>
</ProjectComponent>
</ProjectComponents>
</Store>

View file

@ -0,0 +1,129 @@
#include "display.h"
#include <avr/pgmspace.h>
#include "bitwise.h"
#include "math.h"
#include "../../hardware_access/hardware_access.h"
static uint8_t const configuration[] PROGMEM = {
0xD5, 0xF0, // set clock frequency
0x8D, 0x14, // enable charge pump
0x20, 0x00, // horizontal addressing mode
0xD6, 0x01, // 2 times vertical zoom
0x22, 0x00, 0x03, // only draw to the top half of the screen
0xAF // display on
};
static struct {
uint8_t compositingBuffer[DISPLAY_WIDTH_IN_PIXELS];
Rectangle compositingWindow;
DrawFunction drawEverything;
bool wasIntersection;
} display;
static inline void commandMode() {
setOutputPin(DISPLAY_DC_OUTPUT_PIN, false);
}
static inline void dataMode() {
setOutputPin(DISPLAY_DC_OUTPUT_PIN, true);
}
void setDisplayContrast(uint8_t value) {
commandMode();
sendByteOnSPI(0x81);
sendByteOnSPI(value);
dataMode();
}
void initializeDisplay(DrawFunction drawEverything) {
setOutputPin(DISPLAY_RESET_OUTPUT_PIN, false);
for (volatile uint8_t i = 0; i != 255; i++)
;
// some time has to elapse before the next line gets called,
// otherwise the display wont turn on
setOutputPin(DISPLAY_RESET_OUTPUT_PIN, true);
for (uint8_t i = 0; i < sizeof(configuration); i++) {
sendByteOnSPI(pgm_read_byte(configuration + i));
}
display.drawEverything = drawEverything;
setDisplayContrast(255);
dataMode();
}
void startIntersectionTest(Rectangle compositingWindow) {
display.wasIntersection = false;
display.compositingWindow = compositingWindow;
}
bool endIntersectionTest() {
for (uint8_t x = 0; x < DISPLAY_WIDTH_IN_PIXELS; x++) {
display.compositingBuffer[x] = 0;
}
return display.wasIntersection;
}
void drawFrame() {
display.compositingWindow = DEFAULT_COMPOSITING_WINDOW;
for (display.compositingWindow.position.y = 0; display.compositingWindow.position.y < DISPLAY_HEIGHT_IN_PIXELS; display.compositingWindow.position.y += 8) {
display.drawEverything(display.compositingWindow);
for (uint8_t x = 0; x < DISPLAY_WIDTH_IN_PIXELS; x++) {
sendByteOnSPI(display.compositingBuffer[x]);
sendByteOnSPI(display.compositingBuffer[x]);
display.compositingBuffer[x] = 0;
}
}
}
static void compositePixelColumn(uint8_t x, uint8_t invertedMask, uint8_t fill) {
if (display.compositingBuffer[x] & fill) {
display.wasIntersection = true;
}
display.compositingBuffer[x] = (display.compositingBuffer[x] & (~invertedMask)) | fill;
}
void drawBitmapFromProgMem(Rectangle boundingBox, uint16_t const data[boundingBox.size.x][(boundingBox.size.y + 7) / 8], bool isMirrored) {
boundingBox.position = substract(boundingBox.position, display.compositingWindow.position);
uint8_t spriteY = max(0, -boundingBox.position.y);
uint8_t spriteYByte = spriteY >> 3;
for (uint8_t x = max(0, -boundingBox.position.x); x < boundingBox.size.x && boundingBox.position.x + x < DISPLAY_WIDTH_IN_PIXELS; x++) {
uint8_t spriteX = isMirrored ? boundingBox.size.x - x - 1 : x;
uint16_t currentPixelColumn = loadWordEEPROM(&data[spriteX][spriteYByte]);
uint8_t fill, invertedMask;
if (boundingBox.position.y >= 0) {
fill = (currentPixelColumn & 0x00FF) << boundingBox.position.y;
invertedMask = currentPixelColumn >> 8 << boundingBox.position.y;
} else {
uint16_t lowerPixelColumn = spriteYByte + 1 < (boundingBox.size.y + 7) / 8 ? loadWordEEPROM(&data[spriteX][spriteYByte + 1]) : 0;
uint8_t shift = spriteY % 8;
uint8_t inverseShift = 8 - shift;
fill = ((currentPixelColumn & 0x00FF) >> shift) | ((lowerPixelColumn & 0x0FF) << inverseShift);
invertedMask = (currentPixelColumn >> 8 >> shift) | (lowerPixelColumn >> 8 << inverseShift);
}
compositePixelColumn(boundingBox.position.x + x, invertedMask, fill);
}
}
void drawFilledRectangle(Rectangle box, uint8_t invertedMask, uint8_t fill) {
box.position = substract(box.position, display.compositingWindow.position);
uint8_t upperGapHeight = min(8, max(0, box.position.y));
uint8_t lowerGapHeight = min(8, max(0, 8 - (box.position.y + box.size.y)));
uint8_t actualFill = (fill >> lowerGapHeight) & (fill << upperGapHeight);
uint8_t actualInvertedMask = (invertedMask >> lowerGapHeight) & (invertedMask << upperGapHeight);
for (uint8_t x = max(0, box.position.x); x < box.position.x + box.size.x && x < DISPLAY_WIDTH_IN_PIXELS; x++) {
compositePixelColumn(x, actualInvertedMask, actualFill);
}
}

View file

@ -0,0 +1,34 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <stdbool.h>
#include <avr/io.h>
#include "../../util/rectangle/rectangle.h"
#define DISPLAY_RESET_OUTPUT_PIN PB0
#define DISPLAY_DC_OUTPUT_PIN PB4
#define DISPLAY_WIDTH_IN_PIXELS 64
#define DISPLAY_HEIGHT_IN_PIXELS 32
#define WINDOW ((Rectangle){(Vec2){0, 0}, (Vec2){DISPLAY_WIDTH_IN_PIXELS, DISPLAY_HEIGHT_IN_PIXELS}})
#define DEFAULT_COMPOSITING_WINDOW ((Rectangle){(Vec2){0, 0}, (Vec2){DISPLAY_WIDTH_IN_PIXELS, 8}})
typedef void (*DrawFunction)(Rectangle);
void initializeDisplay(DrawFunction drawEverything);
void setDisplayContrast(uint8_t value);
void startIntersectionTest();
bool endIntersectionTest();
void drawFrame();
void drawBitmapFromProgMem(Rectangle boundingBox, uint16_t const data[boundingBox.size.x][(boundingBox.size.y + 7) / 8], bool isMirrored);
// for white rectangle: invertedMask: don't care, fill: 0xFF
// for black rectangle: invertedMask: 0xFF, fill: 0x00
void drawFilledRectangle(Rectangle box, uint8_t invertedMask, uint8_t fill);
#endif

View file

@ -0,0 +1,144 @@
#include "infra.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include "bitwise.h"
#include "../../hardware_access/hardware_access.h"
// (0.5625 + (0.5625 + 1.6875) / 2) / 1000 / timer interval
#define MEAN_OF_0_1_BIT_TIMES 53
// 9 / 2 / 1000 / timer interval
#define MAYBE_ONE_CHECK_TIME 141
// some large value
#define TIMEOUT 254
typedef enum {
idle, maybeLeadingOne, leadingOneConfirmed, activeFirstBit, active, timingOut
} ProtocolState;
typedef enum {
noMatch, foundStartingByte, significantByte, waitingForEndOfCommand, waitingForRepeat
} CommandState;
static struct {
uint8_t current;
uint8_t bitPosition;
ProtocolState protocolState;
CommandState commandState;
OnCommandReceived onCommandReceived;
} infra;
static void saveCurrentByte() {
uint8_t byte = infra.current;
infra.current = 0;
infra.bitPosition = 0;
if (byte == INFRA_ADDRESS) {
infra.commandState = foundStartingByte;
return;
}
switch (infra.commandState) {
case foundStartingByte:
infra.commandState = significantByte;
break;
case significantByte:
infra.onCommandReceived(byte);
infra.commandState = waitingForEndOfCommand;
break;
case waitingForEndOfCommand:
if (byte == 0) {
infra.commandState = waitingForRepeat;
}
break;
case waitingForRepeat:
if (byte == 0) {
infra.onCommandReceived(REPEAT_CODE);
}
break;
default:
break;
}
}
static void saveBit(uint8_t bit) {
infra.current <<= 1;
infra.current |= bit;
if (++infra.bitPosition == 8) {
saveCurrentByte();
}
}
static inline uint8_t isIrOff() {
return getBit(PINB, IR_PIN);
}
static inline uint8_t isIrOn() {
return !isIrOff();
}
ISR(PCINT0_vect) {
switch (infra.protocolState) {
case idle:
if (isIrOn()) {
enableTimerB(MAYBE_ONE_CHECK_TIME);
infra.protocolState = maybeLeadingOne;
}
break;
case maybeLeadingOne:
infra.protocolState = idle;
break;
case leadingOneConfirmed:
if (isIrOff()) {
infra.protocolState = activeFirstBit;
}
break;
case activeFirstBit:
case timingOut:
if (isIrOn()) {
infra.protocolState = active;
enableTimerB(MEAN_OF_0_1_BIT_TIMES);
}
break;
case active:
if (isIrOn()) {
saveBit(1);
enableTimerB(MEAN_OF_0_1_BIT_TIMES);
}
break;
}
}
ISR(TIM0_COMPB_vect) {
switch (infra.protocolState) {
case maybeLeadingOne:
if (isIrOn()) {
infra.protocolState = leadingOneConfirmed;
}
disableTimerB();
break;
case active:
saveBit(0);
infra.protocolState = timingOut;
enableTimerB(TIMEOUT);
break;
case timingOut:
infra.protocolState = idle;
saveCurrentByte();
disableTimerB();
break;
default:
disableTimerB();
break;
}
}
void initializeInfra(OnCommandReceived onCommandReceived) {
setBit(PORTB, IR_PIN); // enable pull-up
setBit(PCMSK, IR_PIN); // specific pin change interrupt enable
setBit(GIMSK, PCIE); // global on pin change interrupt enable;
infra.onCommandReceived = onCommandReceived;
}

View file

@ -0,0 +1,16 @@
#ifndef INFRA_H
#define INFRA_H
#include <stdbool.h>
#include <avr/io.h>
#define INFRA_ADDRESS 255
#define IR_PIN PB3
#define REPEAT_CODE 1
typedef void (*OnCommandReceived)(uint8_t);
void initializeInfra(OnCommandReceived onCommandReceived);
#endif

View file

@ -0,0 +1,120 @@
#include "redundant_storage.h"
#include "../../hardware_access/hardware_access.h"
#define offsetof(type, member) __builtin_offsetof (type, member)
#define OBJECT_VALIDITY_MASK (0b00111111)
#define IS_USING_PAGE_A_BIT 6
#define IS_VALID_BIT 7
#define METADATA_REDUNDANCY 4
typedef struct {
uint8_t redundantBufferA[REDUNDANT_BUFFER_SIZE];
uint8_t redundantBufferB[REDUNDANT_BUFFER_SIZE];
uint8_t metadata[METADATA_REDUNDANCY];
} MemoryLayout;
static volatile struct {
MemoryLayout buffer;
uint8_t saveIndex;
uint8_t* savePointer;
uint8_t loadIndex;
uint8_t* loadPointer;
uint8_t validMetadata;
bool isEEPROMWriting;
} storage;
static inline bool isUsingPageA() {
return getBit(storage.validMetadata, IS_USING_PAGE_A_BIT);
}
bool isValid() {
return getBit(storage.validMetadata, IS_VALID_BIT);
}
static inline void fixMetadata() {
uint8_t a = storage.buffer.metadata[0];
uint8_t b = storage.buffer.metadata[1];
uint8_t c = storage.buffer.metadata[2];
uint8_t d = storage.buffer.metadata[3];
if (a == b || a == c || a == d) {
storage.validMetadata = a;
} else if (b == c || b == d) {
storage.validMetadata = b;
} else {
storage.validMetadata = c;
}
}
void initializeRedundantStorage() {
for (uint8_t i = 0; i < sizeof(MemoryLayout); i++) {
((uint8_t*)&storage.buffer)[i] = loadSavedByteEEPROM(i);
}
fixMetadata();
}
void invalidateEEPROM() {
for (uint8_t i = 0; i < sizeof(MemoryLayout); i++) {
((uint8_t*)&storage.buffer)[i] = 0;
}
storage.validMetadata = 0;
}
void onEEPROMWriteFinished(__attribute__((unused)) uint8_t* _) {
storage.isEEPROMWriting = false;
}
bool startSchedulingObjectsForSaving() {
if (storage.isEEPROMWriting) {
return false;
}
toggleBit(storage.validMetadata, IS_USING_PAGE_A_BIT);
storage.validMetadata &= ~OBJECT_VALIDITY_MASK;
storage.saveIndex = 0;
storage.savePointer = isUsingPageA() ?
storage.buffer.redundantBufferA
: storage.buffer.redundantBufferB;
return true;
}
void scheduleNextObjectForSave(uint8_t* object, uint8_t size) {
setBit(storage.validMetadata, storage.saveIndex);
storage.saveIndex++;
for (uint8_t i = 0; i < size; i++) {
*storage.savePointer = object[i];
storage.savePointer++;
}
}
void saveScheduledObjects() {
setBit(storage.validMetadata, IS_VALID_BIT);
for (uint8_t i = 0; i < METADATA_REDUNDANCY; i++) {
storage.buffer.metadata[i] = storage.validMetadata;
}
storage.isEEPROMWriting = true;
asyncWriteEEPROM((uint8_t*)&storage.buffer, onEEPROMWriteFinished);
}
bool loadNextObject(uint8_t* holder, uint8_t size) {
if (storage.loadIndex++ == 0) {
storage.loadPointer = isUsingPageA() ?
storage.buffer.redundantBufferA
: storage.buffer.redundantBufferB;
}
if (getBit(storage.validMetadata, storage.loadIndex - 1)) {
for (uint8_t i = 0; i < size; i++) {
holder[i] = *storage.loadPointer++;
}
return true;
}
return false;
}

View file

@ -0,0 +1,22 @@
#ifndef REDUNDANT_STORAGE_H
#define REDUNDANT_STORAGE_H
#include <stdbool.h>
#include <avr/io.h>
#define REDUNDANT_BUFFER_SIZE 24
void initializeRedundantStorage();
bool isValid();
void invalidateEEPROM();
bool startSchedulingObjectsForSaving();
void scheduleNextObjectForSave(uint8_t* object, uint8_t size);
void saveScheduledObjects();
// Returns is loaded object valid
bool loadNextObject(uint8_t* holder, uint8_t size);
#endif

View file

@ -0,0 +1,34 @@
#include "sleep.h"
#include <stdbool.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "bitwise.h"
#include "../../hardware_access/hardware_access.h"
#define TICKS_IN_MILISECOND 31
volatile int8_t milisecondsSinceFrameStart;
void startFrameLoop(FrameFunction function, uint8_t frameLengthInMilliseconds) {
sleep_enable();
uint8_t previousFrameTime = 0;
while (function(previousFrameTime)) {
previousFrameTime = milisecondsSinceFrameStart;
while (milisecondsSinceFrameStart < frameLengthInMilliseconds) {
sleep_cpu();
}
milisecondsSinceFrameStart = 0;
}
}
ISR(TIM0_COMPA_vect) {
milisecondsSinceFrameStart++;
enableTimerA(TICKS_IN_MILISECOND);
}

View file

@ -0,0 +1,13 @@
#ifndef SLEEP_H
#define SLEEP_H
#include <stdbool.h>
#include <avr/io.h>
typedef bool (*FrameFunction)(uint8_t);
// frameFunction gets previousFrameTime (in milliseconds) as argument
void startFrameLoop(FrameFunction function, uint8_t frameLengthInMilliseconds);
#endif

View file

@ -0,0 +1,75 @@
#include "eeprom.h"
#include <stdbool.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
#include "bitwise.h"
uint8_t memory[STORAGE_SIZE] EEMEM;
static volatile struct {
uint8_t* buffer;
uint8_t positon;
bool isWriting;
OnEEPROMFinished onFinished;
} eeprom;
uint8_t loadByteEEPROM(uint8_t* address) {
while(getBit(EECR, EEPE)) {}
EEAR = (uint16_t)address;
setBit(EECR, EERE);
return EEDR;
}
uint8_t loadSavedByteEEPROM(uint8_t address) {
return loadByteEEPROM(memory + address);
}
uint16_t loadWordEEPROM(uint16_t const* address) {
uint16_t high = ((uint16_t)loadByteEEPROM((uint8_t*)address + 1)) << 8;
uint16_t low = (uint16_t)loadByteEEPROM((uint8_t*)address);
return high | low;
}
static inline void saveByteEEPROM(uint8_t* address, uint8_t byte) {
if (byte != loadByteEEPROM(address)) {
EEDR = byte;
setBit(EECR, EEMPE);
setBit(EECR, EEPE);
}
}
void enableWritingEEPROM() {
modifyBit(EECR, EERIE, eeprom.isWriting);
}
void disableWritingEEPROM() {
clearBit(EECR, EERIE); // clear eeprom ready interrupt enable
}
bool asyncWriteEEPROM(uint8_t* buffer, OnEEPROMFinished onFinished) {
if (eeprom.isWriting) {
return false;
}
eeprom.buffer = buffer;
eeprom.onFinished = onFinished;
eeprom.positon = 0;
eeprom.isWriting = true;
setBit(EECR, EERIE); // set eeprom ready interrupt
return true;
}
ISR(EE_RDY_vect) {
saveByteEEPROM(memory + eeprom.positon, eeprom.buffer[eeprom.positon]);
if (++eeprom.positon == STORAGE_SIZE) {
clearBit(EECR, EERIE);
eeprom.isWriting = false;
eeprom.onFinished(eeprom.buffer);
}
}

View file

@ -0,0 +1,15 @@
#ifndef EEPROM_H
#define EEPROM_H
#include <avr/io.h>
#define STORAGE_SIZE 52
typedef void (*OnEEPROMFinished)(uint8_t*);
inline void initializeEEPROM() {
EECR = 0; // atomic write
}
#endif

View file

@ -0,0 +1,13 @@
#include "hardware_access.h"
#include <avr/interrupt.h>
void initializeHardwareAccess() {
sei();
initializePowerSaving();
initializeSPI();
initializeEEPROM();
initializeTiming();
initializeOutputPins();
}

View file

@ -0,0 +1,33 @@
#ifndef HARDWARE_ACCESS_H
#define HARDWARE_ACCESS_H
#include <stdbool.h>
#include <avr/io.h>
#include "bitwise.h"
#include "power_saving/power_saving.h"
#include "spi/spi.h"
#include "eeprom/eeprom.h"
#include "timing/timing.h"
#include "output_pins/output_pins.h"
void initializeHardwareAccess();
// writing of unchanged byte is atomic
bool asyncWriteEEPROM(uint8_t* buffer, OnEEPROMFinished onFinished);
uint8_t loadSavedByteEEPROM(uint8_t address);
uint8_t loadByteEEPROM(uint8_t* address);
uint16_t loadWordEEPROM(uint16_t const* address);
void enableWritingEEPROM();
void disableWritingEEPROM();
void enableTimerA(uint8_t triggerInterruptInXTicks);
void enableTimerB(uint8_t triggerInterruptInXTicks);
void disableTimerB();
void sendByteOnSPI(uint8_t byte);
void setOutputPin(uint8_t id, bool value);
#endif

View file

@ -0,0 +1,11 @@
#include "output_pins.h"
#include "bitwise.h"
#include <avr/io.h>
#include <stdbool.h>
void setOutputPin(uint8_t id, bool value) {
setBit(DDRB, id);
modifyBit(PORTB, id, value);
}

View file

@ -0,0 +1,7 @@
#ifndef GPIO_OUTPUT_PINS_H
#define GPIO_OUTPUT_PINS_H
inline void initializeOutputPins() {}
#endif

View file

@ -0,0 +1,13 @@
#ifndef POWER_SAVING_H
#define POWER_SAVING_H
#include <avr/io.h>
#include "bitwise.h"
inline void initializePowerSaving() {
setBit(ACSR, ACD); // disable ADC to save power
PRR = BV(PRTIM1) | BV(PRADC); // disable power of timer1 and ADC
}
#endif

View file

@ -0,0 +1,30 @@
#include "spi.h"
#include <avr/interrupt.h>
#define SWAP_BIT (BV(USIWM0) | BV(USICLK) | BV(USITC) | BV(USICS1))
void sendByteOnSPI(uint8_t byte) {
USIDR = byte;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
USICR = SWAP_BIT;
}

View file

@ -0,0 +1,17 @@
#ifndef SPI_H
#define SPI_H
#include <avr/io.h>
#include "bitwise.h"
#define DO_PIN PB1
#define USCK_PIN PB2
inline void initializeSPI() {
DDRB |= BV(DO_PIN) | BV(USCK_PIN); // set pin directions for MOSI and SCK
}
void sendByteOnSPI(uint8_t byte);
#endif

View file

@ -0,0 +1,17 @@
#include "timing.h"
#include "bitwise.h"
void enableTimerA(uint8_t triggerInterruptInXTicks) {
OCR0A = TCNT0 + triggerInterruptInXTicks;
}
void enableTimerB(uint8_t triggerInterruptInXTicks) {
setBit(TIFR, OCF0B);
OCR0B = TCNT0 + triggerInterruptInXTicks;
setBit(TIMSK, OCIE0B);
}
void disableTimerB() {
clearBit(TIMSK, OCIE0B);
}

View file

@ -0,0 +1,13 @@
#ifndef TIMING_H
#define TIMING_H
#include <avr/io.h>
#include "bitwise.h"
inline void initializeTiming() {
TCCR0B = BV(CS02); // CLK / 256
setBit(TIMSK, OCIE0A);
}
#endif

View file

@ -0,0 +1,11 @@
#ifndef BITWISE_H
#define BITWISE_H
#define BV(x) (1 << (x))
#define modifyBit(P, B, V) ((P) = ((P) & ~BV(B)) | ((V) << B))
#define setBit(P, B) ((P) |= BV(B))
#define clearBit(P, B) ((P) &= ~BV(B))
#define toggleBit(P, B) ((P) ^= BV(B))
#define getBit(P, B) (((P) & BV(B)) >> (B))
#endif

View file

@ -0,0 +1,9 @@
#ifndef MATH_H
#define MATH_H
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) > (b) ? (b) : (a))
#define abs(a, b) ((a) > 0 ? (a) : (-a))
#endif

View file

@ -0,0 +1,3 @@
#ifndef NULL
#define NULL ((void*)0)
#endif

View file

@ -0,0 +1,14 @@
#include "mediator/mediator.h"
// Stemming from the module oriented nature of the project
// there is a module responsible for setting up and orchestrating
// the other modules.
//
// From the main function we only have to instruct the mediator to
// do its job.
int main(void) {
setupConnections();
startGame();
}

View file

@ -0,0 +1,93 @@
#include "mediator.h"
#include <stdbool.h>
#include "../hardware_access/hardware_access.h"
#include "../objects/object_container/object_container.h"
#include "../objects/event_generator/event_generator.h"
#include "../objects/commands/commands.h"
#include "../objects/ai/ai.h"
#include "../driver/display/display.h"
#include "../driver/infra/infra.h"
#include "../driver/sleep/sleep.h"
#include "../driver/redundant_storage/redundant_storage.h"
#define TARGET_FRAME_DURATION 20 // ms
#define DEATH_SCREEN_LENGTH 50 // frames
#define SAVE_INTERVAL 50 // every x frames
static struct {
uint8_t contrast;
uint8_t framesSinceLastSave;
uint8_t deathDownCounter;
} state = {
.contrast = 255
};
static inline void saveGame() {
if (++state.framesSinceLastSave > SAVE_INTERVAL && startSchedulingObjectsForSaving()) {
scheduleNextObjectForSave(&state.contrast, sizeof(state.contrast));
saveObjects();
saveScheduledObjects();
state.framesSinceLastSave = 0;
}
}
static bool frameFunction(uint8_t previousFrameTime) {
disableWritingEEPROM();
if (spaceshipObject->as.spaceship.healthLoss >= MAX_HEALTH) {
setDisplayContrast(state.contrast * (state.deathDownCounter / DEATH_SCREEN_LENGTH));
if (state.deathDownCounter-- == 0) {
invalidateEEPROM();
return false;
};
}
handleCommands();
handleAI();
generateEvents();
tickObjects(previousFrameTime);
drawFrame();
enableWritingEEPROM();
saveGame();
return true;
}
static inline void createObjects() {
state.deathDownCounter = DEATH_SCREEN_LENGTH;
if (isValid()) {
loadNextObject(&state.contrast, sizeof(state.contrast));
}
setDisplayContrast(state.contrast);
initializeBackground();
initializeObjectContainer();
}
void setupConnections() {
initializeHardwareAccess();
initializeRedundantStorage();
initializeInfra(addCommand);
initializeDisplay(drawObjects);
}
void startGame() {
while (true) {
createObjects();
startFrameLoop(frameFunction, TARGET_FRAME_DURATION);
}
}
void changeDisplayContrast(int8_t by) {
if (by < 0) {
state.contrast = (state.contrast < -by) ? 0 : (state.contrast + by);
} else {
state.contrast = (state.contrast > 255 - by) ? 255 : (state.contrast + by);
}
setDisplayContrast(state.contrast);
}

View file

@ -0,0 +1,11 @@
#ifndef MEDIATOR_H
#define MEDIATOR_H
#include <avr/io.h>
void setupConnections();
void startGame();
void changeDisplayContrast(int8_t by);
#endif

View file

@ -0,0 +1,214 @@
#include "ai.h"
#include <stdbool.h>
#include <avr/io.h>
#include "../object_container/object_container.h"
#include "../types/astronaut/astronaut.h"
#include "../types/spaceship/spaceship.h"
#include "../../util/rectangle/rectangle.h"
#include "../../util/random/random.h"
#include "../../driver/display/display.h"
#define AI_ACTION_COUNT 5
typedef bool (*Predicate)(Rectangle*, Object*);
typedef void (*Execution)(Object*);
typedef struct {
Predicate predicate;
Execution execution;
SpaceshipPart* spaceshipPart;
bool onlyOneAstronautCanDoIt;
Vec2 deltaCenter;
bool isSomeoneDoingThis;
} AIAction;
static AIAction actions[AI_ACTION_COUNT];
static Vec2 whichDirectionToMove(Object* astronaut, Vec2 position) {
bool const isTargetOnUpperFloor = isOnUpperFloor((Rectangle){position, (Vec2){0, 0}}); // else it's on the lower floor
Vec2 const ladder = add(LADDER_BOUNDING_BOX.position, spaceshipObject->position);
Vec2 astronautCenter = getCenter(getBoundingBox(astronaut));
Vec2 target = astronautCenter;
if ((
isOnUpperFloor(getBoundingBox(astronaut)) && isTargetOnUpperFloor
) || (
isOnLowerFloor(getBoundingBox(astronaut)) && !isTargetOnUpperFloor
)) {
target.x = position.x;
} else if (isOnLadder(getBoundingBox(astronaut))){
target.y = add(position, (Vec2){0, isTargetOnUpperFloor ? -10 : 10}).y;
} else {
target.x = ladder.x;
}
return clampVec2(substract(target, astronautCenter));
}
static void carefullyMoveAstronaut(Object* astronaut, Vec2 target) {
if (getIsControllingSpaceship(astronaut)) {
makeAstronautDoAction(astronaut);
}
if (!getIsControllingSpaceship(astronaut)) {
moveAstronaut(astronaut, whichDirectionToMove(astronaut, target));
}
}
static void carefullyMoveSpaceship(Object* astronaut, Vec2 target) {
if (!getIsControllingSpaceship(astronaut)) {
makeAstronautDoAction(astronaut);
}
if (getIsControllingSpaceship(astronaut)) {
Vec2 direction = clampVec2(
substract(
target,
getCenter(getBoundingBox(spaceshipObject))
)
);
moveAstronaut(astronaut, direction);
}
}
static bool shouldShootTurret(
__attribute__((unused)) Rectangle* boundingBox,
__attribute__((unused)) Object* astronaut
) {
return getIntersectingObjectOfType(
(Rectangle){
add(TURRET_POSITION, spaceshipObject->position),
(Vec2){63, 1}
},
&Asteroid
);
}
static bool shouldControlSpaceship(
__attribute__((unused)) Rectangle* boundingBox,
__attribute__((unused)) Object* astronaut
) {
return getCountOf(&Asteroid) > 0;
}
static void executeControlSpaceship(Object* astronaut) {
carefullyMoveSpaceship(
astronaut,
add(
getCenter(getBoundingBox(getFirstOfType(&Asteroid))),
(Vec2){-30, 0}
)
);
}
static bool shouldRepairSpaceship(Rectangle* boundingBox, Object* astronaut) {
return (
(
areIntersecting(*boundingBox, getBoundingBox(astronaut)) &&
spaceshipObject->as.spaceship.healthLoss > 0
) ||
spaceshipObject->as.spaceship.healthLoss >= MAX_HEALTH / 2
);
}
static bool shouldCenterSpaceship(Rectangle* boundingBox, Object* astronaut) {
return (
!actions[0].isSomeoneDoingThis &&
(
areIntersecting(*boundingBox, getBoundingBox(astronaut)) ||
getCenter(getBoundingBox(spaceshipObject)).x != getCenter(WINDOW).x ||
getCenter(getBoundingBox(spaceshipObject)).y != getCenter(WINDOW).y
)
);
}
static void executeCenterSpaceship(Object* astronaut) {
carefullyMoveSpaceship(
astronaut,
getCenter(WINDOW)
);
}
static bool shouldSocialize(
__attribute__((unused)) Rectangle* boundingBox,
__attribute__((unused)) Object* astronaut
) {
return true;
}
static void executeSocialize(Object* astronaut) {
if (getRandomNumber() % 150 == 0) {
makeAstronautDoAction(astronaut);
}
}
static AIAction actions[AI_ACTION_COUNT] = {
(AIAction) {
.predicate = shouldControlSpaceship,
.execution = executeControlSpaceship,
.spaceshipPart = spaceshipParts + COMMAND_PANEL_INDEX,
.onlyOneAstronautCanDoIt = true,
.deltaCenter = {-3, 0}
},
(AIAction) {
.predicate = shouldRepairSpaceship,
.execution = makeAstronautDoAction,
.spaceshipPart = spaceshipParts + BEDS_INDEX,
.onlyOneAstronautCanDoIt = true,
.deltaCenter = {2, 0}
},
(AIAction) {
.predicate = shouldShootTurret,
.execution = makeAstronautDoAction,
.spaceshipPart = spaceshipParts + TURRET_CONTROLLER_INDEX,
.onlyOneAstronautCanDoIt = true,
.deltaCenter = {-3, 0}
},
(AIAction) {
.predicate = shouldCenterSpaceship,
.execution = executeCenterSpaceship,
.spaceshipPart = spaceshipParts + COMMAND_PANEL_INDEX,
.onlyOneAstronautCanDoIt = true,
.deltaCenter = {-3, 0}
},
(AIAction) {
.predicate = shouldSocialize,
.execution = executeSocialize,
.spaceshipPart = spaceshipParts + TABLE_INDEX,
.onlyOneAstronautCanDoIt = false,
.deltaCenter = {2, 0}
},
};
void handleAI() {
for (uint8_t j = 0; j < ACTION_COUNT; j++) {
actions[j].isSomeoneDoingThis = false;
}
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (objects[i].prototype == &Astronaut && objects + i != character) {
for (uint8_t j = 0; j < ACTION_COUNT; j++) {
AIAction* currentAction = actions + j;
Rectangle boundingBox = getBoundingBoxOfSpaceshipPart(currentAction->spaceshipPart);
Object* astronautIntersectingBoundingBox = getIntersectingObjectOfType(boundingBox, &Astronaut);
if (
isSpaceshipPartActivated(currentAction->spaceshipPart) &&
(!currentAction->onlyOneAstronautCanDoIt || (!currentAction->isSomeoneDoingThis && astronautIntersectingBoundingBox != character)) &&
currentAction->predicate(&boundingBox, objects + i)
) {
if (!areIntersecting(boundingBox, getBoundingBox(objects + i))) {
carefullyMoveAstronaut(objects + i, add(getCenter(boundingBox), currentAction->deltaCenter));
} else {
currentAction->execution(objects + i);
}
currentAction->isSomeoneDoingThis = true;
break;
}
}
}
}
}

View file

@ -0,0 +1,8 @@
#ifndef AI_H
#define AI_H
// If there are non player controlled astronauts
// control them according to some basic rule set
void handleAI();
#endif

View file

@ -0,0 +1,66 @@
#include "commands.h"
#include "../../objects/object_container/object_container.h"
#include "../../mediator/mediator.h"
static struct {
Command received[COMMAND_BUFFER_SIZE];
uint8_t start;
uint8_t end;
Command previous;
} commands;
static inline bool areThereAnyCommandsLeft() {
return commands.start != commands.end;
}
static inline Command getNextCommand() {
Command top = commands.received[commands.start++];
commands.start %= COMMAND_BUFFER_SIZE;
return top;
}
void addCommand(Command command) {
commands.received[commands.end++] = command;
commands.end %= COMMAND_BUFFER_SIZE;
}
void handleCommands() {
while(areThereAnyCommandsLeft()) {
Command next = getNextCommand();
if (next == repeat) {
next = commands.previous;
} else {
commands.previous = next;
}
switch(next) {
case increaseContrast:
changeDisplayContrast(CONTRAST_STEP);
break;
case decreaseContrast:
changeDisplayContrast(-CONTRAST_STEP);
break;
case moveLeft:
moveAstronaut(character, directions[west]);
break;
case moveRight:
moveAstronaut(character, directions[east]);
break;
case moveUp:
moveAstronaut(character, directions[north]);
break;
case moveDown:
moveAstronaut(character, directions[south]);
break;
case action:
makeAstronautDoAction(character);
commands.previous = noAction;
break;
default:
break;
}
}
}

View file

@ -0,0 +1,34 @@
#ifndef COMMANDS_H
#define COMMANDS_H
// There can be no more than COMMAND_BUFFER_SIZE commands
// waiting for processing simultaneously
#define COMMAND_BUFFER_SIZE 8
// increaseContrast and decreaseContrast changes the contrast
// with this value
#define CONTRAST_STEP 15
// The possible inputs of the system
// Coincidentally these are the codes of the IR remote
// controller's buttons.
typedef enum {
noCommand = 0,
repeat = 1,
increaseContrast = 87,
decreaseContrast = 31,
moveUp = 231,
moveDown = 181,
moveLeft = 239,
moveRight = 165,
action = 199,
} Command;
// Add a new command to the buffer
// It will not be processed immediately.
void addCommand(Command command);
// Process every command in the buffer at once in a FIFO manner
void handleCommands();
#endif

View file

@ -0,0 +1,81 @@
#include "event_generator.h"
#include <avr/io.h>
#include <stdbool.h>
#include "null.h"
#include "../object.h"
#include "../object_container/object_container.h"
#include "../types/spaceship/spaceship.h"
#include "../types/background/background.h"
#include "../types/astronaut/astronaut.h"
#include "../types/asteroid/asteroid.h"
#include "../../util/random/random.h"
#include "../../driver/display/display.h"
typedef bool (*Predicate)(Rectangle*);
static inline Vec2 getRandomPosition() {
return (Vec2) {
getRandomNumber() % DISPLAY_WIDTH_IN_PIXELS,
getRandomNumber() % DISPLAY_HEIGHT_IN_PIXELS
};
}
static void generate(Prototype const* type, Predicate predicate) {
Object* emptySpace = getEmptyObjectSpace();
if (emptySpace == NULL || getRandomNumber() != 0) {
return;
}
for (uint8_t tryCount = 0; tryCount < TRY_COUNT; tryCount++) {
Rectangle proposedBoundingBox = (Rectangle){getRandomPosition(), getSizeFromPrototype(type)};
if (predicate(&proposedBoundingBox)) {
createObject(type, emptySpace);
emptySpace->position = proposedBoundingBox.position;
return;
}
}
}
bool generateAstronautPredicate(Rectangle* proposedBoundingBox) {
return (
(
(getCountOf(&Astronaut) == 1 && spaceshipObject->as.spaceship.progress >= hasTable) ||
(getCountOf(&Astronaut) == 2 && spaceshipObject->as.spaceship.progress >= hasFullCrew)
) &&
getIntersectingObjectOfType(*proposedBoundingBox, &Astronaut) == NULL &&
isOnboard(*proposedBoundingBox)
);
}
bool generateAsteroidPredicate(Rectangle* proposedBoundingBox) {
return (
getCountOf(&Asteroid) < MAX_ASTEROID_COUNT &&
isInside(*proposedBoundingBox, WINDOW) &&
getIntersectingObjectOfType(*proposedBoundingBox, &Spaceship) == NULL &&
getIntersectingObjectOfType(*proposedBoundingBox, &Asteroid) == NULL
);
}
void createPersistentObjects() {
createObject(&Spaceship, spaceshipObject);
spaceshipObject->position = (Vec2){EXHAUST_BOUNDING_BOX.size.x, DISPLAY_HEIGHT_IN_PIXELS / 2 - getSize(spaceshipObject).y / 2};
createObject(&Astronaut, character);
Rectangle upperFloor = translateRectangle(UPPER_FLOOR_BOUNDING_BOX, spaceshipObject->position);
character->position = add(upperFloor.position, (Vec2){10, 1});
}
void createTransientObjects() {
createObject(&Background, getEmptyObjectSpace());
}
void generateEvents() {
generate(&Astronaut, generateAstronautPredicate);
generate(&Asteroid, generateAsteroidPredicate);
}

View file

@ -0,0 +1,20 @@
#ifndef EVENT_GENERATOR_H
#define EVENT_GENERATOR_H
#define MAX_ASTEROID_COUNT 2
// For minimizing code size the position of generated objects is decided randomly.
// If it fits then it stays. For each generated object can be a maximum of
// TRY_COUNT tries.
#define TRY_COUNT 16
// Create the background
void createTransientObjects();
// Create the spaceship and the player's astronaut
void createPersistentObjects();
// Generate asteroids and astronaut randomly based on a set of conditions
void generateEvents();
#endif

View file

@ -0,0 +1,41 @@
#include "object.h"
#include "null.h"
Object* createObject(Prototype const* prototype, Object* holder) {
Object empty = {0};
*holder = empty;
holder->prototype = prototype;
return holder;
}
void tickObject(Object* object, uint8_t previousFrameTime) {
if (object->prototype != NULL) {
((TickMethod)pgm_read_word(&object->prototype->tick))(object, previousFrameTime);
}
}
void drawObject(Object* object, Rectangle compositingWindow) {
if (object->prototype != NULL && areIntersecting(getBoundingBox(object), compositingWindow)) {
((DrawMethod)pgm_read_word(&object->prototype->draw))(object, compositingWindow);
}
}
Vec2 getSizeFromPrototype(Prototype const* prototype) {
// required for casting
uint16_t read = pgm_read_word(&prototype->size);
Vec2* v = (Vec2*) &read;
return *v;
}
Vec2 getSize(Object const* object) {
return getSizeFromPrototype(object->prototype);
}
void move(Object* object, Vec2 value) {
object->position = add(object->position, value);
}
Rectangle getBoundingBox(Object const* object) {
return (Rectangle){object->position, getSize(object)};
}

View file

@ -0,0 +1,78 @@
#ifndef OBJECT_H
#define OBJECT_H
#include <avr/io.h>
#include <avr/pgmspace.h>
#include "../util/rectangle/rectangle.h"
#include "types/asteroid/asteroid.h"
#include "types/astronaut/astronaut.h"
#include "types/background/background.h"
#include "types/spaceship/spaceship.h"
#include "types/bullet/bullet.h"
#include "types/heart/heart.h"
#include "prototype.h"
// Objects (they could have been called GameObjects) have a simple
// hierarchy. A prototype/flyweight motivated system is used.
// Each type has some common data and methods which are stored
// in their respective prototype.
// This module provides us with the methods to easily and mostly
// transparently access an object's prototype.
typedef union {
struct _background_t background;
struct _spaceship_t spaceship;
struct _astronaut_t astronaut;
struct _asteroid_t asteroid;
struct _bullet_t bullet;
struct _heart_t heart;
} object_specific_data_t;
struct _object_t {
Prototype const* prototype;
Vec2 position;
object_specific_data_t as;
};
// A simplified object intended for persisting its data
// without saving its 16 bit long reference to its prototype
typedef struct {
Vec2 position;
object_specific_data_t as;
} DTO;
// Set the prototype of the holder and initialize all the holder's
// vale to zero. Return the freshly updated holder
Object* createObject(Prototype const* prototype, Object* holder);
// Call the tick function referenced in the object's prototype
// on the object itself
// Object might react to the elapsed time.
// Does nothing when called with NULL.
void tickObject(Object* object, uint8_t previousFrameTime);
// Call the draw function referenced in the object's prototype
// on the object itself
// Does nothing when called with NULL.
void drawObject(Object* object, Rectangle compositingWindow);
// Find out the prototype of the object and return the size of that
Vec2 getSize(Object const* object);
Vec2 getSizeFromPrototype(Prototype const* prototype);
// Move the position of the object by a vector
void move(Object* object, Vec2 value);
// Get a new rectangle from the objects position and its
// prototype's size
Rectangle getBoundingBox(Object const* object);
#endif

View file

@ -0,0 +1,91 @@
#include "object_container.h"
#include "../../driver/redundant_storage/redundant_storage.h"
#include "../event_generator/event_generator.h"
Object* getFirstOfType(Prototype const* type) {
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (objects[i].prototype == type) {
return objects + i;
}
}
return NULL;
}
uint8_t getCountOf(Prototype const* type) {
uint8_t count = 0;
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (objects[i].prototype == type) {
count++;
}
}
return count;
}
Object* getIntersectingObjectOfType(Rectangle boundingBox, Prototype const* type) {
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (objects[i].prototype == type && areIntersecting(boundingBox, getBoundingBox(objects + i))) {
return objects + i;
}
}
return NULL;
}
void clearObject(Object* object) {
createObject(NULL, object);
}
void drawObjects(Rectangle window) {
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
drawObject(objects + i, window);
}
}
void tickObjects(uint8_t previousFrameTime) {
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
tickObject(objects + i, previousFrameTime);
}
}
void saveObject(Object* object) {
DTO dto = {object->position, object->as};
scheduleNextObjectForSave((uint8_t*)&dto, sizeof(dto));
}
void loadObject(Object* holder, Prototype const* prototype) {
DTO dto;
holder->prototype = loadNextObject((uint8_t*)&dto, sizeof(dto)) ? prototype : NULL;
holder->position = dto.position;
holder->as = dto.as;
}
void saveObjects() {
saveObject(spaceshipObject);
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (objects[i].prototype == &Astronaut) {
saveObject(objects + i);
}
}
}
void initializeObjectContainer() {
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
clearObject(objects + i);
}
createTransientObjects();
if (isValid()) {
loadObject(spaceshipObject, &Spaceship);
loadObject(character, &Astronaut);
loadObject(getEmptyObjectSpace(), &Astronaut);
loadObject(getEmptyObjectSpace(), &Astronaut);
} else {
createPersistentObjects();
}
}

View file

@ -0,0 +1,62 @@
#ifndef OBJECT_HANDLER_H
#define OBJECT_HANDLER_H
#include <stdbool.h>
#include <avr/io.h>
#include "null.h"
#include "../object.h"
#include "../../util/rectangle/rectangle.h"
#include "../../util/vec2/vec2.h"
// Contain up to OBJECT_COUNT objects.
// Provide the basic functionality to access, search and modify
// these objects.
// For ease of use, there are some convenience global variables for accessing
// objects that are very commonly accessed.
#define OBJECT_COUNT 10
#define BACKGROUND_INDEX 0
#define SPACESHIP_INDEX 1
#define CHARACTER_INDEX 2
#define spaceshipObject (objects + SPACESHIP_INDEX)
#define character (objects + CHARACTER_INDEX)
// The actual container
Object objects[OBJECT_COUNT];
// may return NULL
Object* getFirstOfType(Prototype const* type);
// may return NULL
#define getEmptyObjectSpace() getFirstOfType(NULL)
// Return the number of objects with a prototype being type
uint8_t getCountOf(Prototype const* type);
// Return a reference to a random object intersecting boundingBox and having
// a prototype of type
Object* getIntersectingObjectOfType(Rectangle boundingBox, Prototype const* type);
// Call the tick method of every object
// objects might respond to the elapsed time
void tickObjects(uint8_t previousFrameTime);
// Call the draw method of every object
void drawObjects(Rectangle window);
// Schedule the saving of persistent objects into redundant_storage
// Asteroids are not persistent.
void saveObjects();
// Delete the object given by its address from objects
// It achieves this by setting the object's prototype to NULL.
void clearObject(Object* object);
// Delete every object inside of objects
// and create (or load) the starting objects
void initializeObjectContainer();
#endif

View file

@ -0,0 +1,22 @@
#include "prototype.h"
Prototype temp;
static void loadPrototype(Prototype* prototype) {
/*for (uint8_t i = 0; i < sizeof(prototype); i++) {
((uint8_t*)(&temp))[i] = pgm_read_byte(prototype + i);
}*/
temp = *prototype;
}
void tickObjectFromPrototype(Object* object) {
loadPrototype(object->prototype);
temp.tick(object);
}
void drawObjectFromPrototype(Object* object) {
/*loadPrototype(object->prototype);
temp.draw(object);*/
}

View file

@ -0,0 +1,28 @@
#ifndef PROTOTYPE_H
#define PROTOTYPE_H
#include <avr/io.h>
#include "../util/rectangle/rectangle.h"
// See more information in object.h
struct _object_t;
typedef struct _object_t Object;
// Update the inner state of the given object
// The first argument is the object itself, the second is the elapsed
// time in milliseconds.
typedef void (*TickMethod)(Object*, uint8_t);
// Draw the given object if its overlapping with the given rectangle
typedef void (*DrawMethod)(Object*, Rectangle);
typedef struct {
TickMethod tick;
DrawMethod draw;
Vec2 size;
} Prototype;
#endif

View file

@ -0,0 +1,51 @@
#include "asteroid.h"
#include <avr/pgmspace.h>
#include "../sprites.h"
#include "../../object.h"
#include "../../object_container/object_container.h"
#include "../../../util/vec2/vec2.h"
#include "../../../util/random/random.h"
#include "../../../driver/display/display.h"
bool mineAsteroid(Object* asteroid) {
return ++asteroid->as.asteroid.animationFrame == IDLE_FRAME_COUNT;
}
static void tick(Object* asteroid, uint8_t previousFrameTime) {
if (asteroid->as.asteroid.animationFrame < IDLE_FRAME_COUNT) {
return;
}
if (++asteroid->as.asteroid.timeSinceLastFrameChange == EXPLODING_FRAME_CHANGE_INTERVAL) {
if (++asteroid->as.asteroid.animationFrame >= IDLE_FRAME_COUNT + EXPLODING_FRAME_COUNT) {
clearObject(asteroid);
} else {
asteroid->as.asteroid.timeSinceLastFrameChange = 0;
}
}
}
bool isAsteroidIntersectingWithSpaceship(Object* asteroid, Object* spaceship) {
Rectangle bb = getBoundingBox(asteroid);
startIntersectionTest(bb);
drawObject(asteroid, bb);
drawObject(spaceship, bb);
return endIntersectionTest();
}
static void draw(Object* asteroid, Rectangle __attribute__((unused)) compositingWindow) {
drawBitmapFromProgMem(
getBoundingBox(asteroid),
small_asteroid[asteroid->as.asteroid.animationFrame],
asteroid->position.x % 2
);
}
const Prototype Asteroid PROGMEM = {
.tick = tick,
.draw = draw,
.size = ASTEROID_SIZE,
};

View file

@ -0,0 +1,25 @@
#ifndef ASTEROID_H
#define ASTEROID_H
#include <avr/io.h>
#include <stdbool.h>
#include "../../prototype.h"
#define ASTEROID_SIZE ((Vec2){8, 8})
#define IDLE_FRAME_COUNT 4
#define EXPLODING_FRAME_COUNT 3
#define EXPLODING_FRAME_CHANGE_INTERVAL 3
const Prototype Asteroid;
bool mineAsteroid(Object* asteroid);
bool isAsteroidIntersectingWithSpaceship(Object* asteroid, Object* spaceship);
struct _asteroid_t {
bool isMirrored;
uint8_t timeSinceLastFrameChange;
uint8_t animationFrame;
};
#endif

View file

@ -0,0 +1,145 @@
#include "astronaut.h"
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "bitwise.h"
#include "../../../driver/display/display.h"
#include "../heart/heart.h"
#include "../../object_container/object_container.h"
#include "../sprites.h"
#include "../../../util/vec2/vec2.h"
#include "../../../util/random/random.h"
#include "../../object.h"
#define IS_MIRRORED_BIT 0
#define IS_CONTROLLING_SPACESHIP_BIT 1
#define WAS_DOING_ACTION_BIT 2
static inline bool getIsMirrored(Object* astronaut) {
return getBit(astronaut->as.astronaut.flags, IS_MIRRORED_BIT);
}
static inline void setIsMirrored(Object* astronaut, bool value) {
modifyBit(astronaut->as.astronaut.flags, IS_MIRRORED_BIT, value);
}
static inline bool getWasDoingAction(Object* astronaut) {
return getBit(astronaut->as.astronaut.flags, WAS_DOING_ACTION_BIT);
}
static inline void setWasDoingAction(Object* astronaut, bool value) {
modifyBit(astronaut->as.astronaut.flags, WAS_DOING_ACTION_BIT, value);
}
bool getIsControllingSpaceship(Object* astronaut) {
return getBit(astronaut->as.astronaut.flags, IS_CONTROLLING_SPACESHIP_BIT);
}
static void setIsControllingSpaceship(Object* astronaut, bool value) {
modifyBit(astronaut->as.astronaut.flags, IS_CONTROLLING_SPACESHIP_BIT, value);
}
static inline void applyGravity(Object* astronaut) {
if (!isOnLadder(getBoundingBox(astronaut)) && !isBottomOnFloor(getBoundingBox(astronaut))) {
move(astronaut, directions[south]);
}
}
static void tick(Object* astronaut, uint8_t previousFrameTime) {
if (astronaut->as.astronaut.timeSinceLastAction < TIME_BETWEEN_ACTION_CHANGE) {
astronaut->as.astronaut.timeSinceLastAction += previousFrameTime;
}
applyGravity(astronaut);
}
void moveAstronaut(Object* astronaut, Vec2 direction) {
if (
astronaut->as.astronaut.timeSinceLastAction < TIME_BETWEEN_ACTION_CHANGE
&& !getWasDoingAction(astronaut)
) {
return;
}
astronaut->as.astronaut.timeSinceLastAction = 0;
setWasDoingAction(astronaut, false);
if (getIsControllingSpaceship(astronaut)) {
moveSpaceship(direction);
} else {
Vec2 proposedPosition = add(astronaut->position, direction);
Rectangle proposedBoundingBox = (Rectangle){proposedPosition, getSize(astronaut)};
if (isOnboard(proposedBoundingBox)) {
astronaut->position = proposedPosition;
astronaut->as.astronaut.animationFrame = (astronaut->as.astronaut.animationFrame + 1) % MOVE_FRAME_COUNT;
}
if (direction.x == 0) {
astronaut->as.astronaut.animationFrame = 0;
}
setIsMirrored(astronaut, direction.x < 0);
}
}
void makeAstronautDoAction(Object* astronaut) {
if (
astronaut->as.astronaut.timeSinceLastAction < TIME_BETWEEN_ACTION_CHANGE
&& getWasDoingAction(astronaut)
) {
return;
}
astronaut->as.astronaut.timeSinceLastAction = 0;
setWasDoingAction(astronaut, true);
if (getIsControllingSpaceship(astronaut)) {
setIsControllingSpaceship(astronaut, false);
} else {
Object* heart;
switch (getPossibleActionFromSpaceship(astronaut)) {
case shootTurret:
shootTurretOfSpaceship();
break;
case showLove:
heart = getEmptyObjectSpace();
if (heart != NULL) {
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (
objects[i].prototype == &Astronaut &&
areIntersecting(getBoundingBox(astronaut), getBoundingBox(objects + i)) &&
objects + i != astronaut
) {
createObject(&Heart, heart);
heart->position = add(astronaut->position, (Vec2){(getRandomNumber() % 11) - 5, -(getRandomNumber() % 5) - 10});
break;
}
}
}
break;
case repairingSpaceship:
if (spaceshipObject->as.spaceship.healthLoss > 0) {
spaceshipObject->as.spaceship.healthLoss--;
}
break;
case controllingSpaceship:
setIsControllingSpaceship(astronaut, true);
break;
default:
break;
}
}
}
static void draw(Object* astronaut, __attribute__((unused)) Rectangle compositingWindow) {
drawBitmapFromProgMem(
getBoundingBox(astronaut),
small_character_moving[astronaut->as.astronaut.animationFrame],
getIsMirrored(astronaut)
);
}
const Prototype Astronaut PROGMEM = {
.tick = tick,
.draw = draw,
.size = ASTRONAUT_SIZE
};

View file

@ -0,0 +1,37 @@
#ifndef ASTRONAUT_H
#define ASTRONAUT_H
#include "../../prototype.h"
#include <stdbool.h>
#define ASTRONAUT_SIZE ((Vec2){5, 5})
#define MOVE_FRAME_COUNT 4
// Between two consecutive actions (or movements)
// there has to be at least this many milliseconds
#define TIME_BETWEEN_ACTION_CHANGE 40
typedef enum {
noAction = 0,
controllingSpaceship,
shootTurret,
showLove,
repairingSpaceship,
ACTION_COUNT
} Action;
const Prototype Astronaut;
struct _astronaut_t {
uint8_t flags;
uint8_t animationFrame;
uint8_t timeSinceLastAction;
};
void moveAstronaut(Object* astronaut, Vec2 unitVector);
void makeAstronautDoAction(Object* astronaut);
bool getIsControllingSpaceship(Object* astronaut);
#endif

View file

@ -0,0 +1,71 @@
#include "background.h"
#include <stdbool.h>
#include <avr/pgmspace.h>
#include "../../object.h"
#include "../../../util/rectangle/rectangle.h"
#include "../../../util/random/random.h"
#include "../sprites.h"
#include "../../../driver/display/display.h"
typedef struct {
Vec2 position;
uint8_t type;
} Star;
static Star backgroundStars[STAR_COUNT];
static Star createStarOnTheRight() {
return (Star){
(Vec2){DISPLAY_WIDTH_IN_PIXELS, getRandomNumber() % (DISPLAY_HEIGHT_IN_PIXELS - STAR_SIZE)},
getRandomNumber() % STAR_SHAPE_COUNT
};
}
static void tick(Object* background, uint8_t previousFrameTime) {
background->as.background.movementState++;
for (uint8_t i = 0; i < STAR_COUNT; i++) {
switch (i % 3) {
case 0:
backgroundStars[i].position.x -= 1;
break;
case 1:
backgroundStars[i].position.x -= background->as.background.movementState & 1;
break;
case 2:
backgroundStars[i].position.x -= ~background->as.background.movementState & 1;
break;
}
if (backgroundStars[i].position.x == -STAR_SIZE) {
backgroundStars[i] = createStarOnTheRight();
}
}
}
static void draw(__attribute__((unused)) Object* background, Rectangle compositingWindow) {
for (uint8_t i = 0; i < STAR_COUNT; i++) {
Rectangle starBoundingBox = (Rectangle){backgroundStars[i].position, (Vec2){STAR_SIZE, STAR_SIZE}};
if (areIntersecting(compositingWindow, starBoundingBox)) {
drawBitmapFromProgMem(
starBoundingBox,
stars[backgroundStars[i].type],
false
);
}
}
}
void initializeBackground() {
for (uint8_t i = 0; i < STAR_COUNT; i++) {
backgroundStars[i] = createStarOnTheRight();
backgroundStars[i].position.x = getRandomNumber();
}
}
const Prototype Background PROGMEM = {
.tick = tick,
.draw = draw,
.size = (Vec2){DISPLAY_WIDTH_IN_PIXELS, DISPLAY_HEIGHT_IN_PIXELS} // == WINDOW.size
};

View file

@ -0,0 +1,18 @@
#ifndef BACKGROUND_H
#define BACKGROUND_H
#include "../../prototype.h"
#define STAR_COUNT 8
#define STAR_SIZE 3
#define STAR_SHAPE_COUNT 3
const Prototype Background;
struct _background_t {
uint8_t movementState;
};
void initializeBackground();
#endif

View file

@ -0,0 +1,41 @@
#include "bullet.h"
#include "../asteroid/asteroid.h"
#include "../spaceship/spaceship.h"
#include "../../object.h"
#include "../../object_container/object_container.h"
#include "null.h"
#include "../../../driver/display/display.h"
static void tick(Object* bullet, uint8_t previousFrameTime) {
if (bullet->as.bullet.wereIntersectingInThePreviousFrame) {
clearObject(bullet);
return;
}
move(bullet, directions[east]);
Object* asteroid = getIntersectingObjectOfType(getBoundingBox(bullet), &Asteroid);
if (asteroid != NULL) {
if (mineAsteroid(asteroid) || mineAsteroid(asteroid)) {
onAsteroidMined();
}
bullet->as.bullet.wereIntersectingInThePreviousFrame = true;
}
if (!areIntersecting(getBoundingBox(bullet), WINDOW)) {
bullet->as.bullet.wereIntersectingInThePreviousFrame = true;
}
}
static void draw(Object* bullet, Rectangle __attribute__((unused)) compositingWindow) {
drawFilledRectangle((Rectangle){bullet->position, BULLET_SIZE}, 0, 0xFF);
}
const Prototype Bullet PROGMEM = {
.tick = tick,
.draw = draw,
.size = BULLET_SIZE,
};

View file

@ -0,0 +1,16 @@
#ifndef BULLET_H
#define BULLET_H
#include "../../prototype.h"
#include <stdbool.h>
#define BULLET_SIZE ((Vec2){5, 1})
const Prototype Bullet;
struct _bullet_t {
bool wereIntersectingInThePreviousFrame;
};
#endif

View file

@ -0,0 +1,33 @@
#include "heart.h"
#include <avr/pgmspace.h>
#include "../../../driver/display/display.h"
#include "../sprites.h"
#include "../../object.h"
#include "../../object_container/object_container.h"
static void tick(Object* heart, uint8_t previousFrameTime) {
if (++heart->as.heart.timeSinceLastChange == HEART_ANIMATION_INTERVAL) {
heart->as.heart.animationFrame = (heart->as.heart.animationFrame + 1) % HEART_FRAME_COUNT;
heart->as.heart.timeSinceLastChange = 0;
}
if (++heart->as.heart.timeLived == TIME_TO_LIVE) {
clearObject(heart);
}
}
static void draw(Object* heart, Rectangle __attribute__((unused)) compositingWindow) {
drawBitmapFromProgMem(
getBoundingBox(heart),
heart_blinking[heart->as.heart.animationFrame],
false
);
}
const Prototype Heart PROGMEM = {
.tick = tick,
.draw = draw,
.size = HEART_SIZE,
};

View file

@ -0,0 +1,22 @@
#ifndef HEART_H
#define HEART_H
#include "../../prototype.h"
#define HEART_SIZE ((Vec2){7, 6})
#define TIME_TO_LIVE 128
#define HEART_FRAME_COUNT 2
#define HEART_ANIMATION_INTERVAL 12
const Prototype Heart;
struct _heart_t {
uint8_t animationFrame;
uint8_t timeLived;
uint8_t timeSinceLastChange;
};
#endif

View file

@ -0,0 +1,214 @@
#include "spaceship.h"
#include <avr/pgmspace.h>
#include "../../object.h"
#include "../../../driver/display/display.h"
#include "../astronaut/astronaut.h"
#include "../asteroid/asteroid.h"
#include "../../object_container/object_container.h"
#include "../sprites.h"
#include "../../../util/vec2/vec2.h"
#include "../../../util/random/random.h"
#include "bitwise.h"
static uint8_t flickerState;
SpaceshipPart spaceshipParts[SPACESHIP_PART_COUNT] = {
[TABLE_INDEX] = (SpaceshipPart) {
{{7, 8}, {3, 3}},
table[0],
showLove,
false
},
[BEDS_INDEX] = (SpaceshipPart) {
{{3, 12}, {8, 6}},
beds[0],
repairingSpaceship,
false
},
[COMMAND_PANEL_INDEX] = (SpaceshipPart) {
{{26, 7}, {7, 4}},
NULL,
controllingSpaceship,
true,
},
[TURRET_CONTROLLER_INDEX] = (SpaceshipPart) {
{{26, 12}, {7, 6}},
turret_controller[0],
shootTurret,
false
}
};
bool isOnUpperFloor(Rectangle boundingBox) {
return isInside(boundingBox, translateRectangle(UPPER_FLOOR_BOUNDING_BOX, spaceshipObject->position));
}
bool isOnLowerFloor(Rectangle boundingBox) {
return isInside(boundingBox, translateRectangle(LOWER_FLOOR_BOUNDING_BOX, spaceshipObject->position));
}
bool isBottomOnFloor(Rectangle boundingBox) {
return (
add(spaceshipObject->position, UPPER_FLOOR_BOUNDING_BOX.position).y + UPPER_FLOOR_BOUNDING_BOX.size.y == boundingBox.position.y + boundingBox.size.y ||
add(spaceshipObject->position, LOWER_FLOOR_BOUNDING_BOX.position).y + LOWER_FLOOR_BOUNDING_BOX.size.y == boundingBox.position.y + boundingBox.size.y
);
}
bool isOnLadder(Rectangle boundingBox) {
return areIntersecting(boundingBox, translateRectangle(LADDER_BOUNDING_BOX, spaceshipObject->position));
}
bool isOnboard(Rectangle boundingBox) {
return isOnLowerFloor(boundingBox) || isOnUpperFloor(boundingBox) || isOnLadder(boundingBox);
}
Rectangle getBoundingBoxOfSpaceshipPart(SpaceshipPart* part) {
return translateRectangle(part->boundingBox, spaceshipObject->position);
}
void shootTurretOfSpaceship() {
Object* bullet = getEmptyObjectSpace();
if (getEmptyObjectSpace() != NULL && spaceshipObject->as.spaceship.healthLoss < MAX_HEALTH - 1) {
createObject(&Bullet, bullet);
bullet->position = add(TURRET_POSITION, spaceshipObject->position);
spaceshipObject->as.spaceship.healthLoss++;
}
}
void onAsteroidMined() {
switch (++spaceshipObject->as.spaceship.progress) {
case hasBeds:
setBit(spaceshipObject->as.spaceship.activatedParts, BEDS_INDEX);
break;
case hasTurret:
setBit(spaceshipObject->as.spaceship.activatedParts, TURRET_CONTROLLER_INDEX);
break;
case hasTable:
setBit(spaceshipObject->as.spaceship.activatedParts, TABLE_INDEX);
break;
default:
break;
}
}
void moveSpaceship(Vec2 direction) {
Vec2 proposedPosition = add(spaceshipObject->position, direction);
if (!isInside(translateRectangle(IN_VIEW_BOUNDING_BOX, proposedPosition), WINDOW)) {
return;
}
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (objects[i].prototype == &Astronaut) {
move(objects + i, direction);
}
}
move(spaceshipObject, direction);
spaceshipObject->position = proposedPosition;
for (uint8_t i = 0; i < OBJECT_COUNT; i++) {
if (objects[i].prototype == &Asteroid && isAsteroidIntersectingWithSpaceship(objects + i, spaceshipObject)) {
if (mineAsteroid(objects + i)) {
spaceshipObject->as.spaceship.healthLoss += 2;
onAsteroidMined();
}
}
}
}
Action getPossibleActionFromSpaceship(Object* astronaut) {
for (uint8_t i = 0; i < SPACESHIP_PART_COUNT; i++) {
SpaceshipPart* part = spaceshipParts + i;
if (
isSpaceshipPartActivated(part) && areIntersecting(getBoundingBoxOfSpaceshipPart(part), getBoundingBox(astronaut))) {
return part->possibleAction;
}
}
return noAction;
}
void tick(Object* spaceship, uint8_t previousFrameTime) {
flickerState = !flickerState;
if (spaceship->as.spaceship.healthLoss >= MAX_HEALTH) {
spaceship->as.spaceship.healthLoss++;
}
}
bool isSpaceshipPartActivated(SpaceshipPart* part) {
return part->alwaysActiveDoNotDraw || ((spaceshipObject->as.spaceship.activatedParts >> (part - spaceshipParts)) & 1);
}
static inline void drawSpaceshipHealthBar() {
uint8_t actualBarLength = spaceshipObject->as.spaceship.healthLoss * BAR_LENGTH / MAX_HEALTH;
drawFilledRectangle(
(Rectangle){add(
spaceshipObject->position,
(Vec2){BAR_END_POSITION.x - actualBarLength, BAR_END_POSITION.y}
), (Vec2){actualBarLength, 1}}, 0xFF, 0x00
);
}
static inline void drawSpaceshipParts(Rectangle compositingWindow) {
for (uint8_t i = 0; i < SPACESHIP_PART_COUNT; i++) {
if (
!(spaceshipParts + i)->alwaysActiveDoNotDraw &&
isSpaceshipPartActivated(spaceshipParts + i) &&
areIntersecting(compositingWindow, getBoundingBoxOfSpaceshipPart(spaceshipParts + i))
) {
drawBitmapFromProgMem(
getBoundingBoxOfSpaceshipPart(spaceshipParts + i),
spaceshipParts[i].sprite,
false
);
}
}
}
static inline void drawExhaust(Rectangle compositingWindow) {
Rectangle exhaustRectangle = translateRectangle(EXHAUST_BOUNDING_BOX, spaceshipObject->position);
if (
areIntersecting(compositingWindow, exhaustRectangle) &&
flickerState
) {
drawBitmapFromProgMem(exhaustRectangle, exhaust[0], false);
}
}
static inline void drawGlitches() {
for (uint8_t i = 0; i < spaceshipObject->as.spaceship.healthLoss - MAX_HEALTH; i++) {
Rectangle r = translateRectangle((Rectangle){(Vec2){getRandomNumber() % SPACESHIP_SIZE.x, getRandomNumber() % SPACESHIP_SIZE.y}, (Vec2){8, 8}}, spaceshipObject->position);
if (areIntersecting(r, WINDOW)) {
drawFilledRectangle(r, 0xFF, 0x00);
}
}
}
static void draw(Object* spaceship, Rectangle compositingWindow) {
drawBitmapFromProgMem(
getBoundingBox(spaceship),
spaceship_idle[0],
false
);
drawSpaceshipParts(compositingWindow);
drawSpaceshipHealthBar();
if (spaceship->as.spaceship.healthLoss > MAX_HEALTH) {
drawGlitches();
} else {
drawExhaust(compositingWindow);
}
}
const Prototype Spaceship PROGMEM = {
.tick = tick,
.draw = draw,
.size = SPACESHIP_SIZE,
};

View file

@ -0,0 +1,72 @@
#ifndef SPACESHIP_H
#define SPACESHIP_H
#include "../../prototype.h"
#include "../../../util/rectangle/rectangle.h"
#include "../astronaut/astronaut.h"
#include <stdbool.h>
#define SPACESHIP_SIZE ((Vec2){36, 23})
#define IN_VIEW_BOUNDING_BOX ((Rectangle){(Vec2){7, 4}, (Vec2){22, 15}})
#define UPPER_FLOOR_BOUNDING_BOX ((Rectangle){(Vec2){8, 5}, (Vec2){19, 6}})
#define LOWER_FLOOR_BOUNDING_BOX ((Rectangle){(Vec2){5, 12}, (Vec2){23, 6}})
#define EXHAUST_BOUNDING_BOX ((Rectangle){(Vec2){-4, 9}, (Vec2){5, 5}})
#define TURRET_POSITION ((Vec2){35, 11})
#define LADDER_BOUNDING_BOX ((Rectangle){(Vec2){12, 10}, (Vec2){1, 4}})
#define BOBBING_INTERVAL 130
#define SPACESHIP_PART_COUNT 4
#define TABLE_INDEX 3
#define BEDS_INDEX 2
#define COMMAND_PANEL_INDEX 1
#define TURRET_CONTROLLER_INDEX 0
#define BAR_END_POSITION ((Vec2){33, 11})
#define BAR_LENGTH 4
#define MAX_HEALTH 8
typedef struct {
Rectangle boundingBox;
uint16_t** sprite;
Action possibleAction;
bool alwaysActiveDoNotDraw;
} SpaceshipPart;
SpaceshipPart spaceshipParts[SPACESHIP_PART_COUNT];
const Prototype Spaceship;
typedef enum {
hasBeds = 1,
hasTurret = 3,
hasTable = 5,
hasFullCrew = 9
} Progress;
struct _spaceship_t {
uint8_t healthLoss;
uint8_t progress;
uint8_t activatedParts;
};
bool isOnboard(Rectangle boundingBox);
void moveSpaceship(Vec2 direction);
Rectangle getBoundingBoxOfSpaceshipPart(SpaceshipPart* part);
bool isBottomOnFloor(Rectangle boundingBox);
bool isOnUpperFloor(Rectangle boundingBox);
bool isOnLowerFloor(Rectangle boundingBox);
bool isOnLadder(Rectangle boundingBox);
void onAsteroidMined();
bool isSpaceshipPartActivated(SpaceshipPart* part);
void shootTurretOfSpaceship();
Action getPossibleActionFromSpaceship(Object* astronaut);
#endif

View file

@ -0,0 +1,16 @@
#include "sprites.h"
#include <avr/eeprom.h>
// AUTO-GENERATED
const uint16_t small_character_moving[4][5][1] EEMEM = {{{0x606},{0x1f1d},{0xf0b},{0x1f1d},{0x606}},{{0x606},{0x1f1d},{0xf0b},{0xf0d},{0x1616}},{{0x606},{0x1f1d},{0xf0b},{0x1f1d},{0x606}},{{0x606},{0xf0d},{0x1f1b},{0x1f1d},{0x606}}};
const uint16_t spaceship_idle[1][36][3] EEMEM = {{{0x404,0x1414,0x1010},{0x404,0x3e3e,0x1010},{0xceca,0xffff,0x3828},{0xee6a,0xff8a,0x3929},{0xff3b,0xff09,0x7f6f},{0xff91,0xff08,0x7f44},{0xff51,0xff08,0x7f44},{0xff31,0xff08,0x7f44},{0xff1f,0xff08,0x7f7c},{0xf111,0xff08,0x4744},{0xf010,0xff08,0x704},{0xf010,0xfff8,0x707},{0xf010,0xff28,0x705},{0xf010,0xfff8,0x707},{0xf010,0xff08,0x704},{0xf010,0xff08,0x704},{0xf010,0xff08,0x704},{0xf010,0xff08,0x704},{0xf414,0xff08,0x1714},{0xf414,0xff08,0x1714},{0xfc1c,0xff08,0x1f1c},{0xfc1c,0xff08,0x1f1c},{0xf818,0xff08,0xf0c},{0xf010,0xff08,0x704},{0xf010,0xff08,0x704},{0xf010,0xff08,0x704},{0xf010,0xff0c,0x704},{0xf010,0xff0a,0x704},{0xf0b0,0xff1f,0x706},{0xe020,0xff1c,0x302},{0xe060,0xff1c,0x303},{0xc0c0,0xff9c,0x101},{0x8080,0xffdd,0x0},{0x0,0x7f7f,0x0},{0x0,0x1c1c,0x0},{0x0,0x808,0x0}}};
const uint16_t table[1][3][1] EEMEM = {{{0x707},{0x101},{0x101}}};
const uint16_t exhaust[1][5][1] EEMEM = {{{0x404},{0xe0e},{0xe0e},{0x1f1f},{0x404}}};
const uint16_t small_asteroid[7][8][1] EEMEM = {{{0x1c1c},{0x7e7e},{0xfef2},{0xfffb},{0xffff},{0xffdf},{0x7e7e},{0x3c3c}},{{0x0},{0x3c3c},{0x7e72},{0x7e7a},{0x7e7e},{0x7e5e},{0x3c3c},{0x0}},{{0x0},{0x0},{0x3030},{0x7878},{0x7c7c},{0x7c5c},{0x3838},{0x0}},{{0x0},{0x0},{0x3030},{0x3838},{0x3838},{0x1010},{0x0},{0x0}},{{0x0},{0x3030},{0x4848},{0x4444},{0x4444},{0x2828},{0x1010},{0x0}},{{0x2828},{0x8484},{0x8080},{0x0},{0x8282},{0x4444},{0x2828},{0x0}},{{0x202},{0x0},{0x0},{0x0},{0x0},{0x0},{0x8181},{0x4242}}};
const uint16_t stars[3][3][1] EEMEM = {{{0x202},{0x707},{0x202}},{{0x505},{0x202},{0x505}},{{0x0},{0x303},{0x303}}};
const uint16_t heart_blinking[2][7][1] EEMEM = {{{0x606},{0x909},{0x1111},{0x2222},{0x1111},{0x909},{0x606}},{{0x606},{0xf0f},{0x1f1f},{0x3e3e},{0x1f1f},{0xf0f},{0x606}}};
const uint16_t beds[1][8][1] EEMEM = {{{0x707},{0xc0c},{0x2424},{0x2424},{0x2424},{0x2424},{0x2424},{0x2424}}};
const uint16_t turret_controller[1][7][1] EEMEM = {{{0x3030},{0x808},{0xf0f},{0x101},{0x101},{0x101},{0x101}}};

View file

@ -0,0 +1,19 @@
#ifndef SPRITES_H
#define SPRITES_H
#include <avr/io.h>
// AUTO-GENERATED
const uint16_t small_character_moving[4][5][1];
const uint16_t spaceship_idle[1][36][3];
const uint16_t table[1][3][1];
const uint16_t exhaust[1][5][1];
const uint16_t small_asteroid[7][8][1];
const uint16_t stars[3][3][1];
const uint16_t heart_blinking[2][7][1];
const uint16_t beds[1][8][1];
const uint16_t turret_controller[1][7][1];
#endif

View file

@ -0,0 +1,14 @@
#include "random.h"
static uint16_t currentValue = SEED;
static uint16_t getRandom16bitNumberModuloPrime() {
uint16_t bit = currentValue ^ (currentValue >> 2) ^ (currentValue >> 3) ^ (currentValue >> 5);
currentValue = (currentValue >> 1) | (bit << 15);
return currentValue % 1031;
}
uint8_t getRandomNumber() {
return (uint8_t)(getRandom16bitNumberModuloPrime() ^ getRandom16bitNumberModuloPrime());
}

View file

@ -0,0 +1,14 @@
#ifndef RANDOM_H
#define RANDOM_H
#include <avr/io.h>
// Mustn't be zero, should be lower than 65535
#define SEED 42
// Simple LFSR with some improvements to enhance distribution
// while maintaining short execution time
uint8_t getRandomNumber();
#endif

View file

@ -0,0 +1,34 @@
#include "rectangle.h"
bool areIntersecting(Rectangle r1, Rectangle r2) {
return (
r1.position.x < r2.position.x + r2.size.x &&
r1.position.x + r1.size.x > r2.position.x &&
r1.position.y < r2.position.y + r2.size.y &&
r1.position.y + r1.size.y > r2.position.y
);
}
bool isInside(Rectangle inner, Rectangle outer) {
return (
outer.position.x <= inner.position.x &&
inner.position.x + inner.size.x <= outer.position.x + outer.size.x &&
outer.position.y <= inner.position.y &&
inner.position.y + inner.size.y <= outer.position.y + outer.size.y
);
}
Vec2 getCenter(Rectangle r) {
return (Vec2) {
r.position.x + r.size.x / 2,
r.position.y + r.size.y / 2
};
}
Rectangle translateRectangle(Rectangle r, Vec2 translate) {
return (Rectangle) {
add(r.position, translate),
r.size
};
}

View file

@ -0,0 +1,26 @@
#ifndef RECTANGLE_H
#define RECTANGLE_H
#include <stdbool.h>
#include "../vec2/vec2.h"
typedef struct {
Vec2 position;
Vec2 size;
} Rectangle;
bool areIntersecting(Rectangle r1, Rectangle r2);
// Return true only if inner is fully inside of outer
bool isInside(Rectangle inner, Rectangle outer);
// Return the geometrical middle point of the given rectangle
Vec2 getCenter(Rectangle r);
// Return a new rectangle shifted by vector translate
Rectangle translateRectangle(Rectangle r, Vec2 translate);
#endif

View file

@ -0,0 +1,24 @@
#include "vec2.h"
const Vec2 directions[] = {
[north] = (Vec2){0, -1},
[west] = (Vec2){-1, 0},
[south] = (Vec2){0, 1},
[east] = (Vec2){1, 0}
};
Vec2 add(Vec2 v1, Vec2 v2) {
return (Vec2){v1.x + v2.x, v1.y + v2.y};
}
Vec2 substract(Vec2 v1, Vec2 v2) {
return (Vec2){v1.x - v2.x, v1.y - v2.y};
}
Vec2 clampVec2(Vec2 v) {
return (Vec2){
v.x == 0 ? 0 : (v.x > 0 ? 1 : -1),
v.y == 0 ? 0 : (v.y > 0 ? 1 : -1)
};
}

View file

@ -0,0 +1,26 @@
#ifndef VEC2_H
#define VEC2_H
#include <avr/io.h>
typedef struct {
int8_t x;
int8_t y;
} Vec2;
typedef enum {
north, west, south, east
} Direction;
// The array directions can be indexed by a Direction and
// it contains vectors pointing into that direction.
const Vec2 directions[4];
Vec2 add(Vec2 v1, Vec2 v2);
Vec2 substract(Vec2 v1, Vec2 v2);
// Return new vector with ll components between -1 and 1 (inclusive)
Vec2 clampVec2(Vec2 vector);
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 KiB

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,19 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Atmel Studio Solution File, Format Version 11.00
VisualStudioVersion = 14.0.23107.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "SpaceGame", "SpaceGame\SpaceGame.cproj", "{DCE6C7E3-EE26-4D79-826B-08594B9AD897}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Release|AVR = Release|AVR
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.ActiveCfg = Release|AVR
{DCE6C7E3-EE26-4D79-826B-08594B9AD897}.Release|AVR.Build.0 = Release|AVR
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Store xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="AtmelPackComponentManagement">
<ProjectComponents>
<ProjectComponent z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<CApiVersion></CApiVersion>
<CBundle></CBundle>
<CClass>Device</CClass>
<CGroup>Startup</CGroup>
<CSub></CSub>
<CVariant></CVariant>
<CVendor>Atmel</CVendor>
<CVersion>1.3.0</CVersion>
<DefaultRepoPath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs</DefaultRepoPath>
<DependentComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays" />
<Description></Description>
<Files xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\include</AbsolutePath>
<Attribute></Attribute>
<Category>include</Category>
<Condition>C</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>include</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\include\avr\iotn85.h</AbsolutePath>
<Attribute></Attribute>
<Category>header</Category>
<Condition>C</Condition>
<FileContentHash>RcYmivGpgsCGGCzeWAIjcA==</FileContentHash>
<FileVersion></FileVersion>
<Name>include/avr/iotn85.h</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\templates\main.c</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>9ptzGqB00V1zM0TC00KMag==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.c</Name>
<SelectString>Main file (.c)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\templates\main.cpp</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>YXFphlh0CtZJU+ebktABgQ==</FileContentHash>
<FileVersion></FileVersion>
<Name>templates/main.cpp</Name>
<SelectString>Main file (.cpp)</SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
<d4p1:anyType i:type="FileInfo">
<AbsolutePath>C:/Program Files (x86)\Atmel\Studio\7.0\Packs\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85</AbsolutePath>
<Attribute></Attribute>
<Category>libraryPrefix</Category>
<Condition>GCC</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>gcc/dev/attiny85</Name>
<SelectString></SelectString>
<SourcePath></SourcePath>
</d4p1:anyType>
</Files>
<PackName>ATtiny_DFP</PackName>
<PackPath>C:/Program Files (x86)/Atmel/Studio/7.0/Packs/atmel/ATtiny_DFP/1.3.229/Atmel.ATtiny_DFP.pdsc</PackPath>
<PackVersion>1.3.229</PackVersion>
<PresentInProject>true</PresentInProject>
<ReferenceConditionId>ATtiny85</ReferenceConditionId>
<RteComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:string></d4p1:string>
</RteComponents>
<Status>Resolved</Status>
<VersionMode>Fixed</VersionMode>
<IsComponentInAtProject>true</IsComponentInAtProject>
</ProjectComponent>
</ProjectComponents>
</Store>

View file

@ -0,0 +1,422 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="14.0">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<ProjectVersion>7.0</ProjectVersion>
<ToolchainName>com.Atmel.AVRGCC8.C</ToolchainName>
<ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
<avrdevice>ATtiny85</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>C</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>TestProject</AssemblyName>
<Name>TestProject</Name>
<RootNamespace>TestProject</RootNamespace>
<ToolchainFlavour>Native</ToolchainFlavour>
<KeepTimersRunning>false</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>false</CacheFlash>
<ProgFlashFromRam>true</ProgFlashFromRam>
<RamSnippetAddress>0x20000000</RamSnippetAddress>
<UncachedRange />
<preserveEEPROM>false</preserveEEPROM>
<OverrideVtorValue>exception_table</OverrideVtorValue>
<BootSegment>2</BootSegment>
<ResetRule>0</ResetRule>
<eraseonlaunchrule>0</eraseonlaunchrule>
<EraseKey />
<AsfFrameworkConfig>
<framework-data>
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.47.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
<avrtool>com.atmel.avrdbg.tool.ispmk2</avrtool>
<avrtoolserialnumber>000200212345</avrtoolserialnumber>
<avrdeviceexpectedsignature>0x1E930B</avrdeviceexpectedsignature>
<avrtoolinterface>ISP</avrtoolinterface>
<avrtoolinterfaceclock>125000</avrtoolinterfaceclock>
<com_atmel_avrdbg_tool_ispmk2>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
</InterfaceProperties>
<InterfaceName>ISP</InterfaceName>
</ToolOptions>
<ToolType>com.atmel.avrdbg.tool.ispmk2</ToolType>
<ToolNumber>000200212345</ToolNumber>
<ToolName>AVRISP mkII</ToolName>
</com_atmel_avrdbg_tool_ispmk2>
<com_atmel_avrdbg_tool_simulator>
<ToolOptions xmlns="">
<InterfaceProperties>
</InterfaceProperties>
<InterfaceName>
</InterfaceName>
</ToolOptions>
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
<ToolNumber xmlns="">
</ToolNumber>
<ToolName xmlns="">Simulator</ToolName>
</com_atmel_avrdbg_tool_simulator>
<custom>
<ToolOptions>
<InterfaceProperties>
<IspClock>125000</IspClock>
</InterfaceProperties>
<InterfaceName>
</InterfaceName>
</ToolOptions>
<ToolType>custom</ToolType>
<ToolNumber>
</ToolNumber>
<ToolName>Custom Programming Tool</ToolName>
</custom>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.SubroutinesFunctionPrologues>True</avrgcc.compiler.general.SubroutinesFunctionPrologues>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
<Value>../src/macros</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Undefined>True</avrgcc.compiler.warnings.Undefined>
<avrgcc.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
</AvrGcc>
</ToolchainSettings>
<OutputFileName>space_game</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize (-O1)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
</AvrGcc>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'WithUART' ">
<ToolchainSettings>
<AvrGcc>
<avrgcc.common.Device>-mmcu=attiny85 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\gcc\dev\attiny85"</avrgcc.common.Device>
<avrgcc.common.optimization.RelaxBranches>True</avrgcc.common.optimization.RelaxBranches>
<avrgcc.common.outputfiles.hex>True</avrgcc.common.outputfiles.hex>
<avrgcc.common.outputfiles.lss>True</avrgcc.common.outputfiles.lss>
<avrgcc.common.outputfiles.eep>True</avrgcc.common.outputfiles.eep>
<avrgcc.common.outputfiles.srec>True</avrgcc.common.outputfiles.srec>
<avrgcc.common.outputfiles.usersignatures>False</avrgcc.common.outputfiles.usersignatures>
<avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcc.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcc.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcc.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
<Value>UART_ENABLED</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.compiler.directories.IncludePaths>
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
<avrgcc.compiler.optimization.PackStructureMembers>True</avrgcc.compiler.optimization.PackStructureMembers>
<avrgcc.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcc.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
<avrgcc.compiler.warnings.Undefined>True</avrgcc.compiler.warnings.Undefined>
<avrgcc.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcc.linker.libraries.Libraries>
<avrgcc.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.229\include</Value>
</ListValues>
</avrgcc.assembler.general.IncludePaths>
</AvrGcc>
</ToolchainSettings>
<OutputFileName>space_game</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputPath>bin\WithUART\</OutputPath>
</PropertyGroup>
<ItemGroup>
<Compile Include="src\driver\sleep\sleep.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\uart\receive.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\uart\receive.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\uart\transmit.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\uart\transmit.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\eeprom\eeprom.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\hardware_access.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\hardware_access.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\output_pins\output_pins.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\output_pins\output_pins.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\power_saving\power_saving.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\spi\spi.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\spi\spi.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\timing\timing.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\hardware_access\timing\timing.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\display\display.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\display\display.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\infra\infra.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\infra\infra.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\driver\sleep\sleep.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\macros\bitwise.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\macros\math.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\macros\null.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\main.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\mediator\mediator.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\mediator\mediator.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\ai\ai.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\ai\ai.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\commands\commands.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\commands\commands.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\event_generator\event_generator.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\event_generator\event_generator.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object_container\object_container.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\object_container\object_container.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\prototype.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\asteroid\asteroid.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\asteroid\asteroid.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\astronaut\astronaut.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\astronaut\astronaut.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\background\background.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\background\background.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\bullet\bullet.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\bullet\bullet.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\heart\heart.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\heart\heart.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\spaceship\spaceship.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\spaceship\spaceship.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\sprites.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\objects\types\sprites.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\random\random.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\random\random.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\rectangle\rectangle.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\rectangle\rectangle.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\vec2\vec2.c">
<SubType>compile</SubType>
</Compile>
<Compile Include="src\util\vec2\vec2.h">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="src" />
<Folder Include="src\controller\" />
<Folder Include="src\driver\" />
<Folder Include="src\driver\display\" />
<Folder Include="src\driver\infra\" />
<Folder Include="src\driver\uart" />
<Folder Include="src\driver\sleep\" />
<Folder Include="src\hardware_access\" />
<Folder Include="src\hardware_access\eeprom\" />
<Folder Include="src\hardware_access\output_pins" />
<Folder Include="src\hardware_access\power_saving\" />
<Folder Include="src\hardware_access\spi\" />
<Folder Include="src\hardware_access\timing\" />
<Folder Include="src\macros\" />
<Folder Include="src\mediator\" />
<Folder Include="src\objects\" />
<Folder Include="src\objects\ai\" />
<Folder Include="src\objects\commands\" />
<Folder Include="src\objects\event_generator\" />
<Folder Include="src\objects\object_container\" />
<Folder Include="src\objects\types\" />
<Folder Include="src\objects\types\asteroid\" />
<Folder Include="src\objects\types\astronaut\" />
<Folder Include="src\objects\types\background\" />
<Folder Include="src\objects\types\bullet\" />
<Folder Include="src\objects\types\heart\" />
<Folder Include="src\objects\types\spaceship\" />
<Folder Include="src\util\" />
<Folder Include="src\util\random\" />
<Folder Include="src\util\rectangle\" />
<Folder Include="src\util\vec2\" />
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

View file

@ -0,0 +1,130 @@
#include "display.h"
#include <avr/pgmspace.h>
#include <avr/eeprom.h>
#include "bitwise.h"
#include "math.h"
#include "../../hardware_access/hardware_access.h"
static uint8_t const configuration[] PROGMEM = {
0xD5, 0xF0, // set clock frequency
0x8D, 0x14, // enable charge pump
0x20, 0x00, // horizontal addressing mode
0xD6, 0x01, // 2 times vertical zoom
0x22, 0x00, 0x03, // only draw to the top half of the screen
0xAF // display on
};
static struct {
uint8_t compositingBuffer[DISPLAY_WIDTH_IN_PIXELS];
Rectangle compositingWindow;
DrawFunction drawEverything;
bool wasIntersection;
} display;
static inline void commandMode() {
setOutputPin(DISPLAY_DC_OUTPUT_PIN, false);
}
static inline void dataMode() {
setOutputPin(DISPLAY_DC_OUTPUT_PIN, true);
}
void setDisplayContrast(uint8_t value) {
commandMode();
sendByteOnSPI(0x81);
sendByteOnSPI(value);
dataMode();
}
void initializeDisplay(DrawFunction drawEverything) {
setOutputPin(DISPLAY_RESET_OUTPUT_PIN, false);
for (volatile uint8_t i = 0; i != 255; i++)
;
// some time has to elapse before the next line gets called,
// otherwise the display wont turn on
setOutputPin(DISPLAY_RESET_OUTPUT_PIN, true);
for (uint8_t i = 0; i < sizeof(configuration); i++) {
sendByteOnSPI(pgm_read_byte(configuration + i));
}
display.drawEverything = drawEverything;
setDisplayContrast(255);
dataMode();
}
void startIntersectionTest(Rectangle compositingWindow) {
display.wasIntersection = false;
display.compositingWindow = compositingWindow;
}
bool endIntersectionTest() {
for (uint8_t x = 0; x < DISPLAY_WIDTH_IN_PIXELS; x++) {
display.compositingBuffer[x] = 0;
}
return display.wasIntersection;
}
void drawFrame() {
display.compositingWindow = DEFAULT_COMPOSITING_WINDOW;
for (display.compositingWindow.position.y = 0; display.compositingWindow.position.y < DISPLAY_HEIGHT_IN_PIXELS; display.compositingWindow.position.y += 8) {
display.drawEverything(display.compositingWindow);
for (uint8_t x = 0; x < DISPLAY_WIDTH_IN_PIXELS; x++) {
sendByteOnSPI(display.compositingBuffer[x]);
sendByteOnSPI(display.compositingBuffer[x]);
display.compositingBuffer[x] = 0;
}
}
}
static void compositePixelColumn(uint8_t x, uint8_t invertedMask, uint8_t fill) {
if (display.compositingBuffer[x] & fill) {
display.wasIntersection = true;
}
display.compositingBuffer[x] = (display.compositingBuffer[x] & (~invertedMask)) | fill;
}
void drawBitmapFromProgMem(Rectangle boundingBox, uint16_t const bitmap[boundingBox.size.x][(boundingBox.size.y + 7) / 8], bool isMirrored) {
boundingBox.position = substract(boundingBox.position, display.compositingWindow.position);
uint8_t spriteY = max(0, -boundingBox.position.y);
uint8_t spriteYByte = spriteY >> 3;
for (uint8_t x = max(0, -boundingBox.position.x); x < boundingBox.size.x && boundingBox.position.x + x < DISPLAY_WIDTH_IN_PIXELS; x++) {
uint8_t spriteX = isMirrored ? boundingBox.size.x - x - 1 : x;
uint16_t currentPixelColumn = eeprom_read_word(&bitmap[spriteX][spriteYByte]);
uint8_t fill, invertedMask;
if (boundingBox.position.y >= 0) {
fill = (currentPixelColumn & 0x00FF) << boundingBox.position.y;
invertedMask = currentPixelColumn >> 8 << boundingBox.position.y;
} else {
uint16_t lowerPixelColumn = spriteYByte + 1 < (boundingBox.size.y + 7) / 8 ? eeprom_read_word(&bitmap[spriteX][spriteYByte + 1]) : 0;
uint8_t shift = spriteY % 8;
uint8_t inverseShift = 8 - shift;
fill = ((currentPixelColumn & 0x00FF) >> shift) | ((lowerPixelColumn & 0x0FF) << inverseShift);
invertedMask = (currentPixelColumn >> 8 >> shift) | (lowerPixelColumn >> 8 << inverseShift);
}
compositePixelColumn(boundingBox.position.x + x, invertedMask, fill);
}
}
void drawFilledRectangle(Rectangle box, uint8_t invertedMask, uint8_t fill) {
box.position = substract(box.position, display.compositingWindow.position);
uint8_t upperGapHeight = min(8, max(0, box.position.y));
uint8_t lowerGapHeight = min(8, max(0, 8 - (box.position.y + box.size.y)));
uint8_t actualFill = (fill >> lowerGapHeight) & (fill << upperGapHeight);
uint8_t actualInvertedMask = (invertedMask >> lowerGapHeight) & (invertedMask << upperGapHeight);
for (uint8_t x = max(0, box.position.x); x < box.position.x + box.size.x && x < DISPLAY_WIDTH_IN_PIXELS; x++) {
compositePixelColumn(x, actualInvertedMask, actualFill);
}
}

View file

@ -0,0 +1,35 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <stdbool.h>
#include <avr/io.h>
#include "../../util/rectangle/rectangle.h"
#define DISPLAY_RESET_OUTPUT_PIN PB0
#define DISPLAY_DC_OUTPUT_PIN PB4
#define DISPLAY_WIDTH_IN_PIXELS 64
#define DISPLAY_HEIGHT_IN_PIXELS 32
#define WINDOW ((Rectangle){(Vec2){0, 0}, (Vec2){DISPLAY_WIDTH_IN_PIXELS, DISPLAY_HEIGHT_IN_PIXELS}})
#define DEFAULT_COMPOSITING_WINDOW ((Rectangle){(Vec2){0, 0}, (Vec2){DISPLAY_WIDTH_IN_PIXELS, 8}})
typedef void (*DrawFunction)(Rectangle);
void initializeDisplay(DrawFunction drawEverything);
void setDisplayContrast(uint8_t value);
void startIntersectionTest();
bool endIntersectionTest();
void drawFrame();
void drawBitmapFromProgMem(Rectangle boundingBox, uint16_t const bitmap[boundingBox.size.x][(boundingBox.size.y + 7) / 8], bool isMirrored);
// for white rectangle: invertedMask: don't care, fill: 0xFF
// for black rectangle: invertedMask: 0xFF, fill: 0x00
void drawFilledRectangle(Rectangle box, uint8_t invertedMask, uint8_t fill);
#endif

View file

@ -0,0 +1,146 @@
#include "infra.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include "bitwise.h"
#include "../../hardware_access/hardware_access.h"
#include "../uart/receive.h"
// (0.5625 + (0.5625 + 1.6875) / 2) / 1000 / timer interval
#define MEAN_OF_0_1_BIT_TIMES 53
// 9 / 2 / 1000 / timer interval
#define MAYBE_ONE_CHECK_TIME 141
// some large value
#define TIMEOUT 254
typedef enum {
idle, maybeLeadingOne, leadingOneConfirmed, activeFirstBit, active, timingOut
} ProtocolState;
typedef enum {
noMatch, foundStartingByte, significantByte, waitingForEndOfCommand, waitingForRepeat
} CommandState;
static struct {
uint8_t current;
uint8_t bitPosition;
ProtocolState protocolState;
CommandState commandState;
OnCommandReceived onCommandReceived;
} infra;
static void saveCurrentByte() {
uint8_t byte = infra.current;
infra.current = 0;
infra.bitPosition = 0;
if (byte == INFRA_ADDRESS) {
infra.commandState = foundStartingByte;
return;
}
switch (infra.commandState) {
case foundStartingByte:
infra.commandState = significantByte;
break;
case significantByte:
infra.onCommandReceived(byte);
infra.commandState = waitingForEndOfCommand;
break;
case waitingForEndOfCommand:
if (byte == 0) {
infra.commandState = waitingForRepeat;
}
break;
case waitingForRepeat:
if (byte == 0) {
infra.onCommandReceived(REPEAT_CODE);
}
break;
default:
break;
}
}
static void saveBit(uint8_t bit) {
infra.current <<= 1;
infra.current |= bit;
if (++infra.bitPosition == 8) {
saveCurrentByte();
}
}
static inline uint8_t isIrOff() {
return getBit(PINB, IR_PIN);
}
static inline uint8_t isIrOn() {
return !isIrOff();
}
ISR(PCINT0_vect) {
handlePinChangeForUartReceive();
switch (infra.protocolState) {
case idle:
if (isIrOn()) {
enableTimerB(MAYBE_ONE_CHECK_TIME);
infra.protocolState = maybeLeadingOne;
}
break;
case maybeLeadingOne:
infra.protocolState = idle;
break;
case leadingOneConfirmed:
if (isIrOff()) {
infra.protocolState = activeFirstBit;
}
break;
case activeFirstBit:
case timingOut:
if (isIrOn()) {
infra.protocolState = active;
enableTimerB(MEAN_OF_0_1_BIT_TIMES);
}
break;
case active:
if (isIrOn()) {
saveBit(1);
enableTimerB(MEAN_OF_0_1_BIT_TIMES);
}
break;
}
}
ISR(TIM0_COMPB_vect) {
switch (infra.protocolState) {
case maybeLeadingOne:
if (isIrOn()) {
infra.protocolState = leadingOneConfirmed;
}
disableTimerB();
break;
case active:
saveBit(0);
infra.protocolState = timingOut;
enableTimerB(TIMEOUT);
break;
case timingOut:
infra.protocolState = idle;
saveCurrentByte();
disableTimerB();
break;
default:
disableTimerB();
break;
}
}
void initializeInfra(OnCommandReceived onCommandReceived) {
setBit(PORTB, IR_PIN); // enable pull-up
setBit(PCMSK, IR_PIN); // specific pin change interrupt enable
setBit(GIMSK, PCIE); // global on pin change interrupt enable;
infra.onCommandReceived = onCommandReceived;
}

View file

@ -0,0 +1,16 @@
#ifndef INFRA_H
#define INFRA_H
#include <stdbool.h>
#include <avr/io.h>
#define INFRA_ADDRESS 255
#define IR_PIN PB4
#define REPEAT_CODE 1
typedef void (*OnCommandReceived)(uint8_t);
void initializeInfra(OnCommandReceived onCommandReceived);
#endif

View file

@ -0,0 +1,34 @@
#include "sleep.h"
#include <stdbool.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include "bitwise.h"
#include "../../hardware_access/hardware_access.h"
#define TICKS_IN_MILISECOND 31
volatile int8_t milisecondsSinceFrameStart;
void startFrameLoop(FrameFunction function, uint8_t frameLengthInMilliseconds) {
sleep_enable();
uint8_t previousFrameTime = 0;
while (function(previousFrameTime)) {
previousFrameTime = milisecondsSinceFrameStart;
while (milisecondsSinceFrameStart < frameLengthInMilliseconds) {
sleep_cpu();
}
milisecondsSinceFrameStart = 0;
}
}
ISR(TIM0_COMPA_vect) {
milisecondsSinceFrameStart++;
enableTimerA(TICKS_IN_MILISECOND);
}

View file

@ -0,0 +1,13 @@
#ifndef SLEEP_H
#define SLEEP_H
#include <stdbool.h>
#include <avr/io.h>
typedef bool (*FrameFunction)(uint8_t);
// frameFunction gets previousFrameTime (in milliseconds) as argument
void startFrameLoop(FrameFunction function, uint8_t frameLengthInMilliseconds);
#endif

View file

@ -0,0 +1,49 @@
#include <stdbool.h>
#include <avr/interrupt.h>
#include "receive.h"
#include "bitwise.h"
#include "../../hardware_access/hardware_access.h"
static struct {
uint16_t message;
uint8_t bitPosition; // goes from 0 to 9
bool previousValue;
uint8_t previousTimestamp;
OnCommandReceived onCommandReceived;
} uartReceive = {
.previousValue = true
};
void initializeUartReceive(OnCommandReceived onCommandReceived) {
setBit(PORTB, RECEIVE_PIN); // setup pull-up
setBit(PCMSK, RECEIVE_PIN); // enable interrupt on pin
uartReceive.onCommandReceived = onCommandReceived;
}
void handlePinChangeForUartReceive() {
bool currentValue = getBit(PINB, RECEIVE_PIN);
if (uartReceive.previousValue != currentValue) {
uint8_t elapsedBitCount = (getTimeSince(uartReceive.previousTimestamp) + BIT_TIME / 2) / BIT_TIME;
uartReceive.message >>= elapsedBitCount;
uartReceive.bitPosition += elapsedBitCount;
if (uartReceive.bitPosition == 9) {
uartReceive.onCommandReceived((uint8_t)(uartReceive.message));
uartReceive.bitPosition = 0;
}
if (uartReceive.previousValue == true && currentValue == false) {
if (uartReceive.bitPosition != elapsedBitCount) {
uartReceive.message |= (uint8_t)(0xFF << (8 - elapsedBitCount));
} else {
uartReceive.bitPosition = 0;
}
}
uartReceive.previousTimestamp = getTimestampFromFastTimer();
uartReceive.previousValue = currentValue;
}
}

View file

@ -0,0 +1,15 @@
#ifndef RECEIVE_H
#define RECEIVE_H
// 8*10^6 / 256 / 1200
#define BIT_TIME 26
#define RECEIVE_PIN PB3
typedef void (*OnCommandReceived)(uint8_t);
void initializeUartReceive(OnCommandReceived onCommandReceived);
void handlePinChangeForUartReceive();
#endif

View file

@ -0,0 +1,74 @@
#include "transmit.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include "bitwise.h"
#include "../../hardware_access/hardware_access.h"
static struct {
char bytes[ASYNC_BUFFER_SIZE];
uint8_t start;
uint8_t end;
// 0 - start bit, 1-8 word bits, 9 - end bit
uint8_t currentMaskPosition;
} uartTransmitter;
static inline void send0() {
setOutputPin(UART_OUTPUT_PIN, false);
}
static inline void send1() {
setOutputPin(UART_OUTPUT_PIN, true);
}
ISR(TIM1_COMPA_vect) {
enableFastTimerA(BIT_TIME);
switch(uartTransmitter.currentMaskPosition) {
case 0:
send0();
uartTransmitter.currentMaskPosition++;
break;
case 9:
send1();
uartTransmitter.start = (uartTransmitter.start + 1) % ASYNC_BUFFER_SIZE;
if (uartTransmitter.start == uartTransmitter.end) {
disableFastTimerA();
}
uartTransmitter.currentMaskPosition = 0;
break;
default:
uartTransmitter.bytes[uartTransmitter.start] & BV(uartTransmitter.currentMaskPosition - 1) ? send1() : send0();
uartTransmitter.currentMaskPosition++;
}
}
void sendByteOnUartAsync(char byte) {
cli();
uartTransmitter.bytes[uartTransmitter.end] = byte;
if (uartTransmitter.start == uartTransmitter.end) {
enableFastTimerA(BIT_TIME);
}
uartTransmitter.end = (uartTransmitter.end + 1) % ASYNC_BUFFER_SIZE;
sei();
}
void sendTextOnUartAsync(char text[]) {
for (uint8_t i = 0; text[i]; i++) {
sendByteOnUartAsync(text[i]);
}
}
void sendUintOnUartAsync(uint8_t number) {
sendByteOnUartAsync(number >= 100 ? '0' + number / 100 : ' ');
number %= 100;
sendByteOnUartAsync(number >= 10 ? '0' + number / 10 : ' ');
number %= 10;
sendByteOnUartAsync('0' + number);
}
void initializeUartTransmit() {
send1();
}

View file

@ -0,0 +1,18 @@
#ifndef TRANSMIT_H
#define TRANSMIT_H
#include <avr/io.h>
// 8*10^6 / 256 / 1200
#define BIT_TIME 26
#define ASYNC_BUFFER_SIZE 20
#define UART_OUTPUT_PIN 2
void initializeUartTransmit();
void sendByteOnUartAsync(char byte);
void sendTextOnUartAsync(char text[]);
void sendUintOnUartAsync(uint8_t number);
#endif

View file

@ -0,0 +1,15 @@
#ifndef EEPROM_H
#define EEPROM_H
#include <avr/io.h>
#define STORAGE_SIZE 52
typedef void (*OnEEPROMFinished)(uint8_t*);
inline void initializeEEPROM() {
EECR = 0; // atomic write
}
#endif

View file

@ -0,0 +1,12 @@
#include "hardware_access.h"
#include <avr/interrupt.h>
void initializeHardwareAccess() {
sei();
initializePowerSaving();
initializeSPI();
initializeTiming();
initializeOutputPins();
}

View file

@ -0,0 +1,30 @@
#ifndef HARDWARE_ACCESS_H
#define HARDWARE_ACCESS_H
#include <stdbool.h>
#include <avr/io.h>
#include "bitwise.h"
#include "power_saving/power_saving.h"
#include "spi/spi.h"
#include "eeprom/eeprom.h"
#include "timing/timing.h"
#include "output_pins/output_pins.h"
void initializeHardwareAccess();
void enableTimerA(uint8_t triggerInterruptInXTicks);
void enableTimerB(uint8_t triggerInterruptInXTicks);
void disableTimerB();
void enableFastTimerA(uint8_t triggerInterruptInXTicks);
void disableFastTimerA();
uint8_t getTimestampFromFastTimer();
uint8_t getTimeSince(uint8_t timestamp);
void sendByteOnSPI(uint8_t byte);
void setOutputPin(uint8_t id, bool value);
#endif

View file

@ -0,0 +1,19 @@
#include "shift_register_output_pins.h"
#include "bitwise.h"
#include "../../spi/spi.h"
#include <stdbool.h>
static uint8_t currentValue = 0;
void sendCurrentValue() {
clearBit(PORTB, CLK_ST_PIN);
sendByteOnSPI(currentValue);
setBit(PORTB, CLK_ST_PIN);
}
void setOutputPin(uint8_t id, bool value) {
currentValue = (currentValue & ~BV(id)) | (value & 1) << id;
sendCurrentValue();
}

View file

@ -0,0 +1,18 @@
#ifndef SHIFT_REGITER_OUTPUT_PINS_H
#define SHIFT_REGITER_OUTPUT_PINS_H
#include <avr/io.h>
#include "bitwise.h"
#define CLK_ST_PIN PB0
void sendCurrentValue();
inline void initializeOutputPins() {
setBit(DDRB, CLK_ST_PIN);
setBit(PORTB, CLK_ST_PIN);
sendCurrentValue();
}
#endif

View file

@ -0,0 +1,19 @@
#include "output_pins.h"
#include "bitwise.h"
#include "../spi/spi.h"
#include <stdbool.h>
static uint8_t currentValue = 0;
void sendCurrentValue() {
clearBit(PORTB, CLK_ST_PIN);
sendByteOnSPI(currentValue);
setBit(PORTB, CLK_ST_PIN);
}
void setOutputPin(uint8_t id, bool value) {
currentValue = (currentValue & ~BV(id)) | (value & 1) << id;
sendCurrentValue();
}

Some files were not shown because too many files have changed in this diff Show more