migrate code to AS7, including fucked up arduino import

arduino as a library will not build with -flto. I can't figure it out. so we
waste some space compared to what platformio was building. oh well. there's
still over 1K of space left for programs.
This commit is contained in:
true
2025-04-23 01:42:39 -07:00
parent 1c34e1228f
commit 70b9fe0dd6
96 changed files with 23755 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Store xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="AtmelPackComponentManagement">
<ProjectComponents>
<ProjectComponent z:Id="i1" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<CApiVersion></CApiVersion>
<CBundle></CBundle>
<CClass>Device</CClass>
<CGroup>Startup</CGroup>
<CSub></CSub>
<CVariant></CVariant>
<CVendor>Atmel</CVendor>
<CVersion>1.10.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.10.348\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.10.348\include\avr\iotn402.h</AbsolutePath>
<Attribute></Attribute>
<Category>header</Category>
<Condition>C</Condition>
<FileContentHash>g0XngzH9uwBI0kp8K6DswA==</FileContentHash>
<FileVersion></FileVersion>
<Name>include/avr/iotn402.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.10.348\templates\main.c</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>KjvOcFWd++tbnsEMfVPd/w==</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.10.348\templates\main.cpp</AbsolutePath>
<Attribute>template</Attribute>
<Category>source</Category>
<Condition>C Exe</Condition>
<FileContentHash>uK6xwpZG+RPPFiJUJnueCQ==</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.10.348\gcc\dev\attiny402</AbsolutePath>
<Attribute></Attribute>
<Category>libraryPrefix</Category>
<Condition>GCC</Condition>
<FileContentHash i:nil="true" />
<FileVersion></FileVersion>
<Name>gcc/dev/attiny402</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.10.348/Atmel.ATtiny_DFP.pdsc</PackPath>
<PackVersion>1.10.348</PackVersion>
<PresentInProject>true</PresentInProject>
<ReferenceConditionId>ATtiny402</ReferenceConditionId>
<RteComponents xmlns:d4p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<d4p1:string></d4p1:string>
</RteComponents>
<Status>Resolved</Status>
<VersionMode>Fixed</VersionMode>
<IsComponentInAtProject>true</IsComponentInAtProject>
</ProjectComponent>
</ProjectComponents>
</Store>

View File

