Copy project
This commit is contained in:
parent
ce7a467af7
commit
26a0fd884f
173 changed files with 157458 additions and 1 deletions
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
**/Debug
|
||||
**/Release
|
||||
**/__pycache__
|
||||
**/.idea
|
||||
**/.vs
|
||||
**/bin
|
||||
|
|
@ -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
19
ad_astra/AdAstra.atsln
Normal 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
|
||||
4
ad_astra/AdAstra/AdAstra.componentinfo.xml
Normal file
4
ad_astra/AdAstra/AdAstra.componentinfo.xml
Normal 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>
|
||||
404
ad_astra/AdAstra/AdAstra.cproj
Normal file
404
ad_astra/AdAstra/AdAstra.cproj
Normal 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>
|
||||
86
ad_astra/AdAstra/AdAstra.xml
Normal file
86
ad_astra/AdAstra/AdAstra.xml
Normal 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>
|
||||
129
ad_astra/AdAstra/src/driver/display/display.c
Normal file
129
ad_astra/AdAstra/src/driver/display/display.c
Normal 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);
|
||||
}
|
||||
}
|
||||
34
ad_astra/AdAstra/src/driver/display/display.h
Normal file
34
ad_astra/AdAstra/src/driver/display/display.h
Normal 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
|
||||
144
ad_astra/AdAstra/src/driver/infra/infra.c
Normal file
144
ad_astra/AdAstra/src/driver/infra/infra.c
Normal 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;
|
||||
}
|
||||
16
ad_astra/AdAstra/src/driver/infra/infra.h
Normal file
16
ad_astra/AdAstra/src/driver/infra/infra.h
Normal 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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
34
ad_astra/AdAstra/src/driver/sleep/sleep.c
Normal file
34
ad_astra/AdAstra/src/driver/sleep/sleep.c
Normal 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);
|
||||
}
|
||||
13
ad_astra/AdAstra/src/driver/sleep/sleep.h
Normal file
13
ad_astra/AdAstra/src/driver/sleep/sleep.h
Normal 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
|
||||
75
ad_astra/AdAstra/src/hardware_access/eeprom/eeprom.c
Normal file
75
ad_astra/AdAstra/src/hardware_access/eeprom/eeprom.c
Normal 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);
|
||||
}
|
||||
}
|
||||
15
ad_astra/AdAstra/src/hardware_access/eeprom/eeprom.h
Normal file
15
ad_astra/AdAstra/src/hardware_access/eeprom/eeprom.h
Normal 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
|
||||
13
ad_astra/AdAstra/src/hardware_access/hardware_access.c
Normal file
13
ad_astra/AdAstra/src/hardware_access/hardware_access.c
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#include "hardware_access.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
|
||||
void initializeHardwareAccess() {
|
||||
sei();
|
||||
initializePowerSaving();
|
||||
initializeSPI();
|
||||
initializeEEPROM();
|
||||
initializeTiming();
|
||||
initializeOutputPins();
|
||||
}
|
||||
33
ad_astra/AdAstra/src/hardware_access/hardware_access.h
Normal file
33
ad_astra/AdAstra/src/hardware_access/hardware_access.h
Normal 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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef GPIO_OUTPUT_PINS_H
|
||||
#define GPIO_OUTPUT_PINS_H
|
||||
|
||||
|
||||
inline void initializeOutputPins() {}
|
||||
|
||||
#endif
|
||||
|
|
@ -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
|
||||
30
ad_astra/AdAstra/src/hardware_access/spi/spi.c
Normal file
30
ad_astra/AdAstra/src/hardware_access/spi/spi.c
Normal 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;
|
||||
}
|
||||
17
ad_astra/AdAstra/src/hardware_access/spi/spi.h
Normal file
17
ad_astra/AdAstra/src/hardware_access/spi/spi.h
Normal 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
|
||||
17
ad_astra/AdAstra/src/hardware_access/timing/timing.c
Normal file
17
ad_astra/AdAstra/src/hardware_access/timing/timing.c
Normal 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);
|
||||
}
|
||||
13
ad_astra/AdAstra/src/hardware_access/timing/timing.h
Normal file
13
ad_astra/AdAstra/src/hardware_access/timing/timing.h
Normal 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
|
||||
11
ad_astra/AdAstra/src/macros/bitwise.h
Normal file
11
ad_astra/AdAstra/src/macros/bitwise.h
Normal 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
|
||||
9
ad_astra/AdAstra/src/macros/math.h
Normal file
9
ad_astra/AdAstra/src/macros/math.h
Normal 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
|
||||
3
ad_astra/AdAstra/src/macros/null.h
Normal file
3
ad_astra/AdAstra/src/macros/null.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
14
ad_astra/AdAstra/src/main.c
Normal file
14
ad_astra/AdAstra/src/main.c
Normal 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();
|
||||
}
|
||||
93
ad_astra/AdAstra/src/mediator/mediator.c
Normal file
93
ad_astra/AdAstra/src/mediator/mediator.c
Normal 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);
|
||||
}
|
||||
11
ad_astra/AdAstra/src/mediator/mediator.h
Normal file
11
ad_astra/AdAstra/src/mediator/mediator.h
Normal 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
|
||||
214
ad_astra/AdAstra/src/objects/ai/ai.c
Normal file
214
ad_astra/AdAstra/src/objects/ai/ai.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
8
ad_astra/AdAstra/src/objects/ai/ai.h
Normal file
8
ad_astra/AdAstra/src/objects/ai/ai.h
Normal 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
|
||||
66
ad_astra/AdAstra/src/objects/commands/commands.c
Normal file
66
ad_astra/AdAstra/src/objects/commands/commands.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
34
ad_astra/AdAstra/src/objects/commands/commands.h
Normal file
34
ad_astra/AdAstra/src/objects/commands/commands.h
Normal 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
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -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
|
||||
41
ad_astra/AdAstra/src/objects/object.c
Normal file
41
ad_astra/AdAstra/src/objects/object.c
Normal 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)};
|
||||
}
|
||||
78
ad_astra/AdAstra/src/objects/object.h
Normal file
78
ad_astra/AdAstra/src/objects/object.h
Normal 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
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
22
ad_astra/AdAstra/src/objects/prototype.c
Normal file
22
ad_astra/AdAstra/src/objects/prototype.c
Normal 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);*/
|
||||
}
|
||||
28
ad_astra/AdAstra/src/objects/prototype.h
Normal file
28
ad_astra/AdAstra/src/objects/prototype.h
Normal 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
|
||||
51
ad_astra/AdAstra/src/objects/types/asteroid/asteroid.c
Normal file
51
ad_astra/AdAstra/src/objects/types/asteroid/asteroid.c
Normal 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,
|
||||
};
|
||||
25
ad_astra/AdAstra/src/objects/types/asteroid/asteroid.h
Normal file
25
ad_astra/AdAstra/src/objects/types/asteroid/asteroid.h
Normal 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
|
||||
145
ad_astra/AdAstra/src/objects/types/astronaut/astronaut.c
Normal file
145
ad_astra/AdAstra/src/objects/types/astronaut/astronaut.c
Normal 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
|
||||
};
|
||||
37
ad_astra/AdAstra/src/objects/types/astronaut/astronaut.h
Normal file
37
ad_astra/AdAstra/src/objects/types/astronaut/astronaut.h
Normal 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
|
||||
71
ad_astra/AdAstra/src/objects/types/background/background.c
Normal file
71
ad_astra/AdAstra/src/objects/types/background/background.c
Normal 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
|
||||
};
|
||||
18
ad_astra/AdAstra/src/objects/types/background/background.h
Normal file
18
ad_astra/AdAstra/src/objects/types/background/background.h
Normal 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
|
||||
41
ad_astra/AdAstra/src/objects/types/bullet/bullet.c
Normal file
41
ad_astra/AdAstra/src/objects/types/bullet/bullet.c
Normal 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,
|
||||
};
|
||||
16
ad_astra/AdAstra/src/objects/types/bullet/bullet.h
Normal file
16
ad_astra/AdAstra/src/objects/types/bullet/bullet.h
Normal 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
|
||||
33
ad_astra/AdAstra/src/objects/types/heart/heart.c
Normal file
33
ad_astra/AdAstra/src/objects/types/heart/heart.c
Normal 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,
|
||||
};
|
||||
22
ad_astra/AdAstra/src/objects/types/heart/heart.h
Normal file
22
ad_astra/AdAstra/src/objects/types/heart/heart.h
Normal 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
|
||||
214
ad_astra/AdAstra/src/objects/types/spaceship/spaceship.c
Normal file
214
ad_astra/AdAstra/src/objects/types/spaceship/spaceship.c
Normal 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,
|
||||
};
|
||||
72
ad_astra/AdAstra/src/objects/types/spaceship/spaceship.h
Normal file
72
ad_astra/AdAstra/src/objects/types/spaceship/spaceship.h
Normal 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
|
||||
16
ad_astra/AdAstra/src/objects/types/sprites.c
Normal file
16
ad_astra/AdAstra/src/objects/types/sprites.c
Normal 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}}};
|
||||
19
ad_astra/AdAstra/src/objects/types/sprites.h
Normal file
19
ad_astra/AdAstra/src/objects/types/sprites.h
Normal 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
|
||||
14
ad_astra/AdAstra/src/util/random/random.c
Normal file
14
ad_astra/AdAstra/src/util/random/random.c
Normal 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());
|
||||
}
|
||||
14
ad_astra/AdAstra/src/util/random/random.h
Normal file
14
ad_astra/AdAstra/src/util/random/random.h
Normal 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
|
||||
34
ad_astra/AdAstra/src/util/rectangle/rectangle.c
Normal file
34
ad_astra/AdAstra/src/util/rectangle/rectangle.c
Normal 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
|
||||
};
|
||||
}
|
||||
26
ad_astra/AdAstra/src/util/rectangle/rectangle.h
Normal file
26
ad_astra/AdAstra/src/util/rectangle/rectangle.h
Normal 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
|
||||
24
ad_astra/AdAstra/src/util/vec2/vec2.c
Normal file
24
ad_astra/AdAstra/src/util/vec2/vec2.c
Normal 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)
|
||||
};
|
||||
}
|
||||
26
ad_astra/AdAstra/src/util/vec2/vec2.h
Normal file
26
ad_astra/AdAstra/src/util/vec2/vec2.h
Normal 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
|
||||
BIN
docs/datasheets/2N7000-D.PDF
Normal file
BIN
docs/datasheets/2N7000-D.PDF
Normal file
Binary file not shown.
BIN
docs/datasheets/74HC595_EN_10021551.pdf
Normal file
BIN
docs/datasheets/74HC595_EN_10021551.pdf
Normal file
Binary file not shown.
BIN
docs/datasheets/ATTINY85V-10PU_EN_10028798.pdf
Normal file
BIN
docs/datasheets/ATTINY85V-10PU_EN_10028798.pdf
Normal file
Binary file not shown.
BIN
docs/datasheets/D096-12864-SPI6_EN_10035551.pdf
Normal file
BIN
docs/datasheets/D096-12864-SPI6_EN_10035551.pdf
Normal file
Binary file not shown.
BIN
docs/datasheets/LD1117V33LD33V_EN_10026083.pdf
Normal file
BIN
docs/datasheets/LD1117V33LD33V_EN_10026083.pdf
Normal file
Binary file not shown.
BIN
docs/datasheets/TSOP4838_EN_10033222.pdf
Normal file
BIN
docs/datasheets/TSOP4838_EN_10033222.pdf
Normal file
Binary file not shown.
BIN
docs/datasheets/avr-libc-user-manual-2.0.0.pdf
Normal file
BIN
docs/datasheets/avr-libc-user-manual-2.0.0.pdf
Normal file
Binary file not shown.
BIN
docs/konzultáció-1/03-02-2020-1930.21.jpg
Normal file
BIN
docs/konzultáció-1/03-02-2020-1930.21.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 988 KiB |
BIN
docs/konzultáció-1/SchmelczerAndras_HF.pdf
Normal file
BIN
docs/konzultáció-1/SchmelczerAndras_HF.pdf
Normal file
Binary file not shown.
147759
docs/konzultáció-1/SchmelczerAndras_HF.rtf
Normal file
147759
docs/konzultáció-1/SchmelczerAndras_HF.rtf
Normal file
File diff suppressed because it is too large
Load diff
BIN
docs/konzultáció-1/datasheets/2N7000-D.PDF
Normal file
BIN
docs/konzultáció-1/datasheets/2N7000-D.PDF
Normal file
Binary file not shown.
BIN
docs/konzultáció-1/datasheets/74HC595_EN_10021551.pdf
Normal file
BIN
docs/konzultáció-1/datasheets/74HC595_EN_10021551.pdf
Normal file
Binary file not shown.
BIN
docs/konzultáció-1/datasheets/ATTINY85V-10PU_EN_10028798.pdf
Normal file
BIN
docs/konzultáció-1/datasheets/ATTINY85V-10PU_EN_10028798.pdf
Normal file
Binary file not shown.
BIN
docs/konzultáció-1/datasheets/D096-12864-SPI6_EN_10035551.pdf
Normal file
BIN
docs/konzultáció-1/datasheets/D096-12864-SPI6_EN_10035551.pdf
Normal file
Binary file not shown.
BIN
docs/konzultáció-1/datasheets/TSOP4838_EN_10033222.pdf
Normal file
BIN
docs/konzultáció-1/datasheets/TSOP4838_EN_10033222.pdf
Normal file
Binary file not shown.
BIN
docs/konzultáció-2/architecture.pdf
Normal file
BIN
docs/konzultáció-2/architecture.pdf
Normal file
Binary file not shown.
BIN
docs/konzultáció-2/architektúra.docx
Normal file
BIN
docs/konzultáció-2/architektúra.docx
Normal file
Binary file not shown.
3403
docs/konzultáció-2/schematic.pdf
Normal file
3403
docs/konzultáció-2/schematic.pdf
Normal file
File diff suppressed because it is too large
Load diff
19
space_game/SpaceGame.atsln
Normal file
19
space_game/SpaceGame.atsln
Normal 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
|
||||
86
space_game/SpaceGame/SpaceGame.componentinfo.xml
Normal file
86
space_game/SpaceGame/SpaceGame.componentinfo.xml
Normal 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>
|
||||
422
space_game/SpaceGame/SpaceGame.cproj
Normal file
422
space_game/SpaceGame/SpaceGame.cproj
Normal 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>
|
||||
130
space_game/SpaceGame/src/driver/display/display.c
Normal file
130
space_game/SpaceGame/src/driver/display/display.c
Normal 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);
|
||||
}
|
||||
}
|
||||
35
space_game/SpaceGame/src/driver/display/display.h
Normal file
35
space_game/SpaceGame/src/driver/display/display.h
Normal 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
|
||||
146
space_game/SpaceGame/src/driver/infra/infra.c
Normal file
146
space_game/SpaceGame/src/driver/infra/infra.c
Normal 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;
|
||||
}
|
||||
16
space_game/SpaceGame/src/driver/infra/infra.h
Normal file
16
space_game/SpaceGame/src/driver/infra/infra.h
Normal 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
|
||||
34
space_game/SpaceGame/src/driver/sleep/sleep.c
Normal file
34
space_game/SpaceGame/src/driver/sleep/sleep.c
Normal 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);
|
||||
}
|
||||
13
space_game/SpaceGame/src/driver/sleep/sleep.h
Normal file
13
space_game/SpaceGame/src/driver/sleep/sleep.h
Normal 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
|
||||
49
space_game/SpaceGame/src/driver/uart/receive.c
Normal file
49
space_game/SpaceGame/src/driver/uart/receive.c
Normal 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;
|
||||
}
|
||||
}
|
||||
15
space_game/SpaceGame/src/driver/uart/receive.h
Normal file
15
space_game/SpaceGame/src/driver/uart/receive.h
Normal 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
|
||||
74
space_game/SpaceGame/src/driver/uart/transmit.c
Normal file
74
space_game/SpaceGame/src/driver/uart/transmit.c
Normal 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();
|
||||
}
|
||||
18
space_game/SpaceGame/src/driver/uart/transmit.h
Normal file
18
space_game/SpaceGame/src/driver/uart/transmit.h
Normal 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
|
||||
15
space_game/SpaceGame/src/hardware_access/eeprom/eeprom.h
Normal file
15
space_game/SpaceGame/src/hardware_access/eeprom/eeprom.h
Normal 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
|
||||
12
space_game/SpaceGame/src/hardware_access/hardware_access.c
Normal file
12
space_game/SpaceGame/src/hardware_access/hardware_access.c
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#include "hardware_access.h"
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
|
||||
void initializeHardwareAccess() {
|
||||
sei();
|
||||
initializePowerSaving();
|
||||
initializeSPI();
|
||||
initializeTiming();
|
||||
initializeOutputPins();
|
||||
}
|
||||
30
space_game/SpaceGame/src/hardware_access/hardware_access.h
Normal file
30
space_game/SpaceGame/src/hardware_access/hardware_access.h
Normal 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
|
||||
19
space_game/SpaceGame/src/hardware_access/output_pins.c
Normal file
19
space_game/SpaceGame/src/hardware_access/output_pins.c
Normal 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();
|
||||
}
|
||||
18
space_game/SpaceGame/src/hardware_access/output_pins.h
Normal file
18
space_game/SpaceGame/src/hardware_access/output_pins.h
Normal 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
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue