1
0
mirror of https://github.com/AlexGyver/GyverCore.git synced 2025-04-19 08:42:16 +03:00
This commit is contained in:
Alex 2019-10-22 22:08:09 +03:00
parent 9fd247b99d
commit 2ee86f2a49
10 changed files with 214 additions and 91 deletions

View File

@ -7,27 +7,49 @@ uint32_t toggle_top; // предел счета для toggl'ов
bool willStop; // флаг позволяющий генерировать сигнал бесконечно долго bool willStop; // флаг позволяющий генерировать сигнал бесконечно долго
void tone(uint8_t pin , uint16_t freq, uint32_t duration = 0) { void tone(uint8_t pin , uint16_t freq, uint32_t duration = 0) {
tone_pin = pin; // присвоили номер пина для прерывания tone_pin = pin; // присвоили номер пина для прерывания
willStop = duration;// если введено время генерации - будет ненулевым willStop = duration;// если введено время генерации - будет ненулевым
toggle_top = (freq * duration) / 500; // расчет кол-ва toggl'ов за указанное время генерации toggle_top = (freq * duration) / 500; // расчет кол-ва toggl'ов за указанное время генерации
uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания
cli();//выключаем прерывания cli();//выключаем прерывания
TCCR2A = (1<<WGM21); // вкл CTC
TCCR2A = 0x2; // вкл CTC
TIMSK2 |= (1 << OCIE2A); //Вкл прерывание TIMSK2 |= (1 << OCIE2A); //Вкл прерывание
if(freq < 122){ // максимальный делитель
TCCR2B = 0x7; // присвоили делитель if (freq < (F_CPU >> 18)) { // ( < 240 Hz)
OCR2A = (15625/freq)-1; // рассчитали top для CTC TCCR2B = 0x7; // prescaler = 1024
OCR2A = ((F_CPU >> 11) / freq) - 1;
} }
if(freq > 244){ // минимальный делитель else if (freq < (F_CPU >> 15)) { // ( 240 - 480 Hz)
TCCR2B = 0x5; // по аналогии см выше TCCR2B = 0x6; // prescaler = 256
OCR2A = (62500/freq)-1; // по аналогии см выше OCR2A = ((F_CPU >> 9) / freq) - 1;
} }
else { // средний делитель else if (freq <= (F_CPU >> 14)) { // ( 480 - 970 Hz)
TCCR2B = 0x6; // по аналогии см выше TCCR2B = 0x5; // prescaler = 128
OCR2A = (125000/freq)-1; // по аналогии см выше OCR2A = ((F_CPU >> 8) / freq) - 1;
} }
else if (freq <= (F_CPU >> 13)) { // ( 970 - 1900 Hz)
TCCR2B = 0x4; // prescaler = 64
OCR2A = ((F_CPU >> 7) / freq) - 1;
}
else if (freq <= (F_CPU >> 11)) { // ( 1.9 - 7.8 kHz)
TCCR2B = 0x3; // prescaler = 32
OCR2A = ((F_CPU >> 6) / freq) - 1;
}
else if (freq <= (F_CPU >> 8)) { // ( 7.8 - 62 kHz)
TCCR2B = 0x2; // prescaler = 8
OCR2A = ((F_CPU >> 4) / freq) - 1;
}
else { // ( > 62 kHz)
TCCR2B = 0x1; // prescaler = 1
OCR2A = ((F_CPU >> 1) / freq) - 1;
}
toggle_counter = 0; // обнулили счетчик toggl'ов toggle_counter = 0; // обнулили счетчик toggl'ов
SREG = oldSREG; SREG = oldSREG;
} }
void noTone(uint8_t pin) { // если вызван noTone void noTone(uint8_t pin) { // если вызван noTone
@ -35,18 +57,16 @@ void noTone(uint8_t pin){ // если вызван noTone
uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания
cli();//выключаем прерывания cli();//выключаем прерывания
TIMSK2 &= ~ (1 << OCIE2A); // остановить прерывания TIMSK2 &= ~ (1 << OCIE2A); // остановить прерывания
TCCR2A = 0b00000011; // установить стандартные настройки для таймера 2 TCCR2A = 0x3; // установить стандартные настройки для таймера 2
TCCR2B = 0b00000100; TCCR2B = 0x4;
OCR2A = 0; //обнуляем регистр сравнения OCR2A = 0; //обнуляем регистр сравнения
TCCR2A &=~ ((1<<COM2A1)|(1<<COM2B1)); // откл регистры сравнения (подстраховка)
SREG = oldSREG; SREG = oldSREG;
} }
ISR(TIMER2_COMPA_vect) { // прерывание генерации ISR(TIMER2_COMPA_vect) { // прерывание генерации
if(toggle_counter < toggle_top || !willStop ){ // если количество toggl'ов не достигло предела или процесс бесконечен - генерация if (!willStop || toggle_counter < toggle_top ) { // если количество toggl'ов не достигло предела или процесс бесконечен - генерация
digitalToggle(tone_pin); // иневертируем состоние на ноге digitalToggle(tone_pin); // иневертируем состоние на ноге
toggle_counter++; // икремент счетчика toggle_counter++; // икремент счетчика
} }
} }