@@ -0,0 +1,226 @@
<?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.CPP</ToolchainName>
<ProjectGuid>dce6c7e3-ee26-4d79-826b-08594b9ad897</ProjectGuid>
<avrdevice>ATtiny402</avrdevice>
<avrdeviceseries>none</avrdeviceseries>
<OutputType>Executable</OutputType>
<Language>CPP</Language>
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
<OutputFileExtension>.elf</OutputFileExtension>
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
<AssemblyName>HackSpaceCon_AS7</AssemblyName>
<Name>HSC_Wand</Name>
<RootNamespace>HackSpaceCon_AS7</RootNamespace>
<ToolchainFlavour>Native</ToolchainFlavour>
<KeepTimersRunning>true</KeepTimersRunning>
<OverrideVtor>false</OverrideVtor>
<CacheFlash>true</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 xmlns="">
<options />
<configurations />
<files />
<documentation help="" />
<offline-documentation help="" />
<dependencies>
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.52.0" />
</dependencies>
</framework-data>
</AsfFrameworkConfig>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=attiny402 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402"</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>NDEBUG</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\</Value>
<Value>..\include\libraries\EEPROM\src</Value>
<Value>..\include\libraries\Event\src</Value>
<Value>..\include\libraries\Logic\src</Value>
<Value>..\include\libraries\megaTinyCore\examples\TuningSource</Value>
<Value>..\include\libraries\megaTinyCore\src</Value>
<Value>..\include\libraries\SoftwareSerial\src</Value>
<Value>..\include\libraries\SPI\src</Value>
<Value>..\include\libraries\tinyNeoPixel</Value>
<Value>..\include\libraries\tinyNeoPixel_Static</Value>
<Value>..\include\libraries\Wire\src</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>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>NDEBUG</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\</Value>
<Value>..\include\libraries\EEPROM\src</Value>
<Value>..\include\libraries\Event\src</Value>
<Value>..\include\libraries\Logic\src</Value>
<Value>..\include\libraries\megaTinyCore\examples\TuningSource</Value>
<Value>..\include\libraries\megaTinyCore\src</Value>
<Value>..\include\libraries\SoftwareSerial\src</Value>
<Value>..\include\libraries\SPI\src</Value>
<Value>..\include\libraries\tinyNeoPixel</Value>
<Value>..\include\libraries\tinyNeoPixel_Static</Value>
<Value>..\include\libraries\Wire\src</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.warnings.AllWarnings>True</avrgcccpp.compiler.warnings.AllWarnings>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<ToolchainSettings>
<AvrGccCpp>
<avrgcc.common.Device>-mmcu=attiny402 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\gcc\dev\attiny402"</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>DEBUG</Value>
<Value>ARDUINO=108019</Value>
</ListValues>
</avrgcc.compiler.symbols.DefSymbols>
<avrgcc.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\</Value>
<Value>../../Arduino/megatinycore</Value>
<Value>../../Arduino/variants/txy2</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.optimization.DebugLevel>Default (-g2)</avrgcc.compiler.optimization.DebugLevel>
<avrgcc.compiler.warnings.AllWarnings>True</avrgcc.compiler.warnings.AllWarnings>
<avrgcc.compiler.miscellaneous.OtherFlags>-std=gnu11</avrgcc.compiler.miscellaneous.OtherFlags>
<avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultCharTypeUnsigned>
<avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>True</avrgcccpp.compiler.general.ChangeDefaultBitFieldUnsigned>
<avrgcccpp.compiler.symbols.DefSymbols>
<ListValues>
<Value>DEBUG</Value>
<Value>ARDUINO=108019</Value>
<Value>ARDUINO_AVR_ATtinyxy4</Value>
<Value>ARDUINO_attinyxy4</Value>
<Value>F_CPU=8000000UL</Value>
<Value>MEGATINYCORE="2.6.10"</Value>
<Value>MEGATINYCORE_MAJOR=2UL</Value>
<Value>MEGATINYCORE_MINOR=6UL</Value>
<Value>MEGATINYCORE_PATCH=10UL</Value>
<Value>MEGATINYCORE_RELEASED=1</Value>
<Value>MILLIS_USE_TIMERA0</Value>
<Value>CLOCK_SOURCE=0</Value>
<Value>TWI_MORS</Value>
</ListValues>
</avrgcccpp.compiler.symbols.DefSymbols>
<avrgcccpp.compiler.directories.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\</Value>
<Value>../../Arduino/megatinycore</Value>
<Value>../../Arduino/variants/txy2</Value>
<Value>../../Arduino/arduino_libraries/tinyNeoPixel_static</Value>
</ListValues>
</avrgcccpp.compiler.directories.IncludePaths>
<avrgcccpp.compiler.optimization.level>Optimize for size (-Os)</avrgcccpp.compiler.optimization.level>
<avrgcccpp.compiler.optimization.OtherFlags>-flto -fno-threadsafe-statics</avrgcccpp.compiler.optimization.OtherFlags>
<avrgcccpp.compiler.optimization.PackStructureMembers>True</avrgcccpp.compiler.optimization.PackStructureMembers>
<avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>True</avrgcccpp.compiler.optimization.AllocateBytesNeededForEnum>
<avrgcccpp.compiler.optimization.DebugLevel>Default (-g2)</avrgcccpp.compiler.optimization.DebugLevel>
<avrgcccpp.compiler.warnings.InhibitAllWarnings>True</avrgcccpp.compiler.warnings.InhibitAllWarnings>
<avrgcccpp.compiler.miscellaneous.OtherFlags>-std=gnu++17</avrgcccpp.compiler.miscellaneous.OtherFlags>
<avrgcccpp.linker.libraries.Libraries>
<ListValues>
<Value>libm</Value>
</ListValues>
</avrgcccpp.linker.libraries.Libraries>
<avrgcccpp.linker.miscellaneous.LinkerFlags>-Os -fuse-linker-plugin</avrgcccpp.linker.miscellaneous.LinkerFlags>
<avrgcccpp.assembler.general.IncludePaths>
<ListValues>
<Value>%24(PackRepoDir)\atmel\ATtiny_DFP\1.10.348\include\</Value>
</ListValues>
</avrgcccpp.assembler.general.IncludePaths>
<avrgcccpp.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcccpp.assembler.debugging.DebugLevel>
</AvrGccCpp>
</ToolchainSettings>
</PropertyGroup>
<ItemGroup>
<Compile Include="hsv2rgb.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="hsv2rgb.h">
<SubType>compile</SubType>
</Compile>
<Compile Include="isr.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="wand_program.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="rgbled.cpp">
<SubType>compile</SubType>
</Compile>
<Compile Include="rgbled.h">
<SubType>compile</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Arduino\Arduino.cppproj">
<Name>Arduino</Name>
<Project>{47694d30-4990-4f03-a1f7-e94eb79783f0}</Project>
<Private>True</Private>
</ProjectReference>
</ItemGroup>
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
</Project>

