Initial commit of tweaked ATtiny88 code
Only some minor cleanup performed. Builds fine with AS7 but is otherwise untested.
This commit is contained in:
commit
08102c2bcd
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
attiny88_main/Debug
|
||||||
|
attiny88_main/Release
|
Binary file not shown.
|
@ -0,0 +1,141 @@
|
||||||
|
:100000002DC047C046C045C044C043C042C041C0E7
|
||||||
|
:1000100040C03FC03EC03DC0AAC33BC03AC039C08B
|
||||||
|
:100020008BC037C036C034C3BDC1C0C1CAC1DBC17B
|
||||||
|
:10003000F8C116C228C227C2F9C103C224C223C212
|
||||||
|
:1000400022C221C220C209C20BC20AC21CC21BC2E8
|
||||||
|
:100050001AC219C218C217C216C207C211241FBE83
|
||||||
|
:10006000CFEFD2E0DEBFCDBF11E0A0E0B1E0E8EA23
|
||||||
|
:10007000F8E002C005900D92A430B107D9F721E055
|
||||||
|
:10008000A4E0B1E001C01D92A433B207E1F76DD244
|
||||||
|
:1000900009C4B6CFE4E6F0E080818E7F8083EAE792
|
||||||
|
:1000A000F0E08FED8083ACE7B0E08C918F7D8C9396
|
||||||
|
:1000B0008081886880830895282F803188F490910A
|
||||||
|
:1000C0007C00907F982B90937C00883030F481E006
|
||||||
|
:1000D00001C0880F2A95EAF701C080E080937E0076
|
||||||
|
:1000E000613021F480917C00806405C0623029F485
|
||||||
|
:1000F00080917C008F7B80937C00089590917A00A2
|
||||||
|
:10010000292F207496FD15C080930C01662311F0F1
|
||||||
|
:10011000982F01C090E09093040190917C009F7013
|
||||||
|
:10012000906890931F0190917A00906490937A0068
|
||||||
|
:1001300001C021E0822F08951F920F920FB60F92F7
|
||||||
|
:1001400011242F934F935F938F939F93AF93BF93FC
|
||||||
|
:10015000EF93FF93E0917C00EF7020910401222344
|
||||||
|
:10016000D1F080910C012817B1F0E930A0F4AE2F46
|
||||||
|
:10017000B0E0AA0FBB1FA35FBE4F4D915C911197DA
|
||||||
|
:100180008091780090917900840F951F96958795BE
|
||||||
|
:1001900011969C938E9380910C01882359F0809145
|
||||||
|
:1001A0000C01815080930C0180917A0080648093CF
|
||||||
|
:1001B0007A0011C021110DC0E93058F4F0E08091AF
|
||||||
|
:1001C000780090917900EE0FFF1FE35FFE4F91835F
|
||||||
|
:1001D000808310921F01FF91EF91BF91AF919F918A
|
||||||
|
:1001E0008F915F914F912F910F900FBE0F901F90A5
|
||||||
|
:1001F00018958AB1806F8AB987B18F6087B98BB142
|
||||||
|
:10020000806F8BB988B18F6088B90895CF93DF93E1
|
||||||
|
:100210008BB1806F8BB988B18F6088B9C8E8D0E0A6
|
||||||
|
:100220008EEF8883AAE8B0E08C938AEF90E09093F9
|
||||||
|
:100230008500809384003BB124E02D0D81E090E0A7
|
||||||
|
:10024000AC0101C0440F2A95EAF7242F20952323FF
|
||||||
|
:100250002BB928B10D2C01C0880F0A94EAF78095BC
|
||||||
|
:10026000822388B9ED2DF0E0EB5DFE4F8BEF90819E
|
||||||
|
:10027000282F291B2883ED2DF0E0EF5DFE4F9081A4
|
||||||
|
:10028000891B8C93DF91CF9108959BB1906F9BB99F
|
||||||
|
:10029000E0E8F0E090819F70908397B1907F97B9EC
|
||||||
|
:1002A00095B7906195BF47B121E030E0B90102C038
|
||||||
|
:1002B000660F771F8A95E2F7CB01462B47B998B1B5
|
||||||
|
:1002C000907F98B92A9A98B1982B98B92A9878E093
|
||||||
|
:1002D0007A95F1F797B18095982397B998B18923CA
|
||||||
|
:1002E00088B985B78F7E85BF0895843038F466233A
|
||||||
|
:1002F00029F0E82FF0E0E050FF4F6083089583700D
|
||||||
|
:1003000080930501089580910501E82FF0E0E05009
|
||||||
|
:10031000FF4F9081911101C091E02E2DE11003C09B
|
||||||
|
:1003200061E08FE012C0213019F460E080E018C075
|
||||||
|
:10033000223061F490911F01992319F0EE24E39487
|
||||||
|
:100340000895A3DF6FEF80910501B6CE4E2D50E0EA
|
||||||
|
:10035000892F90E002964817590719F461E083E06D
|
||||||
|
:10036000CDCE8417950794F42150E22E80911F0181
|
||||||
|
:1003700081110CC06FEF8FE09FDE3BDF8EEF80932B
|
||||||
|
:10038000800084B1866084B91092200108958F2D79
|
||||||
|
:100390004F2D50E04A31510508F075C0FA01EC5E6E
|
||||||
|
:1003A000FF4F0994F12C10922A0108958091330196
|
||||||
|
:1003B000882309F46CC0F090300183E0809333010E
|
||||||
|
:1003C00050C0E0912F01E43020F4F0E0EB5DFE4FEF
|
||||||
|
:1003D00006C0E83008F044C0F0E0E35EFE4F8091D4
|
||||||
|
:1003E000300180833DC080913301882309F44FC0E0
|
||||||
|
:1003F00080911D0190911E01892B09F444C06091E8
|
||||||
|
:100400001D0170911E0180913001681B710987FDEB
|
||||||
|
:10041000739570930701609306018EE390E024D2F8
|
||||||
|
:100420001FC0809133018230D8F41DC0809120011B
|
||||||
|
:10043000811117C010922001E12C88E080932001E7
|
||||||
|
:1004400010C08091200181110CC010922001E12C7C
|
||||||
|
:1004500080912F0154DF81E0F1CF84E08093090186
|
||||||
|
:10046000F12C10922A0180E00895809133018823B5
|
||||||
|
:1004700071F080912F01843098F7609130016623EC
|
||||||
|
:1004800079F333DFEDCFF12C10922A0181E008954A
|
||||||
|
:100490008093BB00ECEBF0E08081806880838081FA
|
||||||
|
:1004A0008F7B808380E008958F2D8830B9F089306C
|
||||||
|
:1004B000C1F0843051F580912F01803428F490E010
|
||||||
|
:1004C000C8D1E6DF81E006C08091BC008F7B8093BD
|
||||||
|
:1004D000BC008FEFF12C10922A0108958091080141
|
||||||
|
:1004E0000EC0E0912F01E370F0E0EE0FFF1FE35F1D
|
||||||
|
:1004F000FE4F808191819695879596958795C8DF67
|
||||||
|
:10050000F12C10922A0181E008958091BC008F7B2C
|
||||||
|
:100510008093BC008FEF089580911D0190911E0182
|
||||||
|
:1005200090910601891B982F959595959595891B16
|
||||||
|
:1005300008958E2DE11003C062E088E0BDCD8330C8
|
||||||
|
:1005400019F461E084E0DACD843070F08150E82E57
|
||||||
|
:1005500080911F01811108C061E08FE0ADDD109234
|
||||||
|
:100560002001DADF80930801089580E8809361001C
|
||||||
|
:100570001092610082B3806F82BB1DB881E084B9A4
|
||||||
|
:1005800017B81AB8CFEFCEB9DEEFD5B9C8B9CBB925
|
||||||
|
:1005900030DE22E02093B8008CEF8093B90086EE25
|
||||||
|
:1005A0008093BA001092BD0085E48093BC008091D6
|
||||||
|
:1005B00064008A7F809364009BEF95BD8DE387BDC7
|
||||||
|
:1005C00016BC20936E00809164008C7F8093640041
|
||||||
|
:1005D000C0938900C0938800C0938A001092850060
|
||||||
|
:1005E00010928400D093800089E180938100109262
|
||||||
|
:1005F000820080918000809329019093860084B1CD
|
||||||
|
:10060000866084B910926F0045DD629923C042DD97
|
||||||
|
:100610002FEF80E792E0215080409040E1F700C04A
|
||||||
|
:100620000000629917C0789488E08093200181DFF0
|
||||||
|
:1006300080911F018111FCCF60911D0170911E01FD
|
||||||
|
:1006400070930701609306018EE390E00DD1109244
|
||||||
|
:1006500020010DC08EE390E003D1813322E09207A8
|
||||||
|
:1006600014F081E191E0909307018093060183B734
|
||||||
|
:10067000897F90910901892B83BF10920901789499
|
||||||
|
:1006800083B7816083BF889583B78E7F83BFEFCFA9
|
||||||
|
:100690001F920F920FB60F9211242F933F934F93F7
|
||||||
|
:1006A0005F936F937F938F939F93AF93BF93EF93DA
|
||||||
|
:1006B000FF938091B900887F803AF1F160F4883629
|
||||||
|
:1006C00009F43FC028F4882391F18036D1F134C079
|
||||||
|
:1006D000803839F031C0883B41F170F5883A29F112
|
||||||
|
:1006E0002BC08091BB00F1100FC0982F92959F7086
|
||||||
|
:1006F000F92E982F9F7090932F0110923301109232
|
||||||
|
:100700002A0187FF1EC00AC0E0913301EF5FE3704A
|
||||||
|
:10071000E0933301F0E0E15DFE4F808338DE882313
|
||||||
|
:1007200081F08091BC008F7B0AC0BEDE0AC0809140
|
||||||
|
:10073000BC0080698093BC008091BC008064809381
|
||||||
|
:10074000BC008091BC0080688093BC00FF91EF9159
|
||||||
|
:10075000BF91AF919F918F917F916F915F914F91D9
|
||||||
|
:100760003F912F910F900FBE0F901F9018951F92E1
|
||||||
|
:100770000F920FB60F9211242F933F934F935F93D5
|
||||||
|
:100780006F937F938F939F93AF93BF93EF93FF9359
|
||||||
|
:1007900080910B018F5F883C18F480930B010CC093
|
||||||
|
:1007A00010920B0180910A018F5F843618F48093B8
|
||||||
|
:1007B0000A0102C010920A0187B58D3311F08DE352
|
||||||
|
:1007C00001C08EE387BD80912001882371F0809164
|
||||||
|
:1007D0002001813021F0883019F4ABDE01C093DDB7
|
||||||
|
:1007E0008E2D8F3F11F08F5FE82E80912001813098
|
||||||
|
:1007F00041F081E08D0D833010F4D82E01C0D12C52
|
||||||
|
:1008000005DDFF20A1F080912A018F5F80932A01EE
|
||||||
|
:10081000823368F0F12C10922A018091BC008F7B0A
|
||||||
|
:100820008093BC008091BC0080648093BC0086B53E
|
||||||
|
:10083000FF91EF91BF91AF919F918F917F916F91B8
|
||||||
|
:100840005F914F913F912F910F900FBE0F901F908E
|
||||||
|
:100850001895F999FECF81BDF89A992780B508952A
|
||||||
|
:10086000A8E1B0E042E005C010D0272F0FC0DC01A6
|
||||||
|
:10087000862FE82FF999FECF05C0E1BDF89AE395E0
|
||||||
|
:1008800000B40D924150C8F70895262FF999FECF74
|
||||||
|
:100890001FBA81BD20BD0FB6F894FA9AF99A0FBE1F
|
||||||
|
:0808A00001960895F894FFCFC2
|
||||||
|
:0408A8000101010148
|
||||||
|
:00000001FF
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* adc.c
|
||||||
|
*
|
||||||
|
* Created: 6/9/2014 11:07:35 PM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "adc.h"
|
||||||
|
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
|
|
||||||
|
volatile uint8_t adc_busy;
|
||||||
|
volatile uint8_t adc_reread;
|
||||||
|
|
||||||
|
volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1];
|
||||||
|
static uint8_t adc_averages;
|
||||||
|
|
||||||
|
volatile uint8_t adc_read_mode;
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
void adc_init()
|
||||||
|
{
|
||||||
|
// make sure ADC power is enabled
|
||||||
|
PRR &= ~_BV(PRADC);
|
||||||
|
|
||||||
|
// clear all settings; set the ADC prescaler bits to get 500KHz ADC clock (SYSCLK/16), disable auto trigger
|
||||||
|
ADCSRA = _BV(ADPS2) | _BV(ADPS0) | ~(_BV(ADATE));
|
||||||
|
|
||||||
|
// set to right-aligned mode
|
||||||
|
ADMUX &= ~(_BV(ADLAR));
|
||||||
|
|
||||||
|
// enable the ADC, enable interrupts
|
||||||
|
ADCSRA |= _BV(ADEN) | _BV(ADIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adc_channel(uint8_t channel, uint8_t vref)
|
||||||
|
{
|
||||||
|
// can we set channel?
|
||||||
|
if (channel < ADC_CHAN_INVALID) {
|
||||||
|
// set MUX[3:0] to the specified channel
|
||||||
|
ADMUX = (ADMUX & 0xf0) | (channel & 0x0f);
|
||||||
|
// also, if this is an actual pin, disable digital input on this pin
|
||||||
|
DIDR0 = (channel < 8) ? _BV(channel) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the voltage source
|
||||||
|
if (vref == ADC_REF_AVCC) {
|
||||||
|
ADMUX |= (_BV(REFS0));
|
||||||
|
} else if (vref == ADC_REF_BANDGAP) {
|
||||||
|
ADMUX &= ~(_BV(REFS0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t adc_start(uint8_t reread, uint8_t enable_averaging)
|
||||||
|
{
|
||||||
|
// is a conversion already running?
|
||||||
|
if (ADCSRA & _BV(ADSC)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up amount of times to re-read, and mark the amount of values to average
|
||||||
|
adc_reread = reread;
|
||||||
|
adc_averages = enable_averaging ? reread : 0;
|
||||||
|
|
||||||
|
// start conversion
|
||||||
|
adc_busy = 0x80 | (ADMUX & 0x0f);
|
||||||
|
ADCSRA |= _BV(ADSC);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ISR */
|
||||||
|
ISR(ADC_vect)
|
||||||
|
{
|
||||||
|
uint8_t channel;
|
||||||
|
|
||||||
|
channel = ADMUX & 0x0f;
|
||||||
|
|
||||||
|
// mark our result in the average table
|
||||||
|
if (adc_averages) {
|
||||||
|
// except for the first read
|
||||||
|
if (adc_averages != adc_reread) {
|
||||||
|
// we do successive averaging; it's faster, smaller code, less RAM, and good enough for our purpose
|
||||||
|
// update our feedback
|
||||||
|
if (channel <= ADC_MAX_FEEDBACK) {
|
||||||
|
adc_result[channel] = (adc_result[channel] + ADC) >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adc_reread) {
|
||||||
|
adc_reread--;
|
||||||
|
// start another conversion
|
||||||
|
ADCSRA |= _BV(ADSC);
|
||||||
|
} else {
|
||||||
|
// determine if we need to update feedback
|
||||||
|
if (!adc_averages && channel <= ADC_MAX_FEEDBACK) {
|
||||||
|
// not averaging, so just store last result
|
||||||
|
adc_result[channel] = ADC;
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_busy = 0;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* adc.h
|
||||||
|
*
|
||||||
|
* Created: 6/9/2014 11:07:51 PM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ADC_H_
|
||||||
|
#define ADC_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ADC_CHAN_0 0
|
||||||
|
#define ADC_CHAN_1 1
|
||||||
|
#define ADC_CHAN_2 2
|
||||||
|
#define ADC_CHAN_3 3
|
||||||
|
#define ADC_CHAN_4 4
|
||||||
|
#define ADC_CHAN_5 5
|
||||||
|
#define ADC_CHAN_6 6
|
||||||
|
#define ADC_CHAN_7 7
|
||||||
|
#define ADC_CHAN_TEMP 8
|
||||||
|
#define ADC_CHAN_BANDGAP 14
|
||||||
|
#define ADC_CHAN_GND 15
|
||||||
|
#define ADC_CHAN_INVALID ADC_CHAN_GND + 1 // one above last valid channel
|
||||||
|
|
||||||
|
#define ADC_REF_AVCC 1
|
||||||
|
#define ADC_REF_BANDGAP 2
|
||||||
|
#define ADC_REF_NO_SET 255
|
||||||
|
|
||||||
|
#define ADC_MAX_FEEDBACK ADC_CHAN_TEMP
|
||||||
|
|
||||||
|
// adc read interrupt
|
||||||
|
extern volatile uint8_t adc_busy;
|
||||||
|
extern volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1];
|
||||||
|
|
||||||
|
// main timer adc handler
|
||||||
|
extern volatile uint8_t adc_read_mode;
|
||||||
|
register uint8_t adc_read_step asm("r14");
|
||||||
|
|
||||||
|
|
||||||
|
/* application specific */
|
||||||
|
#define ADC_READ_LED_RED ADC_CHAN_0
|
||||||
|
#define ADC_READ_LED_GREEN ADC_CHAN_1
|
||||||
|
#define ADC_READ_LED_BLUE ADC_CHAN_2
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
void adc_init();
|
||||||
|
void adc_channel(uint8_t channel, uint8_t bandgap_ref);
|
||||||
|
uint8_t adc_start(uint8_t reread, uint8_t enable_averaging);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ADC_H_ */
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* config.h
|
||||||
|
*
|
||||||
|
* Created: 5/24/2014 9:22:14 AM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef CONFIG_H_
|
||||||
|
#define CONFIG_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <avr/io.h>
|
||||||
|
#include <avr/sfr_defs.h>
|
||||||
|
|
||||||
|
|
||||||
|
// system
|
||||||
|
#define F_CPU 8000000UL
|
||||||
|
|
||||||
|
|
||||||
|
// LEDs
|
||||||
|
#define LED_COMMON_ANODE // defined = common anode, undef = common cathode
|
||||||
|
//#define LED_RGBX_4LED 1 // defined = use 4 LEDs (RGBX), undef = use 3 LEDs (RGB)
|
||||||
|
|
||||||
|
|
||||||
|
// i2c config
|
||||||
|
#define I2C_SLAVE_ADDRESS 0x73 // 7-bit address (0b1110011)
|
||||||
|
#define I2C_ENABLE_ADDR_ZERO 0 // 1 = enable response on 0x00, 0 = disable
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* CONFIG_H_ */
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* i2c.h
|
||||||
|
*
|
||||||
|
* Created: 5/21/2014 11:41:32 PM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef I2C_H_
|
||||||
|
#define I2C_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* macros */
|
||||||
|
#define i2c_clear_int_flag() TWCR |= _BV(TWINT)
|
||||||
|
|
||||||
|
#define i2c_disable_interrupt() TWCR &= ~(_BV(TWIE))
|
||||||
|
#define i2c_enable_interrupt() TWCR |= _BV(TWIE)
|
||||||
|
|
||||||
|
#define i2c_disable_slave() TWCR &= ~(_BV(TWEA))
|
||||||
|
#define i2c_enable_slave() TWCR |= _BV(TWEA)
|
||||||
|
|
||||||
|
|
||||||
|
/* configuration */
|
||||||
|
static inline void i2c_slave_init(uint8_t address, uint8_t enable_general_addr)
|
||||||
|
{
|
||||||
|
// set bitrate register, clear prescaler
|
||||||
|
// should get us 400KHz (fast mode) max rate
|
||||||
|
TWBR = 2;
|
||||||
|
TWSR = ~(_BV(TWPS0) | _BV(TWPS1));
|
||||||
|
|
||||||
|
// set slave address and clear address mask
|
||||||
|
TWAR = ((address << 1) | (enable_general_addr & 1));
|
||||||
|
TWAMR = 0;
|
||||||
|
|
||||||
|
// enable auto-ack, enable TWI, and enable the TWI interrupt
|
||||||
|
TWCR = _BV(TWEA) | _BV(TWEN) | _BV(TWIE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sending */
|
||||||
|
static uint8_t i2c_slave_tx(uint8_t byte, uint8_t is_last_byte)
|
||||||
|
{
|
||||||
|
// load data
|
||||||
|
TWDR = byte;
|
||||||
|
|
||||||
|
// start sending
|
||||||
|
TWCR |= _BV(TWINT);
|
||||||
|
|
||||||
|
if (is_last_byte) {
|
||||||
|
// this is all the data we have to send; send a nack after this byte
|
||||||
|
i2c_disable_slave();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* I2C_H_ */
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* i2c_interrupt.h
|
||||||
|
*
|
||||||
|
* Created: 6/13/2014 1:53:36 AM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef I2C_INTERRUPT_H_
|
||||||
|
#define I2C_INTERRUPT_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
|
ISR(TWI_vect)
|
||||||
|
{
|
||||||
|
// i2c is low priority - allow it to be interrupted
|
||||||
|
// sei();
|
||||||
|
|
||||||
|
// figure out wtf to do
|
||||||
|
switch (TWSR & 0xf8) { // TWI state
|
||||||
|
// ** SLAVE RECEIVE ** //
|
||||||
|
case 0x60: // slave addr+write receive to valid address
|
||||||
|
case 0x68: { // slave addr+write arbitration lost?
|
||||||
|
// nothing to do. we're ready to receive.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
case 0x70:
|
||||||
|
case 0x78: {
|
||||||
|
// unused: this is for genaddr mode.
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
case 0x80: { // slave data receive w/ACK returned
|
||||||
|
if (pegleg_data_rx(TWDR)) {
|
||||||
|
// I wanted to send a NAK, but TWI already sent an ACK. oh fucking well.
|
||||||
|
// send NACK if any further packets are received
|
||||||
|
i2c_disable_slave();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*case 0x90: { // slave genaddr data receive w/ACK returned
|
||||||
|
// not using this
|
||||||
|
}*/
|
||||||
|
|
||||||
|
case 0x88: // slave data receive w/NACK returned, no longer addressed
|
||||||
|
//case 0x98: // slave genaddr data receive w/NACK returned, no longer addressed
|
||||||
|
case 0xa0: { // STOP asserted; done receiving? no longer addressed
|
||||||
|
// we can re-enable the slave...
|
||||||
|
i2c_enable_slave();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ** SLAVE TRANSMIT ** //
|
||||||
|
case 0xa8: { // slave read request to valid address
|
||||||
|
// try to send data
|
||||||
|
pegleg_data_tx();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xb8: { // slave read continues, master ACK'd last packet
|
||||||
|
// do we have a mode in progress?
|
||||||
|
// NOTE: by default, slave tx modes won't unset, but slave mode will be disabled
|
||||||
|
// when the last packet is sent, and re-enabled on the following ACK/NACK.
|
||||||
|
pegleg_data_tx();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0xb0: // arbitration lost
|
||||||
|
// I don't even know how the fuck this happened
|
||||||
|
case 0xc0: // slave read ends, master doesn't want more data
|
||||||
|
// this usually happens after we've sent data and master doesn't want any more.
|
||||||
|
// if we had more data, tough shit, master doesn't want it. so we don't send it.
|
||||||
|
case 0xc8: { // slave read ends, master wants more data though
|
||||||
|
// this usually happens after we're done sending, but master is requesting more.
|
||||||
|
// but slave mode is disabled, so don't send anything.
|
||||||
|
// we need to make sure send mode is disabled, and we need to re-enable slave mode.
|
||||||
|
i2c_enable_slave();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ** ERROR AND UNHANDLED ** //
|
||||||
|
case 0x00: { // bus error
|
||||||
|
// set TWSTO, clear TWINT (by setting) as per datasheet
|
||||||
|
TWCR |= (_BV(TWSTO)) | (_BV(TWINT));
|
||||||
|
// and make sure slave is enabled
|
||||||
|
i2c_enable_slave();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
// something unhandled? fuck it, we want to be a slave.
|
||||||
|
// reset everything and start over.
|
||||||
|
i2c_enable_slave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// done with this TWI bit
|
||||||
|
i2c_clear_int_flag();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* MAIN_INTERRUPT_H_ */
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* led.c
|
||||||
|
*
|
||||||
|
* Created: 6/13/2014 1:44:28 AM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* led */
|
||||||
|
uint8_t rgbled_pwm_lf[4]; // pwm value for TIMER1 OCA LED outputs
|
||||||
|
uint8_t rgbled_pwm_rt[4]; // pwm value for TIMER1 OCB LED outputs
|
||||||
|
|
||||||
|
static uint8_t rgbled_read_sel; // LED light sensor select
|
||||||
|
static uint8_t rgbled_sensitivity[4] = {1, 1, 1, 1};
|
||||||
|
|
||||||
|
/* adc */
|
||||||
|
volatile uint8_t adc_busy;
|
||||||
|
volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1];
|
||||||
|
volatile uint8_t adc_read_mode;
|
||||||
|
|
||||||
|
|
||||||
|
/* functions */
|
||||||
|
// sets up the IO pins for LED output function.
|
||||||
|
void rgbled_io_init()
|
||||||
|
{
|
||||||
|
// PortD[4:7] (left) and PortC[0:3] (right) are LEDs
|
||||||
|
// Also, Right LEDs are capable of ADC input on ALL pins (ADC[0:3])
|
||||||
|
|
||||||
|
// set all pins as outputs
|
||||||
|
DDRD |= 0xf0;
|
||||||
|
DDRC |= 0x0f;
|
||||||
|
|
||||||
|
#ifdef LED_COMMON_ANODE
|
||||||
|
// com-anode: pin is high to disable
|
||||||
|
PORTD |= 0xf0;
|
||||||
|
PORTC |= 0x0f;
|
||||||
|
#else
|
||||||
|
// com-cathode: pin is low to disable
|
||||||
|
PORTD &= 0x0f;
|
||||||
|
PORTC &= 0xf0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets the appropriate pins and PWM values for the LED index specified in rgbled_idx.
|
||||||
|
// note: this index is updated externally, and not by this function.
|
||||||
|
void rgbled_update()
|
||||||
|
{
|
||||||
|
// clear all selected LED pins
|
||||||
|
// we have to clear the select line then set it because we can't fully disable the PWM for some reason
|
||||||
|
#ifdef LED_COMMON_ANODE
|
||||||
|
// make sure all pins are high
|
||||||
|
PORTD |= 0xf0;
|
||||||
|
PORTC |= 0x0f;
|
||||||
|
#else
|
||||||
|
// make sure all pins are low
|
||||||
|
PORTD &= 0x0f;
|
||||||
|
PORTC &= 0xf0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// set pwm OCx registers to max
|
||||||
|
timer1_set_oca(TIMER1_COMPARE);
|
||||||
|
timer1_set_ocb(TIMER1_COMPARE);
|
||||||
|
// and set pwm counter value to 1 before expiry
|
||||||
|
timer1_set(TIMER1_COMPARE - 1);
|
||||||
|
|
||||||
|
// now we set the desired LED
|
||||||
|
// turn on one LED in each group
|
||||||
|
#ifdef LED_COMMON_ANODE
|
||||||
|
// make sure active pin is output low and others are high
|
||||||
|
PORTD &= ~(_BV(rgbled_idx + 4));
|
||||||
|
PORTC &= ~(_BV(rgbled_idx));
|
||||||
|
#else
|
||||||
|
// make sure active pin is output high and others are low
|
||||||
|
PORTD |= _BV(rgbled_idx) << 4;
|
||||||
|
PORTC |= _BV(rgbled_idx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// load new pwm OCx values for this LED
|
||||||
|
timer1_set_oca(rgbled_pwm_lf[rgbled_idx]);
|
||||||
|
timer1_set_ocb(rgbled_pwm_rt[rgbled_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// sets up the PortC LED matrix as a diode light sensor.
|
||||||
|
// configures the specified LED on the ADC.
|
||||||
|
// this function assumes common anode.
|
||||||
|
void rgbled_sensor_init(uint8_t led)
|
||||||
|
{
|
||||||
|
// set the left eye high (fixes color flash/tearing)
|
||||||
|
PORTD |= 0xf0;
|
||||||
|
|
||||||
|
// disable both eye's PWM (required for right eye, fixes color flash/tearing in left eye)
|
||||||
|
TCCR1A &= ~(_BV(COM1A1) | _BV(COM1A0) | _BV(COM1B1) | _BV(COM1B0));
|
||||||
|
|
||||||
|
// ground the LED
|
||||||
|
DDRC &= 0xf0; // set all LEDs cathode as inputs
|
||||||
|
MCUCR |= (_BV(PUD)); // globally disable pullups
|
||||||
|
DDRC |= (_BV(led)); // set our LED as an output
|
||||||
|
PORTC = (PORTC & 0xf0); // set all LEDs cathode low
|
||||||
|
PORTB |= (_BV(PORTB2)); // set anode high
|
||||||
|
|
||||||
|
// reverse LED bias
|
||||||
|
PORTC |= (_BV(led)); // set cathode high
|
||||||
|
PORTB &= ~(_BV(PORTB2)); // set anode low
|
||||||
|
_delay_us(3); // allow it to charge fully
|
||||||
|
|
||||||
|
// set LED as input
|
||||||
|
DDRC &= ~(_BV(led)); // set led cathode as input
|
||||||
|
PORTC &= ~(_BV(led)); // set led cathode pullup off
|
||||||
|
MCUCR &= ~(_BV(PUD)); // re-enable global pullups
|
||||||
|
}
|
||||||
|
|
||||||
|
// starts ADC to read the value of charge remaining on the LED
|
||||||
|
void rgbled_sensor_sensitivity(uint8_t ledidx, uint8_t sensitivity)
|
||||||
|
{
|
||||||
|
if (ledidx <= 0x03) {
|
||||||
|
if (sensitivity) {
|
||||||
|
rgbled_sensitivity[ledidx] = sensitivity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgbled_sensor_read_idx(uint8_t ledidx)
|
||||||
|
{
|
||||||
|
rgbled_read_sel = ledidx & 0x03;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgbled_sensor_read()
|
||||||
|
{
|
||||||
|
uint8_t sens;
|
||||||
|
|
||||||
|
sens = rgbled_sensitivity[rgbled_read_sel];
|
||||||
|
if (!sens) sens = 1;
|
||||||
|
|
||||||
|
if (adc_read_step == 0) {
|
||||||
|
// adc_init();
|
||||||
|
// clear ADC bias by reading ground
|
||||||
|
adc_channel(ADC_CHAN_GND, ADC_REF_AVCC);
|
||||||
|
} else if (adc_read_step == 1) {
|
||||||
|
adc_start(0, 0);
|
||||||
|
} else if (adc_read_step == 2) {
|
||||||
|
// if the ADC is done, charge up LED for reading
|
||||||
|
if (adc_busy) {
|
||||||
|
adc_read_step--;
|
||||||
|
} else {
|
||||||
|
rgbled_sensor_init(rgbled_read_sel);
|
||||||
|
adc_channel(rgbled_read_sel, ADC_REF_NO_SET);
|
||||||
|
}
|
||||||
|
} else if (adc_read_step == (2 + sens)) {
|
||||||
|
// if vref has changed, it should be stable by now; start reading LED value
|
||||||
|
adc_start(3, 1);
|
||||||
|
} else if (adc_read_step > (2 + sens)) {
|
||||||
|
adc_read_step--;
|
||||||
|
if (!adc_busy) {
|
||||||
|
// we are done! :) finish up...
|
||||||
|
adc_channel(ADC_CHAN_GND, ADC_REF_NO_SET); // change ADC to not look at a real pin
|
||||||
|
rgbled_io_init(); // set LED pins up again
|
||||||
|
timer1_pwm_reinit(); // and set up PWM again
|
||||||
|
adc_read_mode = 0; // clear ADC read mode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* led.h
|
||||||
|
*
|
||||||
|
* Created: 6/13/2014 1:40:53 AM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef LED_H_
|
||||||
|
#define LED_H_
|
||||||
|
|
||||||
|
|
||||||
|
/* incl */
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
#include "adc.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* led */
|
||||||
|
#define LED_RED 0
|
||||||
|
#define LED_GREEN 1
|
||||||
|
#define LED_BLUE 2
|
||||||
|
#define LED_SPARE 3
|
||||||
|
|
||||||
|
|
||||||
|
/* globals */
|
||||||
|
extern uint8_t rgbled_pwm_lf[4]; // pwm value for TIMER1 OCA LED outputs
|
||||||
|
extern uint8_t rgbled_pwm_rt[4]; // pwm value for TIMER1 OCB LED outputs
|
||||||
|
register uint8_t rgbled_idx asm("r13"); // the currently operated LED
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
void rgbled_io_init();
|
||||||
|
void rgbled_update();
|
||||||
|
|
||||||
|
void rgbled_sensor_sensitivity(uint8_t ledidx, uint8_t sensitivity);
|
||||||
|
void rgbled_sensor_read_idx(uint8_t ledidx);
|
||||||
|
void rgbled_sensor_read();
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* LED_H_ */
|
|
@ -0,0 +1,574 @@
|
||||||
|
/*
|
||||||
|
* Whiskey Pirates Badge "PEGLEG CPU"
|
||||||
|
* Sub MCU Firmware for ATtiny88
|
||||||
|
*
|
||||||
|
* Created: 5/21/2014 9:24:48 PM
|
||||||
|
* Author: true
|
||||||
|
* ts:4
|
||||||
|
*
|
||||||
|
********
|
||||||
|
* PEGLEG CPU is responsible for:
|
||||||
|
* - aux gpio (todo: list specifically which GPIOs on the badge)
|
||||||
|
* - eye RGBLED matrix
|
||||||
|
* - temperature sensor
|
||||||
|
* - light sensor (using eye RGBLEDs; in practice uses the left eye red LED)
|
||||||
|
* - user config eeprom
|
||||||
|
*
|
||||||
|
********
|
||||||
|
* Use the following fuses for this project. Needs to run at 8MHz for 400khz I2C operation.
|
||||||
|
* 8MHz, self-program enabled (bootloader support), preserve EEPROM, BOD disabled, ISP enabled
|
||||||
|
* -U lfuse:w:0xEE:m -U hfuse:w:0xD7:m -U efuse:w:0x00:m
|
||||||
|
* (efuse will likely show as 0x06 after setting; this is fine, don't worry about it)
|
||||||
|
*
|
||||||
|
* Resources used: Mainline ISR 5% (3/63 timer counts simulated, as of some old rev)
|
||||||
|
* Flash 26.8%, SRAM 10.4% (as of the above rev)
|
||||||
|
*
|
||||||
|
**********
|
||||||
|
* Register Variables:
|
||||||
|
* main.c:comm_cmd:r15
|
||||||
|
* adc.h:adc_read_step:r14
|
||||||
|
* led.c:rgbled_idx:r13
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* system */
|
||||||
|
#include <avr/eeprom.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
#include <avr/sleep.h>
|
||||||
|
|
||||||
|
#include <util/delay.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include "i2c.h"
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
#include "adc.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* modes (commands) */
|
||||||
|
#define MODE_NONE 0b0000
|
||||||
|
|
||||||
|
#define MODE_EXT_CMD 0b0001 // bit 4 unset = extra parameters needed, up to 6 commands
|
||||||
|
#define MODE_LED_SET_LEVEL 0b0010 // (0x00 reserved, 0x1? extra, leaving 0x2? through 0x7?)
|
||||||
|
#define MODE_TEMPSENSOR_CAL 0b0011
|
||||||
|
#define MODE_EEPROM_READ 0b0100
|
||||||
|
#define MODE_EEPROM_WRITE 0b0101
|
||||||
|
|
||||||
|
#define MODE_TEMPSENSOR_READ 0b1000 // bit 4 set = immediate, no extra parameters, process now
|
||||||
|
#define MODE_LIGHTSENSOR_READ 0b1001
|
||||||
|
#define MODE_SLEEP 0b1111
|
||||||
|
|
||||||
|
#define MODE_AUX_PIN_GET 0x10 // extended (send 0x10, cmd, data...)
|
||||||
|
#define MODE_AUX_PIN_SET 0x11 // ext commands MUST be 0x10 or higher! 0x00-0x0f are RESERVED!
|
||||||
|
#define MODE_LIGHTSENSOR_SENS 0x19
|
||||||
|
|
||||||
|
/* aux pin mode */
|
||||||
|
#define AUX_PIN_COUNT 10
|
||||||
|
#define AUX_PIN_OUTPUT 0x01 // sets to output if set, input if cleared
|
||||||
|
#define AUX_PIN_PORTSET 0x02 // output: sets high/low; input: sets pullup on/off
|
||||||
|
|
||||||
|
/* adc modes */
|
||||||
|
#define ADC_MODE_TEMPSENSOR 8
|
||||||
|
#define ADC_MODE_LIGHTSENSOR 1
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
static void system_init();
|
||||||
|
static void system_io_init();
|
||||||
|
static void tempsensor_cal();
|
||||||
|
|
||||||
|
|
||||||
|
/* globals */
|
||||||
|
static uint8_t tim0_milli;
|
||||||
|
static uint8_t tim0_centi;
|
||||||
|
static uint8_t tim0_profiler;
|
||||||
|
|
||||||
|
#define COMM_DATA_SIZE 4 // must be power of 2; default value is 4
|
||||||
|
register uint8_t comm_cmd asm("r15"); // currently processed SPI command
|
||||||
|
uint8_t comm_data_idx; // command data write index
|
||||||
|
uint8_t comm_data[COMM_DATA_SIZE]; // command data register
|
||||||
|
uint8_t comm_timeout; // command invalidate timeout
|
||||||
|
|
||||||
|
|
||||||
|
/* core */
|
||||||
|
static uint8_t pirate_sleep_mode = SLEEP_MODE_IDLE;
|
||||||
|
|
||||||
|
/* tempsensor */
|
||||||
|
static int8_t temperature;
|
||||||
|
static int16_t temp_offset;
|
||||||
|
|
||||||
|
/* eeprom */
|
||||||
|
#define EEPROM_ADDR_TEMPCAL 62 // 2 bytes
|
||||||
|
|
||||||
|
/* adc */
|
||||||
|
volatile uint8_t adc_busy;
|
||||||
|
volatile uint16_t adc_result[ADC_MAX_FEEDBACK + 1];
|
||||||
|
|
||||||
|
/* led */
|
||||||
|
uint8_t rgbled_pwm_lf[4]; // pwm value for TIMER1 OCA LED outputs
|
||||||
|
uint8_t rgbled_pwm_rt[4]; // pwm value for TIMER1 OCB LED outputs
|
||||||
|
|
||||||
|
uint8_t rgbled_light_level[4];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* it begins */
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
// configure device and IO
|
||||||
|
system_init();
|
||||||
|
system_io_init();
|
||||||
|
|
||||||
|
// configure RGBLEDs
|
||||||
|
rgbled_io_init();
|
||||||
|
|
||||||
|
// configure i2c communications
|
||||||
|
i2c_slave_init(I2C_SLAVE_ADDRESS, I2C_ENABLE_ADDR_ZERO);
|
||||||
|
|
||||||
|
// configure system timer
|
||||||
|
timer0_init();
|
||||||
|
// configure led pwm timer
|
||||||
|
timer1_init();
|
||||||
|
|
||||||
|
// initialize adc
|
||||||
|
adc_init();
|
||||||
|
|
||||||
|
// try calibrating temperature sensor if needed
|
||||||
|
tempsensor_cal();
|
||||||
|
|
||||||
|
// and now we wait.
|
||||||
|
while (1) {
|
||||||
|
// set sleep mode, then set for idle sleep (CPU off, all peripherals on)
|
||||||
|
set_sleep_mode(pirate_sleep_mode);
|
||||||
|
pirate_sleep_mode = SLEEP_MODE_IDLE;
|
||||||
|
|
||||||
|
// re-enable interrupts and nap.
|
||||||
|
sei();
|
||||||
|
sleep_mode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* func */
|
||||||
|
static void system_init()
|
||||||
|
{
|
||||||
|
// make SURE we are running at 8MHz
|
||||||
|
// do this by first enabling clock divider setup mode,
|
||||||
|
CLKPR = _BV(CLKPCE);
|
||||||
|
// and disabling any divider
|
||||||
|
CLKPR = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void system_io_init()
|
||||||
|
{
|
||||||
|
// enable break-before-make outputs on all IO
|
||||||
|
PORTCR |= (_BV(BBMA) | _BV(BBMB) | _BV(BBMC) | _BV(BBMD));
|
||||||
|
|
||||||
|
// set ALL pins as inputs except PB0
|
||||||
|
DDRA = 0x00;
|
||||||
|
DDRB = 0x01;
|
||||||
|
DDRC = 0x00;
|
||||||
|
DDRD = 0x00;
|
||||||
|
|
||||||
|
// and enable pullups (this reduces power consumption)
|
||||||
|
// in the case of PB0, set it LOW
|
||||||
|
PORTA = 0xff;
|
||||||
|
PORTB = 0xfe;
|
||||||
|
PORTC = 0xff;
|
||||||
|
PORTD = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* temperature */
|
||||||
|
uint8_t tempsensor_process()
|
||||||
|
{
|
||||||
|
int8_t temp_gain;
|
||||||
|
int8_t temp_adj;
|
||||||
|
|
||||||
|
temp_adj = adc_result[ADC_CHAN_TEMP] - temp_offset; // our offset adjusted temperature
|
||||||
|
temp_gain = temp_adj >> 3; // our gain adjust amount
|
||||||
|
while (temp_gain > 0) {temp_gain--; temp_adj--;}; // correct positive gain
|
||||||
|
while (temp_gain < 0) {temp_gain++; temp_adj++;}; // correct negative gain
|
||||||
|
|
||||||
|
// save temperature
|
||||||
|
return temp_adj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tempsensor_read()
|
||||||
|
{
|
||||||
|
if (adc_read_step == 0) {
|
||||||
|
// select temperature channel
|
||||||
|
adc_channel(ADC_CHAN_TEMP, ADC_REF_BANDGAP);
|
||||||
|
|
||||||
|
} else if (adc_read_step == 3) {
|
||||||
|
// we've waited 1.5ms so the bandgap voltage should have been set.
|
||||||
|
// start conversion after bandgap ref change timeout per datasheet
|
||||||
|
adc_start(4, 1);
|
||||||
|
|
||||||
|
} else if (adc_read_step > 3) {
|
||||||
|
adc_read_step--;
|
||||||
|
|
||||||
|
if (!adc_busy) {
|
||||||
|
// revert reference to AVCC...per the datasheet only changes to
|
||||||
|
// bandgap should take ~1ms but changes back to AVCC seem to
|
||||||
|
// take a while to be accurate as well
|
||||||
|
adc_channel(ADC_CHAN_GND, ADC_REF_AVCC);
|
||||||
|
adc_read_mode = 0;
|
||||||
|
temperature = tempsensor_process();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void tempsensor_cal()
|
||||||
|
{
|
||||||
|
// NOTE: CALIBRATION IS SINGLE-POINT TO 0 DEGREES CENTIGRADE! ICE YOUR PEGLEG, MOTHERFUCKER!
|
||||||
|
// todo: figure out wtf I meant by this note in 2014 (this is me in 2023)
|
||||||
|
// looking at the code, it looks like a pin needs manually changed to calibrate.
|
||||||
|
// todo: add a zeroing offset calibration command to the command protocol?
|
||||||
|
|
||||||
|
// is pin PA2 low? (pin 3 on attiny88 - is pulled up - short to pin 5 / ground somewhere)
|
||||||
|
if ((PINA & _BV(PINA2)) == 0) {
|
||||||
|
// turn on the ADC, wait for it to warm up
|
||||||
|
adc_init();
|
||||||
|
_delay_ms(100); // todo: is this right? this seems slow
|
||||||
|
|
||||||
|
// is the pin still low? not a glitch?
|
||||||
|
if ((PINA & _BV(PINA2)) == 0) {
|
||||||
|
// enable interrupts
|
||||||
|
sei();
|
||||||
|
|
||||||
|
// start reading the temp sensor; stall until adc is done
|
||||||
|
adc_read_mode = ADC_MODE_TEMPSENSOR;
|
||||||
|
tempsensor_read();
|
||||||
|
while (adc_busy);
|
||||||
|
|
||||||
|
// here's our correction factor!
|
||||||
|
temp_offset = adc_result[ADC_CHAN_TEMP];
|
||||||
|
|
||||||
|
// write it to eeprom
|
||||||
|
eeprom_write_word((uint16_t *)EEPROM_ADDR_TEMPCAL, temp_offset);
|
||||||
|
|
||||||
|
// and that's it - we're done.
|
||||||
|
adc_read_mode = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not saving a value - read the value from eeprom
|
||||||
|
temp_offset = eeprom_read_word((uint16_t *)EEPROM_ADDR_TEMPCAL);
|
||||||
|
|
||||||
|
// does it seem invalid?
|
||||||
|
if (temp_offset > 560) {
|
||||||
|
// yeah, this isn't right. load rough value for 0degC from datasheet.
|
||||||
|
// but you really should calibrate your chip, you lazy fuck.
|
||||||
|
temp_offset = 273;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* comms */
|
||||||
|
static inline uint8_t pegleg_data_tx()
|
||||||
|
{
|
||||||
|
uint8_t ret;
|
||||||
|
|
||||||
|
switch (comm_cmd) {
|
||||||
|
case MODE_EEPROM_READ: {
|
||||||
|
if (comm_data[0] < 64) {
|
||||||
|
i2c_slave_tx(eeprom_read_byte((uint8_t *)(uint16_t)comm_data[0]), 1);
|
||||||
|
ret = 1;
|
||||||
|
} else {
|
||||||
|
// invalid address...
|
||||||
|
i2c_disable_slave();
|
||||||
|
ret = 255;
|
||||||
|
}
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MODE_TEMPSENSOR_READ: {
|
||||||
|
i2c_slave_tx(temperature, 1);
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
case MODE_LIGHTSENSOR_READ: {
|
||||||
|
i2c_slave_tx(adc_result[comm_data[0] & 0x03] >> 2, 1);
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
// nothing active; invalid :(
|
||||||
|
i2c_disable_slave();
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t pegleg_cmd()
|
||||||
|
{
|
||||||
|
switch (comm_cmd) {
|
||||||
|
// no command: we just ACK this as we shouldn't ever get here
|
||||||
|
case MODE_NONE: {
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// standard commands
|
||||||
|
case MODE_EXT_CMD: { // used for more commands
|
||||||
|
if (comm_data_idx >= 1) {
|
||||||
|
comm_cmd = comm_data[1];
|
||||||
|
// set data index to last (will be reset on next data sent)
|
||||||
|
// and also reset timeout since this is effectively a new command
|
||||||
|
comm_data_idx = COMM_DATA_SIZE - 1;
|
||||||
|
comm_timeout = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MODE_LED_SET_LEVEL: { // sets PWM rate for the 8 PWM LEDs
|
||||||
|
if (comm_data[0] < 4) {
|
||||||
|
rgbled_pwm_lf[comm_data[0]] = comm_data[1];
|
||||||
|
} else if (comm_data[0] < 8) {
|
||||||
|
rgbled_pwm_rt[comm_data[0] - 4] = comm_data[1];
|
||||||
|
}
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MODE_TEMPSENSOR_CAL: {
|
||||||
|
// to use this function, make sure the temperature has been previously read.
|
||||||
|
// calculates the appropriate offset based on the reported temperature.
|
||||||
|
if (comm_data_idx >= 1) {
|
||||||
|
// update the offset
|
||||||
|
if (adc_result[ADC_CHAN_TEMP]) {
|
||||||
|
temp_offset = adc_result[ADC_CHAN_TEMP] - (int8_t)comm_data[1];
|
||||||
|
// write it to eeprom
|
||||||
|
eeprom_write_word((uint16_t *)EEPROM_ADDR_TEMPCAL, temp_offset);
|
||||||
|
// and that's it - we're done.
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
} else {
|
||||||
|
// no valid read performed; I fucking told you to do this!
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case MODE_EEPROM_READ: {
|
||||||
|
// our data packet is already set; ready for read.
|
||||||
|
// but if the host keeps writing...
|
||||||
|
if (comm_data_idx > 1) {
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MODE_EEPROM_WRITE: {
|
||||||
|
// TODO: implement
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// immediate commands
|
||||||
|
case MODE_TEMPSENSOR_READ: {
|
||||||
|
// attempt another read
|
||||||
|
if (!adc_read_mode) {
|
||||||
|
adc_read_mode = 0;
|
||||||
|
adc_read_step = 0;
|
||||||
|
adc_read_mode = ADC_MODE_TEMPSENSOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we are ready to read.
|
||||||
|
// data will probably be prior data unless the host waits. (need to verify)
|
||||||
|
comm_timeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MODE_LIGHTSENSOR_READ: {
|
||||||
|
if (!adc_read_mode) {
|
||||||
|
// set the led and step to first step
|
||||||
|
adc_read_mode = 0;
|
||||||
|
adc_read_step = 0;
|
||||||
|
rgbled_sensor_read_idx(comm_data[0]);
|
||||||
|
adc_read_mode = ADC_MODE_LIGHTSENSOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we are ready to read.
|
||||||
|
// data will probably be prior data unless the host waits.
|
||||||
|
comm_timeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MODE_SLEEP: {
|
||||||
|
// put this bitch to bed.
|
||||||
|
// we'll wake up when we get another I2C command.
|
||||||
|
pirate_sleep_mode = SLEEP_MODE_PWR_DOWN;
|
||||||
|
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extended commands
|
||||||
|
case MODE_AUX_PIN_SET: {
|
||||||
|
// TODO: come up with an implementation that isn't shitty
|
||||||
|
}
|
||||||
|
|
||||||
|
case MODE_AUX_PIN_GET: {
|
||||||
|
// TODO: implement when response sending is ...implemented
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MODE_LIGHTSENSOR_SENS: { // 0x10 0x19 <led 0-3> <sens 1-200>
|
||||||
|
if (comm_data_idx >= 1) {
|
||||||
|
if ((comm_data[0] <= 0x03) && (comm_data[1])) {
|
||||||
|
rgbled_sensor_sensitivity(comm_data[0], comm_data[1]);
|
||||||
|
}
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// invalid commands
|
||||||
|
default: {
|
||||||
|
// send NAK
|
||||||
|
comm_cmd = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t pegleg_data_rx(uint8_t data)
|
||||||
|
{
|
||||||
|
if (comm_cmd == MODE_NONE) {
|
||||||
|
// we aren't processing any commands, so this must be a new command/request.
|
||||||
|
// first 4 bits = command
|
||||||
|
comm_cmd = data >> 4;
|
||||||
|
// last 4 bits = optional data
|
||||||
|
comm_data[0] = data & 0x0f;
|
||||||
|
|
||||||
|
// clear our data watchdog and data index
|
||||||
|
comm_data_idx = 0;
|
||||||
|
comm_timeout = 0;
|
||||||
|
|
||||||
|
// if this is an immediate command, process it
|
||||||
|
if (data & 0x80) {
|
||||||
|
return pegleg_cmd();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// command in progress - add data and continue
|
||||||
|
comm_data_idx++;
|
||||||
|
comm_data_idx &= (COMM_DATA_SIZE - 1); // data will LOOP in case of problems; TODO: NAK on failure
|
||||||
|
comm_data[comm_data_idx] = data;
|
||||||
|
return pegleg_cmd();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "i2c_interrupt.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ISR handlers */
|
||||||
|
ISR(TIMER0_COMPA_vect)
|
||||||
|
{
|
||||||
|
/****
|
||||||
|
* this mainline loop runs at 2KHz, or 0.5ms.
|
||||||
|
* at the faster speed, this is ~3968 cycles/loop @8MHz.
|
||||||
|
****/
|
||||||
|
|
||||||
|
/* TIMEKEEPING */
|
||||||
|
// we only count a total of 10 seconds this way before we loop.
|
||||||
|
tim0_milli++;
|
||||||
|
if (tim0_milli >= 200) {
|
||||||
|
tim0_milli = 0;
|
||||||
|
tim0_centi++;
|
||||||
|
if (tim0_centi >= 100) {
|
||||||
|
tim0_centi = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2khz fix. our timer isn't evenly divisible to get our 2K, so we do this...
|
||||||
|
OCR0A = (OCR0A == TIMER0_COMPARE) ? TIMER0_COMPARE + 1 : TIMER0_COMPARE;
|
||||||
|
|
||||||
|
|
||||||
|
/* ADC / LIGHT SENSOR / TEMP SENSOR */
|
||||||
|
// main adc handler
|
||||||
|
if (adc_read_mode) {
|
||||||
|
switch (adc_read_mode) {
|
||||||
|
case ADC_MODE_TEMPSENSOR: {
|
||||||
|
tempsensor_read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ADC_MODE_LIGHTSENSOR: {
|
||||||
|
rgbled_sensor_read();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adc_read_step <= 0xfe) {
|
||||||
|
adc_read_step++;
|
||||||
|
}
|
||||||
|
} /* else {
|
||||||
|
if (adc_read_step != 0xff) {
|
||||||
|
adc_read_step++;
|
||||||
|
if (adc_read_step == 0xff) {
|
||||||
|
// disable the ADC
|
||||||
|
ADCSRA &= ~(_BV(ADEN));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} */ // NOTE: we need to keep the ADC enabled; it takes too long to warm up.
|
||||||
|
|
||||||
|
|
||||||
|
/* LEDs */
|
||||||
|
// TODO: test common cathode mode
|
||||||
|
// figure out next LED to update (order is always RGB(X) repeating)
|
||||||
|
if (adc_read_mode != ADC_MODE_LIGHTSENSOR) {
|
||||||
|
rgbled_idx++;
|
||||||
|
#ifdef LED_RGBX_4LED
|
||||||
|
rgbled_idx &= 0x03;
|
||||||
|
#else
|
||||||
|
if (rgbled_idx > 2) {
|
||||||
|
rgbled_idx = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// and now update them
|
||||||
|
rgbled_update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* COMMAND IO */
|
||||||
|
// stop processing the command if it isn't complete in 100ms.
|
||||||
|
if (comm_cmd != MODE_NONE) {
|
||||||
|
if (++comm_timeout >= 50) {
|
||||||
|
comm_cmd = MODE_NONE;
|
||||||
|
comm_timeout = 0;
|
||||||
|
i2c_disable_slave();
|
||||||
|
i2c_enable_slave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PROFILING */
|
||||||
|
// determine how much CPU usage we are consuming
|
||||||
|
tim0_profiler = TCNT0;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* timer.h
|
||||||
|
*
|
||||||
|
* Created: 5/21/2014 10:45:08 PM
|
||||||
|
* Author: true
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef TIMER_H_
|
||||||
|
#define TIMER_H_
|
||||||
|
|
||||||
|
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define TIMER0_COMPARE 62 - 1
|
||||||
|
#define TIMER1_COMPARE 252 - 1 // divisible by 63 which is set every other round for timer0
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t timer1_mode;
|
||||||
|
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
|
||||||
|
|
||||||
|
/* implementations */
|
||||||
|
inline static void timer0_init()
|
||||||
|
{
|
||||||
|
// make sure timer is enabled
|
||||||
|
PRR &= ~PRTIM0;
|
||||||
|
|
||||||
|
// enable timer with prescale divider /64, enable TOP mode
|
||||||
|
TCCR0A = _BV(CTC0) | (_BV(CS00) | _BV(CS01) | ~(_BV(CS02)));
|
||||||
|
|
||||||
|
// set TOP level to be 62 to 63 counts; this will result in 2KHz cycle @8MHz
|
||||||
|
OCR0A = TIMER0_COMPARE;
|
||||||
|
|
||||||
|
// clear timer
|
||||||
|
TCNT0 = 0;
|
||||||
|
|
||||||
|
// and enable OCA interrupt (we don't use overflow interrupt as we are in TOP mode)
|
||||||
|
TIMSK0 = _BV(OCIE0A);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define timer0_set_compare(x) OCR0A = x
|
||||||
|
|
||||||
|
inline static void timer1_init()
|
||||||
|
{
|
||||||
|
// make sure timer is enabled
|
||||||
|
PRR &= ~PRTIM1;
|
||||||
|
|
||||||
|
// clear PWM OCx
|
||||||
|
OCR1AH = 0xff; // sets temp register to 0xff
|
||||||
|
OCR1AL = 0xff;
|
||||||
|
OCR1BL = 0xff;
|
||||||
|
|
||||||
|
// clear timer
|
||||||
|
TCNT1H = 0; // sets temp register to 0
|
||||||
|
TCNT1L = 0;
|
||||||
|
|
||||||
|
// enable timer OC1 and OC2 clear on match / set at TOP, set to fast PWM mode 14 (ICR1 compare), prescaler off
|
||||||
|
// note: in PWM mode 14, pin PB0 can only be used as an output... =(
|
||||||
|
TCCR1A = (_BV(COM1A1)) | (_BV(COM1B1)) | (_BV(WGM11) | ~(_BV(WGM10)));
|
||||||
|
TCCR1B = (_BV(WGM12) | _BV(WGM13)) | (_BV(CS10));
|
||||||
|
TCCR1C = 0;
|
||||||
|
|
||||||
|
// store timer1 mode to allow enabling / disabling timer
|
||||||
|
timer1_mode = TCCR1A;
|
||||||
|
|
||||||
|
// set ICR compare to result in a PWM rate of 8MHz / 252, or 32256Hz
|
||||||
|
// This is 16 PWM updates per timer0 63-count period (16.25 per 62-count period)
|
||||||
|
// In practice we don't get the first PWM output, so we get:
|
||||||
|
// 15/16 PWM / (x) LEDs = 31.25% max duty for 3 LED, 23.43% max duty for 4 LED
|
||||||
|
ICR1L = TIMER1_COMPARE;
|
||||||
|
|
||||||
|
// set OC pins as outputs
|
||||||
|
DDRB |= (_BV(DDB2) | _BV(DDB1));
|
||||||
|
|
||||||
|
// disable interrupts
|
||||||
|
TIMSK1 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void timer1_pwm_reinit()
|
||||||
|
{
|
||||||
|
// enable pwm output on OCx pins
|
||||||
|
TCCR1A = (_BV(COM1A1)) | (_BV(COM1B1)) | (_BV(WGM11) | ~(_BV(WGM10)));
|
||||||
|
|
||||||
|
// set OC pins as outputs
|
||||||
|
DDRB |= (_BV(DDB2) | _BV(DDB1));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void timer1_set(uint16_t set)
|
||||||
|
{
|
||||||
|
TCNT1 = set;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define timer1_disable() TCCR1A = 0
|
||||||
|
#define timer1_enable() TCCR1A = timer1_mode;
|
||||||
|
|
||||||
|
#ifdef LED_COMMON_ANODE
|
||||||
|
#define timer1_set_oca(v) OCR1AL = TIMER1_COMPARE - v
|
||||||
|
#define timer1_set_ocb(v) OCR1BL = TIMER1_COMPARE - v
|
||||||
|
#else
|
||||||
|
#define timer1_set_oca(v) OCR1AL = TIMER1_COMPARE
|
||||||
|
#define timer1_set_ocb(v) OCR1BL = TIMER1_COMPARE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* TIMER_H_ */
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||||
|
# Atmel Studio Solution File, Format Version 11.00
|
||||||
|
Project("{54F91283-7BC4-4236-8FF9-10F437C3AD48}") = "wp_dc22_attiny88", "wp_dc22_attiny88.cproj", "{0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|AVR = Debug|AVR
|
||||||
|
Release|AVR = Release|AVR
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Debug|AVR.ActiveCfg = Debug|AVR
|
||||||
|
{0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Debug|AVR.Build.0 = Debug|AVR
|
||||||
|
{0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Release|AVR.ActiveCfg = Release|AVR
|
||||||
|
{0AAADF73-70F0-4C23-875D-53CCE8ABBF9B}.Release|AVR.Build.0 = Release|AVR
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
|
@ -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.172\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.172\include\avr\iotn88.h</AbsolutePath>
|
||||||
|
<Attribute></Attribute>
|
||||||
|
<Category>header</Category>
|
||||||
|
<Condition>C</Condition>
|
||||||
|
<FileContentHash>S2HUptOYqYmhL8kjFIMzIA==</FileContentHash>
|
||||||
|
<FileVersion></FileVersion>
|
||||||
|
<Name>include/avr/iotn88.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.172\templates\main.c</AbsolutePath>
|
||||||
|
<Attribute>template</Attribute>
|
||||||
|
<Category>source</Category>
|
||||||
|
<Condition>C Exe</Condition>
|
||||||
|
<FileContentHash>GD1k8YYhulqRs6FD1B2Hog==</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.172\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.172\gcc\dev\attiny88</AbsolutePath>
|
||||||
|
<Attribute></Attribute>
|
||||||
|
<Category>libraryPrefix</Category>
|
||||||
|
<Condition>GCC</Condition>
|
||||||
|
<FileContentHash i:nil="true" />
|
||||||
|
<FileVersion></FileVersion>
|
||||||
|
<Name>gcc/dev/attiny88</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.172/Atmel.ATtiny_DFP.pdsc</PackPath>
|
||||||
|
<PackVersion>1.3.172</PackVersion>
|
||||||
|
<PresentInProject>true</PresentInProject>
|
||||||
|
<ReferenceConditionId>ATtiny88</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>
|
|
@ -0,0 +1,171 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectVersion>7.0</ProjectVersion>
|
||||||
|
<ToolchainName>com.Atmel.AVRGCC8.C</ToolchainName>
|
||||||
|
<ProjectGuid>{0aaadf73-70f0-4c23-875d-53cce8abbf9b}</ProjectGuid>
|
||||||
|
<avrdevice>ATtiny88</avrdevice>
|
||||||
|
<avrdeviceseries>none</avrdeviceseries>
|
||||||
|
<OutputType>Executable</OutputType>
|
||||||
|
<Language>C</Language>
|
||||||
|
<OutputFileName>$(MSBuildProjectName)</OutputFileName>
|
||||||
|
<OutputFileExtension>.elf</OutputFileExtension>
|
||||||
|
<OutputDirectory>$(MSBuildProjectDirectory)\$(Configuration)</OutputDirectory>
|
||||||
|
<AssemblyName>wp_dc22_attiny88</AssemblyName>
|
||||||
|
<Name>wp_dc22_attiny88</Name>
|
||||||
|
<RootNamespace>wp_dc22_attiny88</RootNamespace>
|
||||||
|
<ToolchainFlavour>Native</ToolchainFlavour>
|
||||||
|
<KeepTimersRunning>true</KeepTimersRunning>
|
||||||
|
<OverrideVtor>false</OverrideVtor>
|
||||||
|
<CacheFlash>true</CacheFlash>
|
||||||
|
<ProgFlashFromRam>true</ProgFlashFromRam>
|
||||||
|
<RamSnippetAddress>0x20000000</RamSnippetAddress>
|
||||||
|
<UncachedRange />
|
||||||
|
<OverrideVtorValue>exception_table</OverrideVtorValue>
|
||||||
|
<BootSegment>2</BootSegment>
|
||||||
|
<eraseonlaunchrule>1</eraseonlaunchrule>
|
||||||
|
<AsfFrameworkConfig>
|
||||||
|
<framework-data>
|
||||||
|
<options />
|
||||||
|
<configurations />
|
||||||
|
<files />
|
||||||
|
<documentation help="" />
|
||||||
|
<offline-documentation help="" />
|
||||||
|
<dependencies>
|
||||||
|
<content-extension eid="atmel.asf" uuidref="Atmel.ASF" version="3.37" />
|
||||||
|
</dependencies>
|
||||||
|
</framework-data>
|
||||||
|
</AsfFrameworkConfig>
|
||||||
|
<preserveEEPROM>True</preserveEEPROM>
|
||||||
|
<avrtool>com.atmel.avrdbg.tool.simulator</avrtool>
|
||||||
|
<com_atmel_avrdbg_tool_simulator>
|
||||||
|
<ToolOptions xmlns="">
|
||||||
|
<InterfaceProperties>
|
||||||
|
<JtagEnableExtResetOnStartSession>false</JtagEnableExtResetOnStartSession>
|
||||||
|
</InterfaceProperties>
|
||||||
|
<InterfaceName>
|
||||||
|
</InterfaceName>
|
||||||
|
</ToolOptions>
|
||||||
|
<ToolType xmlns="">com.atmel.avrdbg.tool.simulator</ToolType>
|
||||||
|
<ToolNumber xmlns="">
|
||||||
|
</ToolNumber>
|
||||||
|
<ToolName xmlns="">Simulator</ToolName>
|
||||||
|
</com_atmel_avrdbg_tool_simulator>
|
||||||
|
<ResetRule>0</ResetRule>
|
||||||
|
<EraseKey />
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<ToolchainSettings>
|
||||||
|
<AvrGcc>
|
||||||
|
<avrgcc.common.Device>-mmcu=attiny88 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\gcc\dev\attiny88"</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.3.172\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.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.172\include</Value>
|
||||||
|
</ListValues>
|
||||||
|
</avrgcc.assembler.general.IncludePaths>
|
||||||
|
</AvrGcc>
|
||||||
|
</ToolchainSettings>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
|
||||||
|
<ToolchainSettings>
|
||||||
|
<AvrGcc>
|
||||||
|
<avrgcc.common.Device>-mmcu=attiny88 -B "%24(PackRepoDir)\atmel\ATtiny_DFP\1.3.172\gcc\dev\attiny88"</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.172\include</Value>
|
||||||
|
</ListValues>
|
||||||
|
</avrgcc.compiler.directories.IncludePaths>
|
||||||
|
<avrgcc.compiler.optimization.level>Optimize for size (-Os)</avrgcc.compiler.optimization.level>
|
||||||
|
<avrgcc.compiler.optimization.OtherFlags>-finline-functions</avrgcc.compiler.optimization.OtherFlags>
|
||||||
|
<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.warnings.ExtraWarnings>True</avrgcc.compiler.warnings.ExtraWarnings>
|
||||||
|
<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.172\include</Value>
|
||||||
|
</ListValues>
|
||||||
|
</avrgcc.assembler.general.IncludePaths>
|
||||||
|
<avrgcc.assembler.debugging.DebugLevel>Default (-Wa,-g)</avrgcc.assembler.debugging.DebugLevel>
|
||||||
|
</AvrGcc>
|
||||||
|
</ToolchainSettings>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="src\adc.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\adc.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\config.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\i2c.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\i2c_interrupt.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\led.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\led.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\main.c">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="src\timer.h">
|
||||||
|
<SubType>compile</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="src" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(AVRSTUDIO_EXE_PATH)\\Vs\\Compiler.targets" />
|
||||||
|
</Project>
|
Loading…
Reference in New Issue