View File

@ -7,8 +7,33 @@
static uint8_t a_ref = DEFAULT; // глобальная переменная для хранения опорного напряжения АЦП static uint8_t a_ref = DEFAULT; // глобальная переменная для хранения опорного напряжения АЦП
// ============= DIGITAL ============= // ============= DIGITAL =============
void pinMode(uint8_t pin, uint8_t mode) // service func
{ uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания uint8_t getOutputRegister(uint8_t pin) {
if (pin < 8) return &PORTD;
else if (pin < 14) return &PORTB;
else return &PORTC;
}
uint8_t getInputRegister(uint8_t pin) {
if (pin < 8) return &PIND;
else if (pin < 14) return &PINB;
else return &PINC;
}
uint8_t getModeRegister(uint8_t pin) {
if (pin < 8) return &DDRD;
else if (pin < 14) return &DDRB;
else return &DDRC;
}
uint8_t getBitMask(uint8_t pin) {
if (pin < 8) return (1 << pin);
else if (pin < 14) return (1 << (pin - 8));
else return (1 << (pin - 14));
}
void pinMode(uint8_t pin, uint8_t mode) {
/*uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания
cli();//выключаем прерывания cli();//выключаем прерывания
switch (mode) { switch (mode) {
case 0: // input case 0: // input
@ -36,11 +61,27 @@ void pinMode(uint8_t pin, uint8_t mode)
} }
break; break;
} }
SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот*/
uint8_t *modeReg = getModeRegister(pin);
uint8_t *outputReg = getOutputRegister(pin);
uint8_t mask = getBitMask(pin);
switch (mode) {
case 0x00:
*modeReg &= ~ mask;
return;
case 0x01:
*modeReg |= mask;
return;
case 0x02:
*modeReg &= ~ mask;
*outputReg |= mask;
return;
}
} }
void digitalWrite(uint8_t pin, uint8_t x) { void digitalWrite(uint8_t pin, uint8_t x) {
uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания /*uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания
cli();//выключаем прерывания cli();//выключаем прерывания
switch (pin) { // откл pwm switch (pin) { // откл pwm
case 3: // 2B case 3: // 2B
@ -65,26 +106,39 @@ void digitalWrite(uint8_t pin, uint8_t x) {
if (pin < 8) bitWrite(PORTD, pin, x); if (pin < 8) bitWrite(PORTD, pin, x);
else if (pin < 14) bitWrite(PORTB, (pin - 8), x); else if (pin < 14) bitWrite(PORTB, (pin - 8), x);
else if (pin < 20) bitWrite(PORTC, (pin - 14), x); else if (pin < 20) bitWrite(PORTC, (pin - 14), x);
SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот*/
}
int digitalRead (uint8_t pin) { uint8_t *outputReg = getOutputRegister(pin);
if (pin < 8) return bitRead(PIND, pin); uint8_t mask = getBitMask(pin);
else if (pin < 14) return bitRead(PINB, pin - 8); if (x) *outputReg |= mask;
else if (pin < 20) return bitRead(PINC, pin - 14); else *outputReg &= ~ mask;
} }
void digitalToggle(uint8_t pin){ void digitalToggle(uint8_t pin){
uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания /*uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания
cli();//выключаем прерывания cli();//выключаем прерывания
if (pin < 8) bitToggle(PORTD, pin); if (pin < 8) bitToggle(PORTD, pin);
else if (pin < 14) bitToggle(PORTB, pin - 8); else if (pin < 14) bitToggle(PORTB, pin - 8);
else if (pin < 20) bitToggle(PORTC, pin - 14); else if (pin < 20) bitToggle(PORTC, pin - 14);
SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот*/
uint8_t *outputReg = getOutputRegister(pin);
uint8_t mask = getBitMask(pin);
*outputReg ^= mask;
} }
// ============= ANALOG =============
int digitalRead (uint8_t pin) {
/*if (pin < 8) return bitRead(PIND, pin);
else if (pin < 14) return bitRead(PINB, pin - 8);
else if (pin < 20) return bitRead(PINC, pin - 14); */
uint8_t *inputReg = getInputRegister(pin);
uint8_t mask = getBitMask(pin);
return ((*inputReg & mask) ? 1 : 0);
}
// ================ ANALOG ================
void analogPrescaler(uint8_t prescl) { void analogPrescaler(uint8_t prescl) {
uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания uint8_t oldSREG = SREG; // запомнинаем были ли включены прерывания
cli();//выключаем прерывания cli();//выключаем прерывания
@ -119,13 +173,11 @@ void analogPrescaler(uint8_t prescl) {
SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот SREG = oldSREG; // если прерывания не были включены - не включаем и наоборот
} }
void analogReference(uint8_t mode) void analogReference(uint8_t mode) {
{
a_ref = mode; // изменения будут приняты в силу при следующем analogRead() / analogStartConvert() a_ref = mode; // изменения будут приняты в силу при следующем analogRead() / analogStartConvert()
} }
int analogRead(uint8_t pin) int analogRead(uint8_t pin) {
{
analogStartConvert(pin); analogStartConvert(pin);
return analogGet(); return analogGet();
} }
@ -147,7 +199,7 @@ int analogGet() {
return ADCL | (ADCH << 8); // склеить и вернуть результат return ADCL | (ADCH << 8); // склеить и вернуть результат
} }
// ============= PWM ============= // ================= PWM =================
void analogWrite(uint8_t pin, int val) { void analogWrite(uint8_t pin, int val) {
if (val == 0) { if (val == 0) {
digitalWrite(pin, 0); digitalWrite(pin, 0);

View File

@ -10,6 +10,8 @@
*/ */
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
{ {
return pulseInLong(pin, state, timeout);
/*
// cache the port and bit of the pin in order to speed up the // cache the port and bit of the pin in order to speed up the
// pulse width measuring loop and achieve finer resolution. calling // pulse width measuring loop and achieve finer resolution. calling
// digitalRead() instead yields much coarser resolution. // digitalRead() instead yields much coarser resolution.
@ -28,6 +30,7 @@ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
return clockCyclesToMicroseconds(width * 16 + 16); return clockCyclesToMicroseconds(width * 16 + 16);
else else
return 0; return 0;
*/
} }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH /* Measures the length (in microseconds) of a pulse on the pin; state is HIGH

View File

@ -19,6 +19,11 @@ sbi KEYWORD2
analogStartConvert KEYWORD2 analogStartConvert KEYWORD2
analogGet KEYWORD2 analogGet KEYWORD2
bit_is_set KEYWORD2
bit_is_clear KEYWORD2
loop_until_bit_is_set KEYWORD2
loop_until_bit_is_clear KEYWORD2
begin KEYWORD2 begin KEYWORD2
end KEYWORD2 end KEYWORD2
peek KEYWORD2 peek KEYWORD2
@ -47,6 +52,7 @@ UINT64_MAX LITERAL1
INT64_MAX LITERAL1 INT64_MAX LITERAL1
UDR0 KEYWORD2 UDR0 KEYWORD2
UBRR0 KEYWORD2
UBRR0H KEYWORD2 UBRR0H KEYWORD2
UBRR0L KEYWORD2 UBRR0L KEYWORD2
UCSR0C KEYWORD2 UCSR0C KEYWORD2
@ -64,12 +70,16 @@ OCR2A KEYWORD2
TCNT2 KEYWORD2 TCNT2 KEYWORD2
TCCR2B KEYWORD2 TCCR2B KEYWORD2
TCCR2A KEYWORD2 TCCR2A KEYWORD2
OCR1B KEYWORD2
OCR1BH KEYWORD2 OCR1BH KEYWORD2
OCR1BL KEYWORD2 OCR1BL KEYWORD2
OCR1A KEYWORD2
OCR1AH KEYWORD2 OCR1AH KEYWORD2
OCR1AL KEYWORD2 OCR1AL KEYWORD2
ICR1 KEYWORD2
ICR1H KEYWORD2 ICR1H KEYWORD2
ICR1L KEYWORD2 ICR1L KEYWORD2
TCNT1 KEYWORD2
TCNT1H KEYWORD2 TCNT1H KEYWORD2
TCNT1L KEYWORD2 TCNT1L KEYWORD2
TCCR1C KEYWORD2 TCCR1C KEYWORD2
@ -113,6 +123,7 @@ TCNT0 KEYWORD2
TCCR0B KEYWORD2 TCCR0B KEYWORD2
TCCR0A KEYWORD2 TCCR0A KEYWORD2
GTCCR KEYWORD2 GTCCR KEYWORD2
EEAR KEYWORD2
EEARH KEYWORD2 EEARH KEYWORD2
EEARL KEYWORD2 EEARL KEYWORD2
EEDR KEYWORD2 EEDR KEYWORD2
@ -136,12 +147,6 @@ PINB KEYWORD2
###################################### ######################################
# Constants (LITERAL1) # Constants (LITERAL1)
####################################### #######################################
PWM_8BIT LITERAL1
PWM_10BIT LITERAL1
PWM_DEFAULT LITERAL1
PWM_8KHZ LITERAL1
PWM_31KHZ LITERAL1
THERMOMETR LITERAL1 THERMOMETR LITERAL1
A0 LITERAL1 A0 LITERAL1
A1 LITERAL1 A1 LITERAL1
@ -764,14 +769,3 @@ UDR0_4 LITERAL1
UDR0_5 LITERAL1 UDR0_5 LITERAL1
UDR0_6 LITERAL1 UDR0_6 LITERAL1
UDR0_7 LITERAL1 UDR0_7 LITERAL1

View File

@ -1,7 +1,7 @@
![CORE_PHOTO](https://github.com/AlexGyver/GyverCore/blob/master/gyverCoreLogo.jpg) ![CORE_PHOTO](https://github.com/AlexGyver/GyverCore/blob/master/gyverCoreLogo.jpg)
# GyverCore for ATmega328 # GyverCore for ATmega328
[**▶SWITCH TO ENGLISH◀**](https://github.com/AlexGyver/GyverCore/blob/master/README_eng.md) [**▶SWITCH TO ENGLISH◀**](https://github.com/AlexGyver/GyverCore/blob/master/README_eng.md)
**Версия 1.9.0 от 17.09.2019** **Версия 1.10.0 от 22.10.2019**
Быстрое и лёгкое ядро для Arduino IDE с расширенной конфигурацией. Быстрое и лёгкое ядро для Arduino IDE с расширенной конфигурацией.
Основано на оригинальном ядре Arduino версии 1.8.9, большинство функций заменены на более быстрые и лёгкие аналоги, убрано всё лишнее и не относящееся к микроконтроллеру ATmega328p, убран почти весь Wiring-мусор, код упрощён и причёсан. Добавлено несколько функций и интересных вариантов компиляции. Основано на оригинальном ядре Arduino версии 1.8.9, большинство функций заменены на более быстрые и лёгкие аналоги, убрано всё лишнее и не относящееся к микроконтроллеру ATmega328p, убран почти весь Wiring-мусор, код упрощён и причёсан. Добавлено несколько функций и интересных вариантов компиляции.
Разработано by Александр **AlexGyver** и Egor 'Nich1con' Zaharov Разработано by Александр **AlexGyver** и Egor 'Nich1con' Zaharov
@ -17,14 +17,16 @@
- Открой **Инструменты > Плата > Менеджер плат...** - Открой **Инструменты > Плата > Менеджер плат...**
- Подожди загрузку списка - Подожди загрузку списка
- Листай в самый низ, пока не увидишь **GyverCore** - Листай в самый низ, пока не увидишь **GyverCore**
- Выбери свою версию: **Win32**, **Win64** или **Linux**
- Жми **Установка** - Жми **Установка**
- Закрой окно - Закрой окно
- Выбери плату в **Инструменты > Плата > GyverCore > ATmega328/168 based** - Выбери плату в **Инструменты > Плата > GyverCore > ATmega328 based**
- Готово! - Готово!
- *Примечание*: файлы ядра находятся по пути C:\Users\Username\AppData\Local\Arduino15\packages\GyverCore\hardware\avr\1.9.0\ - *Примечание*: файлы ядра находятся по пути C:\Users\Username\AppData\Local\Arduino15\packages\GyverCore\hardware\avr\1.10.0\
### Ручная ### Ручная
- Файлы из папки GyverCore в этом репозитории положить по пути C:\Users\Username\AppData\Local\Arduino15\packages\GyverCore\hardware\avr\1.9.0\ - Файлы из папки GyverCore в этом репозитории положить по пути C:\Users\Username\AppData\Local\Arduino15\packages\GyverCore\hardware\avr\1.10.0\
- Новая версия компилятора лежит отдельно!
## Изменения ## Изменения
### Облегчено и ускорено ### Облегчено и ускорено
@ -34,9 +36,9 @@
----------------|-----------|-----------|---------- ----------------|-----------|-----------|----------
millis | 1.06 us | 1.00 us | - millis | 1.06 us | 1.00 us | -
micros | 1.19 us | 1.13 us | - micros | 1.19 us | 1.13 us | -
pinMode | 2.90 us | 0.57 us | 5.09 pinMode | 2.90 us | 0.50 us | 5.09
digitalWrite | 2.90 us | 0.57 us | 5.09 digitalWrite | 2.90 us | 0.50 us | 5.09
digitalRead | 2.45 us | 0.50 us | 4.90 digitalRead | 2.45 us | 0.00 us | ?
analogWrite | 4.15 us | 1.13 us | 3.67 analogWrite | 4.15 us | 1.13 us | 3.67
analogRead | 112.01 us | 5.41 us | 20.70 analogRead | 112.01 us | 5.41 us | 20.70
analogReference | 0.00 us | 0.00 us | - analogReference | 0.00 us | 0.00 us | -
@ -50,9 +52,9 @@ tone | 5.63 us | 2.40 us | 2.3
----------------|---------|-----------|--------------- ----------------|---------|-----------|---------------
millis | 26 | 24 | 2 millis | 26 | 24 | 2
micros | 24 | 20 | 4 micros | 24 | 20 | 4
pinMode | 114 | 24 | 90 pinMode | 114 | 2 | 112
digitalWrite | 200 | 24 | 176 digitalWrite | 200 | 2 | 198
digitalRead | 190 | 24 | 166 digitalRead | 190 | 0 | 190
analogWrite | 406 | 48 | 358 analogWrite | 406 | 48 | 358
analogRead | 32 | 72 | -40 analogRead | 32 | 72 | -40
analogReference | 0 | 22 | -22 analogReference | 0 | 22 | -22
@ -104,6 +106,7 @@ parseFloat | 1070 | 246 | 824
- **uart.begin(baudrate)** - запустить соединение по последовательному порту со скоростью baudrate - **uart.begin(baudrate)** - запустить соединение по последовательному порту со скоростью baudrate
- **uart.end()** - выключить сериал - **uart.end()** - выключить сериал
- **uart.peek()** - вернуть крайний байт из буфера, не убирая его оттуда - **uart.peek()** - вернуть крайний байт из буфера, не убирая его оттуда
- **uart.flush()** - ждать принятия данных
- **uart.clear()** - очистить буфер - **uart.clear()** - очистить буфер
- **uart.read()** - вернуть крайний байт из буфера, убрав его оттуда - **uart.read()** - вернуть крайний байт из буфера, убрав его оттуда
- **uart.write(val)** - запись в порт - **uart.write(val)** - запись в порт
@ -177,7 +180,7 @@ parseFloat | 1070 | 246 | 824
--- ---
**Compiler version** - версия компилятора **Compiler version** - версия компилятора
- **default v5.4.0** - встроенная в IDE версия компилятора - **default v5.4.0** - встроенная в IDE версия компилятора
- **avr-gcc v8.3.0** - новая версия компилятора: компилирует быстрее, скетчи весят меньше! - **avr-gcc v8.3.0** - новая версия компилятора: компилирует быстрее, скетчи весят меньше! Билд взял [отсюда](https://blog.zakkemble.net/avr-gcc-builds/)
## Больше контроля! ## Больше контроля!
Для большего контроля за периферией микроконтроллера рекомендую попробовать следующие наши библиотеки: Для большего контроля за периферией микроконтроллера рекомендую попробовать следующие наши библиотеки:
@ -258,3 +261,9 @@ parseFloat | 1070 | 246 | 824
- Ещё чуть ускорен uart - Ещё чуть ускорен uart
- 1.9.0 - 1.9.0
- Вшита новая версия компилятора avr-gcc - Вшита новая версия компилятора avr-gcc
- 1.10.0
- Расширена подсветка синтаксиса
- Пофикшен tone
- Пофикшен pulseIn (но выдаёт разрешение 4 мкс)
- Добавлен avr-gcc v8 под Win32 и Linux
- Ускорен IO

3
avr-gcc/README.md Normal file
View File

@ -0,0 +1,3 @@
#AVR-GCC
Версия 8.3.0 взята [отсюда](https://blog.zakkemble.net/avr-gcc-builds/)
Более новые версии делают код тяжелее по Flash памяти

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -260,7 +260,49 @@
{"name": "ATmega328 based boards"} {"name": "ATmega328 based boards"}
], ],
"toolsDependencies": [] "toolsDependencies": []
} },
{
"name": "GyverCore",
"architecture": "avr",
"version": "1.10.0 win64",
"category": "Contributed",
"url": "https://github.com/AlexGyver/GyverCore/releases/download/GyverCore-1.10.0/GyverCore_win64.zip",
"archiveFileName": "GyverCore.zip",
"checksum": "MD5:c2ec5c7b0d64913faecafac966d64fab",
"size": "59016998",
"boards": [
{"name": "ATmega328 based boards"}
],
"toolsDependencies": []
},
{
"name": "GyverCore",
"architecture": "avr",
"version": "1.10.0 win32",
"category": "Contributed",
"url": "https://github.com/AlexGyver/GyverCore/releases/download/GyverCore-1.10.0/GyverCore_win32.zip",
"archiveFileName": "GyverCore.zip",
"checksum": "MD5:c2ec5c7b0d64913faecafac966d64fab",
"size": "59016998",
"boards": [
{"name": "ATmega328 based boards"}
],
"toolsDependencies": []
},
{
"name": "GyverCore",
"architecture": "avr",
"version": "1.10.0 linux",
"category": "Contributed",
"url": "https://github.com/AlexGyver/GyverCore/releases/download/GyverCore-1.10.0/GyverCore_linux.zip",
"archiveFileName": "GyverCore.zip",
"checksum": "MD5:c2ec5c7b0d64913faecafac966d64fab",
"size": "59016998",
"boards": [
{"name": "ATmega328 based boards"}
],
"toolsDependencies": []
},
], ],
"tools": [] "tools": []
} }