View File

@@ -0,0 +1,177 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 B. Stultiens
* modified by true for 12-bit values
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#include "hsv2rgb.h"
/*
void hsv2rgb_8b(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b)
{
uint8_t sextant;
uint8_t bb;
uint16_t ww;
uint8_t h_fraction;
if (!(s)) {
*(r) = *(g) = *(b) = (v);
return;
}
sextant = h >> 8;
HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space
HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in
*g = v; // Top level
// Perform actual calculations
// Bottom level: v * (1.0 - s)
// --> (v * (255 - s) + error_corr) / 256
bb = ~s;
ww = v * bb;
ww += 1; // Error correction
ww += ww >> 8; // Error correction
*b = ww >> 8;
h_fraction = h & 0xff; // 0...255
if(!(sextant & 1)) {
// *r = ...slope_up...;
// Slope up: v * (1.0 - s * (1.0 - h))
// --> (v * (255 - (s * (256 - h) + error_corr1) / 256) + error_corr2) / 256
ww = !h_fraction ? ((uint16_t)s << 8) : (s * (uint8_t)(-h_fraction));
ww += ww >> 8; // Error correction 1
bb = ww >> 8;
bb = ~bb;
ww = v * bb;
ww += v >> 1; // Error correction 2
*r = ww >> 8;
} else {
// *r = ...slope_down...;
// Slope down: v * (1.0 - s * h)
// --> (v * (255 - (s * h + error_corr1) / 256) + error_corr2) / 256
ww = s * h_fraction;
ww += ww >> 8; // Error correction 1
bb = ww >> 8;
bb = ~bb;
ww = v * bb;
ww += v >> 1; // Error correction 2
*r = ww >> 8;
// A perfect match for h_fraction == 0 implies:
// *r = (ww >> 8) + (h_fraction ? 0 : 1)
// However, this is an extra calculation that may not be required.
}
}
*/
void hsv2rgb_32b_8(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b)
{
HSV_MONOCHROMATIC_TEST(s, v, r, g, b); // Exit with grayscale if s == 0
uint8_t sextant = h >> 8;
HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space
HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in
*g = v; // Top level
// Perform actual calculations
// Bottom level: v * (1.0 - s)
// --> (v * (255 - s) + error_corr + 1) / 256
uint16_t ww; // Intermediate result
ww = v * (255 - s); // We don't use ~s to prevent size-promotion side effects
ww += 1; // Error correction
ww += ww >> 8; // Error correction
*b = ww >> 8;
uint8_t h_fraction = h & 0xff; // 0...255
uint32_t d; // Intermediate result
if(!(sextant & 1)) {
// *r = ...slope_up...;
d = v * (uint32_t)((255 << 8) - (uint16_t)(s * (256 - h_fraction)));
d += d >> 8; // Error correction
d += v; // Error correction
*r = d >> 16;
} else {
// *r = ...slope_down...;
d = v * (uint32_t)((255 << 8) - (uint16_t)(s * h_fraction));
d += d >> 8; // Error correction
d += v; // Error correction
*r = d >> 16;
}
}
/*
void hsv2rgb_32b_16(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b)
{
HSV_MONOCHROMATIC_TEST(s, v, r, g, b); // Exit with grayscale if s == 0
uint8_t sextant = h >> 8;
HSV_SEXTANT_TEST(sextant); // Optional: Limit hue sextants to defined space
HSV_POINTER_SWAP(sextant, r, g, b); // Swap pointers depending which sextant we are in
*g = v; // Top level
// Bottom level: v * (1.0 - s)
// --> (v * (255 - s) + error_corr + 1) / 256
uint16_t ww; // Intermediate result
ww = v * (255 - s); // We don't use ~s to prevent size-promotion side effects
ww += 1; // Error correction
ww += ww >> 8; // Error correction
*b = ww >> 8;
uint8_t h_fraction = h & 0xff; // 0...255
uint32_t d; // Intermediate result
if(!(sextant & 1)) {
// *r = ...slope_up...;
d = v * (uint32_t)((255 << 8) - (uint16_t)(s * (256 - h_fraction)));
d += d >> 8; // Error correction
d += v; // Error correction
*r = d >> 16;
} else {
// *r = ...slope_down...;
d = v * (uint32_t)((255 << 8) - (uint16_t)(s * h_fraction));
d += d >> 8; // Error correction
d += v; // Error correction
*r = d >> 16;
}
}
*/

View File

@@ -0,0 +1,132 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 B. Stultiens
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef __HSV2RGB_H__
#define __HSV2RGB_H__
#include <stdint.h>
typedef struct color_rgb {
uint16_t r;
uint16_t g;
uint16_t b;
} color_rgb;
typedef struct color_hsv {
uint16_t h;
uint16_t s;
uint16_t v;
} color_hsv;
#define HSV2RGB_BITS 8 // 10
#define HSV2RGB_COUNT ((1 < HSV2RGB_BITS)-1)
#define HSV_HUE_SEXTANT (1 << HSV2RGB_BITS)
#define HSV_HUE_STEPS (6 * HSV_HUE_SEXTANT)
#define HSV_HUE_MIN 0
#define HSV_HUE_MAX (HSV_HUE_STEPS - 1)
#define HSV_SAT_MIN 0
#define HSV_SAT_MAX 255
#define HSV_VAL_MIN 0
#define HSV_VAL_MAX 255
/* Options: */
#define HSV_USE_SEXTANT_TEST /* Limit the hue to 0...360 degrees */
#define hsv2rgb(h,s,v,r,g,b) hsv2rgb_32b_8(h,s,v,r,g,b)
//void hsv2rgb_8b(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b);
void hsv2rgb_32b_8(uint16_t h, uint8_t s, uint8_t v, uint8_t *r, uint8_t *g , uint8_t *b);
//void hsv2rgb_32b_16(uint16_t h, uint16_t s, uint16_t v, uint16_t *r, uint16_t *g , uint16_t *b);
/*
* Macros that are common to all implementations
*/
#ifdef HSV_USE_SEXTANT_TEST
#define HSV_SEXTANT_TEST(sextant) \
if((sextant) > 5) { \
(sextant) = 5; \
}
#else
#define HSV_SEXTANT_TEST(sextant)
#endif
/*
* Pointer swapping:
* sext. r g b r<>b g<>b r <> g result
* 0 0 0 v u c !u v c u v c
* 0 0 1 d v c d v c
* 0 1 0 c v u u v c u v c
* 0 1 1 c d v v d c d v c d v c
* 1 0 0 u c v u v c u v c
* 1 0 1 v c d v d c d v c d v c
*
* if(sextant & 2)
* r <-> b
*
* if(sextant & 4)
* g <-> b
*
* if(!(sextant & 6) {
* if(!(sextant & 1))
* r <-> g
* } else {
* if(sextant & 1)
* r <-> g
* }
*/
#define HSV_SWAPPTR(a,b) do { uint8_t *tmp = (a); (a) = (b); (b) = tmp; } while(0)
//#define HSV_SWAPPTR(a,b) do { uint16_t *tmp = (a); (a) = (b); (b) = tmp; } while(0)
#define HSV_POINTER_SWAP(sextant,r,g,b) \
do { \
if((sextant) & 2) { \
HSV_SWAPPTR((r), (b)); \
} \
if((sextant) & 4) { \
HSV_SWAPPTR((g), (b)); \
} \
if(!((sextant) & 6)) { \
if(!((sextant) & 1)) { \
HSV_SWAPPTR((r), (g)); \
} \
} else { \
if((sextant) & 1) { \
HSV_SWAPPTR((r), (g)); \
} \
} \
} while(0)
#define HSV_MONOCHROMATIC_TEST(s,v,r,g,b) \
do { \
if(!(s)) { \
*(r) = *(g) = *(b) = (v); \
return; \
} \
} while(0)
#endif

View File

@@ -0,0 +1,43 @@
/*
hackspacecon wand firmware
interrupt routines
*/
#include <Arduino.h>
#include "rgbled.h"
extern uint8_t run_rgbprog;
// TCB0 general interrupt
ISR(TCB0_INT_vect)
{
uint8_t intflags = TCB0.INTFLAGS;
// in this program, this interrupt is only used for timing.
// we'll now return to executing loop()
// reset the INTFLAGS - necessary on this series
TCB0.INTFLAGS = intflags;
}
// button interrupt
ISR(PORTA_PORT_vect)
{
uint8_t intflags = PORTA.INTFLAGS;
// shitty debounce; this is bad practice
delay(5);
// was our pin changed?
if (intflags & PIN3_bm) {
// start or re-start running a program
run_rgbprog = 1; // run a new program
}
// reset the INTFLAGS - necessary on this series
PORTA.INTFLAGS = intflags;
}

View File

@@ -0,0 +1,146 @@
/*
hackspacecon wand firmware
rgb led control and programs
*/
#include <Arduino.h>
#include "rgbled.h"
#include "hsv2rgb.h"
tinyNeoPixel rgb = tinyNeoPixel(RGB_COUNT, PIN_PA1, NEO_GRB, rgbled);
// rgb program prototypes
uint8_t rgbp_rainbow(uint8_t init);
uint8_t rgbp_circlefade(uint8_t init);
// rgb program function pointer array
uint8_t (*rgb_program[PROG_COUNT])(uint8_t) = {
rgbp_rainbow,
rgbp_circlefade
};
uint8_t rgbled[3 * RGB_COUNT];
// configures and enables the 50Hz timer interrupt that is used for RGB program updates
void conf_rgb_timer()
{
// this timer will run at half speed.
// so 8MHz / 2 (prescale) / 1 (CLK_PER) = 4MHz
// this will allow a full cycle time of ~61Hz.
_PROTECTED_WRITE(CLKCTRL_MCLKCTRLB, 0); // disable CLK_PER divider
disable_rgb_timer();
TCB0.CTRLA = TCB_CLKSEL_CLKDIV2_gc; // prescale timer to run at half speed
TCB0.CCMP = 0xffff; // count to full
TCB0.CNT = 0;
}
// globals for all rgb programs
uint16_t prog_timeout;
uint16_t hue;
uint8_t r, g, b;
// rgb program 0: rainbow puke
#define RAINBOW_HUE_INC 40 // how much to increment the hue every frame
#define RAINBOW_OFFSET (1536/5) // offset between each LED
#define RAINBOW_TIMEOUT 240 // how long to show this program
#define RAINBOW_SAT 0xff // saturation
#define RAINBOW_VAL 0x40 // value (brightness); keep low enough to keep average current down
uint16_t rainbow_hue = 0;
uint8_t rgbp_rainbow(uint8_t init)
{
uint8_t i;
// set our timer when initializing. otherwise every call is identical
if (init) {
prog_timeout = RAINBOW_TIMEOUT;
}
if (--prog_timeout) {
// copy stored hue to working hue
hue = rainbow_hue;
for (i = 0; i < RGB_COUNT; i++) {
// each LED will increment its hue
hue += RAINBOW_OFFSET;
// hue wheel is 256*6 large, so bound the value
if (hue >= 1536) hue -= 1536;
// compute rgb from hue/sat/value
hsv2rgb(hue, RAINBOW_SAT, RAINBOW_VAL, &r, &g, &b);
// apply it to this LED
rgb.setPixelColor(i, r, g, b);
}
// increment stored hue wheel for the next cycle through the program
rainbow_hue += RAINBOW_HUE_INC;
if (rainbow_hue > 1536) rainbow_hue -= 1536;
return 1;
}
// done with program
return 0;
}
// rgb program 2: circle loops with fading
#define CF_TIMEOUT 90 // how long to show this program (max 255, ideally (20*loopcount)+10)
#define CF_BRIGHTNESS 64 // how bright to make the LED. don't make too bright or badge will brown out
#define CF_FADERATE 12 // how much to fade all LEDs each frame
uint8_t circlefade_idx = 0;
uint8_t rgbp_circlefade(uint8_t init)
{
uint8_t i;
uint8_t t;
// set our timer when initializing. otherwise every call is identical
if (init) {
prog_timeout = CF_TIMEOUT;
circlefade_idx = 4; // top LED
}
if (--prog_timeout) {
t = (uint8_t)(CF_TIMEOUT - prog_timeout); // get time elapsed
t &= 0x3; // light a new LED every 4th loop
// fade each LED down every frame
for (i = 0; i < (sizeof(rgbled) / sizeof(rgbled[0])); i++) {
if (rgbled[i] >= CF_FADERATE) {
rgbled[i] -= CF_FADERATE;
} else {
rgbled[i] = 0;
}
}
// set the next LED in sequence on to full brightness every 4 cycles
if (prog_timeout >= 10) { // as long as >10 loops remain,
if (!t) { // then on a loop boundary, light the next LED
rgb.setPixelColor(circlefade_idx, CF_BRIGHTNESS, CF_BRIGHTNESS, CF_BRIGHTNESS);
if (++circlefade_idx >= RGB_COUNT) { // then work on the next LED in sequence
circlefade_idx = 0;
}
}
}
}
}

View File

@@ -0,0 +1,37 @@
/*
hackspacecon wand firmware
rgb led control and programs
*/
#ifndef __RGBLED_H__
#define __RGBLED_H__
#include <tinyNeoPixel_Static.h>
#include <stdint.h>
#define RGB_COUNT 5
#define PROG_COUNT 2
#define enable_rgb_timer() {TCB0.CNT = 0; TCB0.CTRLA |= 1;};
#define disable_rgb_timer() {TCB0.CTRLA &= ~1;};
extern tinyNeoPixel rgb;
extern uint8_t rgbled[3 * RGB_COUNT];
extern uint8_t (*rgb_program[PROG_COUNT])(uint8_t);
void conf_rgb_timer();
#endif

View File

@@ -0,0 +1,162 @@
/*
hackspacecon wand firmware
initially written by true
rgb programs and further hacking by 000000widow
----
this version was hacked to work with AS7.
the resulting binary at time of porting takes an additional
531 bytes of flash and 8 bytes of SRAM. I do not know why.
operation workflow:
- at initial reset (battery inserted), set up GPIO and peripherals. this
includes setting up button wake interrupt. sleep MCU into standby mode.
- when button state changes, MCU will wake up and process the interrupt.
if button is pushed (btn gpio is low), prepare to run next RGB program.
- rgb program setup involves turning on power to the LEDs and enabling
TCB0 periodic timer to interrupt every ~61Hz. this timer interrupt
does not handle the rgb program, but will wake the CPU which resumes
processing in the loop() function.
- call the rgb program with the `init` parameter set to 1. idle the CPU.
- rgb prog timer will interrupt every ~61Hz. this will wake the CPU and
send the previously rendered LED data, then call the rgb prog function.
afterward, the CPU idles. process repeats until the rgb prog fn returns 0.
- every time the rgb program is run, the rgb data to send is updated.
the data is not actually sent until next wakeup in less than 16.4ms.
this allows the functions to have variable processing time, but the
output to have a consistent ~61Hz (~16.4ms) timing.
- once rgb program has finalized, clean up state, disable LED power, and sleep
the CPU in standby mode. MCU will wake again once the button is activated.
todo:
- test the code
- set the RGB output data in the sample rainbow puke program
- add more programs
- support incrementing or randomly selecting the next program on each button push
- run TCB0 in standby mode to save a little more power
*/
#include <Arduino.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include "rgbled.h"
#define PIN_LED_PWRENA PIN_PA6
enum {
RGB_IDLE,
RGB_INIT,
RGB_RUNNING
};
enum {
PROG_RUN = 0,
PROG_INIT = 1
};
uint8_t run_rgbprog = RGB_IDLE;
uint8_t rgbprog_idx = 0;
void idle_cpu()
{
SLPCTRL.CTRLA = SLPCTRL_SMODE_IDLE_gc | SLPCTRL_SEN_bm;
__asm("sleep");
}
void sleep_cpu()
{
SLPCTRL.CTRLA = SLPCTRL_SMODE_STDBY_gc | SLPCTRL_SEN_bm;
__asm("sleep");
}
// mcu init
void setup() {
// configure PA2 as falling edge interrupt for button
// note: only PA2 and PA6 support async wakeup.
// since we're using PA2, we're good to wakeup from a
// falling edge (button pushed) event only.
PORTA.DIRCLR = PIN2_bm;
PORTA.PIN2CTRL = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc;
// configure other hardware pins as appropriate
pinMode(PIN_PA3, INPUT_PULLUP); // unused, spare pad on board
pinMode(PIN_PA7, INPUT_PULLUP); // unused, voltage passthru
digitalWrite(PIN_PA6, LOW);
pinMode(PIN_PA6, OUTPUT); // LED boost regulator enable
digitalWrite(PIN_PA1, LOW);
pinMode(PIN_PA1, OUTPUT); // LED data
// set up the RGB ~61Hz periodic timer
conf_rgb_timer();
// enable global interrupts (though they should already be enabled?)
sei();
}
// mcu program loop
void loop() {
switch (run_rgbprog) {
case RGB_INIT: { // just started running a program
digitalWrite(PIN_LED_PWRENA, HIGH); // enable LED power supply,
delay(20); // wait a moment for LEDs to stabilize,
rgbprog_idx++; // select the next program in sequence,
if (rgbprog_idx >= PROG_COUNT) {
rgbprog_idx = 0;
}
rgb_program[rgbprog_idx](PROG_INIT);// initialize the program,
run_rgbprog++; // and set to running mode.
enable_rgb_timer(); // then start the RGB program timebase.
idle_cpu(); // we can idle CPU after running the program
break;
}
case RGB_RUNNING: { // continuing to run a program
rgb.show(); // send updates to the led
// then process the next program frame
if (!rgb_program[rgbprog_idx](PROG_RUN)) {
run_rgbprog = RGB_IDLE; // until the program says it's done
break;
}
idle_cpu(); // we can idle CPU after running the program
break;
}
default: { // no longer running a program
disable_rgb_timer(); // disable RGB program timer,
digitalWrite(PIN_LED_PWRENA, LOW); // disable LED power supply,
run_rgbprog = RGB_IDLE; // and clear run_rgbprog.
sleep_cpu(); // finally, go to sleep in standby mode
break;
}
}
}