PROGMEM tricks

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

qwone пишет:

sadman41 пишет:
Простите, не понял вопроса. Приведите пример как "хорошо". Можно на JS или что Вы там под "языками для web" понимаете.

Тю . это легко и не очень. всего надо освоить это http://www.solarix.ru/for_developers/cpp/stl/stl.shtml
Но скорее всего данный камень это уже не потянет.


сплю уже... но ведь говорили не раз -- есть 100500 адаптаций стандартных темплейтов под АВР и ардуину.

b707
Offline
Зарегистрирован: 26.05.2017

qwone пишет:

Тю . это легко и не очень. всего надо освоить это http://www.solarix.ru/for_developers/cpp/stl/stl.shtml

Но скорее всего данный камень это уже не потянет.

Потянет. В простейшем виде это называется map. его к ардуино давно прикрутили,

std::map<char,int> first;

  first['a']=10;
  first['b']=30;
  first['c']=50;
  first['d']=70;

правда, чтобы сделать ключом map массив char* - надо прилично извратится и вроде как написать свои функции сравнения строк.

То есть в конечном итоге вся эта красота скрывает внутри теже самые функции поиска нужного значения в структуре путем перебора элементов, от которых Садман хотел бы избавится :)

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

sadman41 пишет:
хотелось бы получить удобный маппинг (в обе стороны)
тут можно долго спорить есть это в языке или нет, т.к. есть оно во внешней библиотеке STL (вроде как не в языке), но эта библиотека стандартизована в ISO-IEC 14882-2017 (нужные нам контейнеры - разд. 26.4, стр. 896).

Другая беда, что в поставке IDE (как и Atmel Studio) библиотеки STL нет. Она, конечно же есть для gnu'сного компилятора, но с этими продуктами не поставляется. Поставить можно. Я как-то ставил. Что-то там было непросто (может потому,  что я плохо знаю gcc) но в итоге поставилось и работало.

sadman41, Вы не из МГУ часом?

sadman41
Offline
Зарегистрирован: 19.10.2016

ЕвгенийП пишет:

sadman41 пишет:
хотелось бы получить удобный маппинг (в обе стороны)
тут можно долго спорить есть это в языке или нет, т.к. есть оно во внешней библиотеке STL (вроде как не в языке),

...

Поставить можно. Я как-то ставил. Что-то там было непросто (может потому,  что я плохо знаю gcc) но в итоге поставилось и работало.

Непросто - это плохо, конечно. В опенсорц-прожект не выплеснешь исходник просто так... Что ж, раз волшебства нет, попробую заварить чаёк на шаблонах. 

ЕвгенийП пишет:
sadman41, Вы не из МГУ часом?

Бывало, конечно, мне льстили в жизни, но чтобы вот вот так - в первый раз. Про МГУ я знаю только то, что в районе Мехмата что ли... снег идёт вверх. 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sadman41 пишет:

Бывало, конечно, мне льстили в жизни, но чтобы вот вот так - в первый раз.

Улыбнули с утра...производство...звонок с сообщением о неисправности ТПА...прихожу...слышу в свой адрес ..."самый умный мужчина Советского Союза"...в ответ - ну Вы и льстите...а по существу...работали исключительно матери-одиночки, зарплата от 350 до 400, надо только чтобы станки работали непрерывно )))
Извиняюсь за оффтоп
PS Видимо Евгений Петрович увидел ШКОЛУ ПРЕПОДАВАНИЯ, а УЧИТЕЛЯ встречаются везде )))
 

sadman41
Offline
Зарегистрирован: 19.10.2016

Нет, конечно уборщиком меня бы взяли, наверное, в МГУ... Однако, мои столкновения с высокими материями ограничиваются разовым  прохождением мимо незамерзающего пруда в ИТЭФе с последующим употребле... обменом опытом с коллегами и наблюдением за всклокоченными людьми в трико, которые в ночи черкали странные формулы на досках, развешенных по коридорам.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

[quote=ua6em увидел ШКОЛУ ПРЕПОДАВАНИЯ[/quote]Нет, я увидел (уже в нескольких местах) использование словечек и выражений, которые, хотя и являются общеизвестными, но почему-то чаще всего используются людьми учившимися или работающими в МГУ (может это только по моим знакомым так - не знаю)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

[quote=ua6em увидел ШКОЛУ ПРЕПОДАВАНИЯ

Нет, я увидел (уже в нескольких местах) использование словечек и выражений, которые, хотя и являются общеизвестными, но почему-то чаще всего используются людьми учившимися или работающими в МГУ (может это только по моим знакомым так - не знаю)

[/quote]

Мир тесен, может его учитель учился или тесно общался с выходцами МГУ )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
void setup() {
  Serial.begin(9600);
  Serial.println("ffff");
  Serial.println(reinterpret_cast<const __FlashStringHelper *>PSTR("qwwhhhhhhhbbbbbbbbbbbbbbbbbbbhhhhhhhe"));
  Serial.println(reinterpret_cast<const __FlashStringHelper *>(__extension__({static const char __c[] PROGMEM = "qwwhhhhhhhbbbbbbbbbbbbbbbbbbbhhhhhhhe"; &__c[0];})));
}
void loop() {
}
Скетч компилируется и работает

 

lean_74
Offline
Зарегистрирован: 22.12.2015

qwone пишет:

Скетч компилируется и работает

да гошишь...

exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
C:\Users\9D20~1\AppData\Local\Temp\ccVhdSDj.ltrans0.ltrans.o:(.rodata+0x6): undefined reference to `Print::write(unsigned char const*, unsigned int)'
 
c:/arduino/arduino-1.8.7/hardware/tools/avr/bin/../lib/gcc/avr/5.4.0/../../../../avr/lib/avr5/crtatmega328p.o:(.init9+0x0): undefined reference to `main'
 
collect2.exe: error: ld returned 1 exit status
 
exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
 
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

у меня скомпилировался тоже, что я не так сделал )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
void setup() {
  Serial.begin(9600);
  Serial.println("ffff");
  Serial.println(reinterpret_cast<const __FlashStringHelper *>PSTR("qwwhhhhhhhbbbbbbbbbbbbbbbbbbbhhhhhhhe"));
  Serial.println(reinterpret_cast<const __FlashStringHelper *>(__extension__({static const char __c[] PROGMEM = "qwwhhhhhhhbbbbbbbbbbbbbbbbbbbhhhhhhhe"; &__c[0];})));
}
void loop() {
}
/*Для Нано
  Скетч использует 1606 байт (5%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 190 байт (9%) динамической памяти, оставляя 1858 байт для локальных переменных. Максимум: 2048 байт.
*/
/* Результат
ffff
qwwhhhhhhhbbbbbbbbbbbbbbbbbbbhhhhhhhe
qwwhhhhhhhbbbbbbbbbbbbbbbbbbbhhhhhhhe
*/

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Чуть более извращённый генератор HTML-страницы, использующий шаблонные функции для доступа к однотипным массивам-"справочникам", расположенным в Program Space. Надеюсь, что совсем грубых ляпов в темплейтах не наделал. Но, если не справился, - напишите. 

//#pragma GCC optimize ("O0")
#include <avr/pgmspace.h>

// *** Strings ***
const char text_EMPTY_STRING[]       PROGMEM = "";
const char text_SUPERHERO_SCHEDULE[] PROGMEM = "Superhero's schedule";

const char name_DAY_MONDAY[]         PROGMEM = "Monday";
const char name_DAY_TUESDAY[]        PROGMEM = "Tuesday";
const char name_DAY_WEDNESDAY[]      PROGMEM = "Wednesday";
const char name_DAY_THURSDAY[]       PROGMEM = "Thursday";
const char name_DAY_FRIDAY[]         PROGMEM = "Friday";
const char name_DAY_SATURDAY[]       PROGMEM = "Saturday";
const char name_DAY_SUNDAY[]         PROGMEM = "Sunday";

const char name_COLOR_VIOLET[]       PROGMEM = "Violet";
const char name_COLOR_INDIGO[]       PROGMEM = "Indigo";
const char name_COLOR_BLUE[]         PROGMEM = "Blue";
const char name_COLOR_GREEN[]        PROGMEM = "Green";
const char name_COLOR_YELLOW[]       PROGMEM = "Yellow";
const char name_COLOR_ORANGE[]       PROGMEM = "Orange";
const char name_COLOR_RED[]          PROGMEM = "Red";

const char html_CLASS_DAY_WORK[]     PROGMEM = "dwrk";
const char html_CLASS_DAY_REST[]     PROGMEM = "drst";
const char html_CLASS_IS_TODAY[]     PROGMEM = "istd";

const char html_CLASS_COLOR_VIOLET[] PROGMEM = "cvi";
const char html_CLASS_COLOR_INDIGO[] PROGMEM = "cin";
const char html_CLASS_COLOR_BLUE[]   PROGMEM = "cbl";
const char html_CLASS_COLOR_GREEN[]  PROGMEM = "cgr";
const char html_CLASS_COLOR_YELLOW[] PROGMEM = "cye";
const char html_CLASS_COLOR_ORANGE[] PROGMEM = "cor";
const char html_CLASS_COLOR_RED[]    PROGMEM = "cre";

const char html_CSS_TABLE[]          PROGMEM = "\n<style>\n\
body,html{height:100%;background-color:#F0F0F0}\n\
table{width:100%}\n\
th{border-bottom:1px solid #999;padding:10px}\n\
td{margin:0;padding:0}\n\
.cvi{color:DarkViolet}\n\
.cin{color:Indigo}\n\
.cbl{color:DarkSlateBlue}\n\
.cgr{color:LimeGreen}\n\
.cye{color:Gold}\n\
.cor{color:Coral}\n\
.cre{color:IndianRed}\n\
.dwrk{background-color:MistyRose}\n\
.drst{background-color:LemonChiffon}\n\
.istd{font-weight:700}\n\
</style>\n\n";

// *** Enumes ***

typedef enum { diMonday = 1, diTuesday, diWednesday, diThursday, diFriday, diSaturday, diSunday } dayId_t;
typedef enum { ciViolet = 10, ciIndigo, ciBlue, ciGreen, ciYellow, ciOrange, ciRed } colorId_t;

// *** Structs ***
typedef struct {
  dayId_t id;
  PGM_P name;
  PGM_P htmlClass;
  colorId_t colorId;
} dayOfWeek_t;

typedef struct {
  colorId_t id;
  PGM_P name;
  PGM_P htmlClass;
} colorOfSocks_t;

// *** Data ***

const dayOfWeek_t daysOfWeek[]      PROGMEM = {
  { diMonday,    name_DAY_MONDAY,    html_CLASS_DAY_WORK, ciViolet },
  { diTuesday,   name_DAY_TUESDAY,   html_CLASS_DAY_WORK, ciIndigo },
  { diWednesday, name_DAY_WEDNESDAY, html_CLASS_DAY_WORK, ciBlue   },
  { diThursday,  name_DAY_THURSDAY,  html_CLASS_DAY_WORK, ciGreen  },
  { diFriday,    name_DAY_FRIDAY,    html_CLASS_DAY_WORK, ciYellow },
  { diSaturday,  name_DAY_SATURDAY,  html_CLASS_DAY_REST, ciOrange },
  { diSunday,    name_DAY_SUNDAY,    html_CLASS_DAY_REST, ciRed    }
};

const colorOfSocks_t colorsOfSocks[] PROGMEM = {
  { ciViolet, name_COLOR_VIOLET, html_CLASS_COLOR_VIOLET  },
  { ciIndigo, name_COLOR_INDIGO, html_CLASS_COLOR_INDIGO  },
  { ciBlue,   name_COLOR_BLUE,   html_CLASS_COLOR_BLUE    },
  { ciGreen,  name_COLOR_GREEN,  html_CLASS_COLOR_GREEN   },
  { ciYellow, name_COLOR_YELLOW, html_CLASS_COLOR_YELLOW  },
  { ciOrange, name_COLOR_ORANGE, html_CLASS_COLOR_ORANGE  },
  { ciRed,    name_COLOR_RED,    html_CLASS_COLOR_RED     }
};

// *** Helpers ***

#define arraySize(_array) ( sizeof(_array) / sizeof(*(_array)) )
#define FSH_P(p) (reinterpret_cast<const __FlashStringHelper *>(p))

// *** Templates ***

// structure.id => structure.htmlClass
template < typename ID_TYPE, typename ITEM_TYPE> PGM_P getHtmlClassById(const ID_TYPE _itemId, ITEM_TYPE * _refArray, size_t _refArraySize) {
  PGM_P ptrItemName = NULL;
  ID_TYPE currentItemId;
  for (size_t i = 0x00; i < _refArraySize; i++) {
    memcpy_P(&currentItemId, &(_refArray[i].id), sizeof(ID_TYPE));
    if (_itemId == currentItemId) {
      ptrItemName = pgm_read_word(&_refArray[i].htmlClass);
      break;
    }
  }
  return ptrItemName;
}

// structure.id => structure.name
template < typename ID_TYPE, typename ITEM_TYPE> PGM_P getNameById(const ID_TYPE _itemId, const ITEM_TYPE * _refArray, size_t _refArraySize) {
  PGM_P ptrItemName = NULL;
  ID_TYPE currentItemId;
  for (size_t i = 0x00; i < _refArraySize; i++) {
    memcpy_P(&currentItemId, &(_refArray[i].id), sizeof(ID_TYPE));
    if (_itemId == currentItemId) {
      ptrItemName = pgm_read_word(&_refArray[i].name);
      break;
    }
  }
  return ptrItemName;
}

// structure.name => structure.id
template <typename ID_TYPE, typename ITEM_TYPE> ID_TYPE getIdByName(char  *_itemName, const ITEM_TYPE * _refArray, size_t _refArraySize) {
  ID_TYPE itemId = NULL;
  for (size_t i = 0x00; i < _refArraySize; i++) {
    PGM_P ptrItemName = pgm_read_word(&_refArray[i].name);
    if (!strcmp_P(_itemName, ptrItemName)) {
      memcpy_P(&itemId, &( _refArray[i].id), sizeof(ID_TYPE));
      break;
    }
  }
  return itemId;
}

// *** Functions ***

// Web page printer
void printPage(Stream& _stream, const dayId_t todayId) {
  char buffer[100];
  dayId_t   someDayId;
  colorId_t someColorId;

  // Print the header of the page and table
  snprintf_P(buffer, sizeof(buffer), PSTR("<!DOCTYPE HTML><html><head><meta charset=\"utf-8\">\n<title>%S</title></head><body>\n<table>\n"), text_SUPERHERO_SCHEDULE);
  _stream.print(buffer);
  
  _stream.print(FSH_P(html_CSS_TABLE));

  snprintf_P(buffer, sizeof(buffer), PSTR("<h2>%S</h2>\n<tr><th>Day</th><th>Socks color</th><tr>\n"), text_SUPERHERO_SCHEDULE);
  _stream.print(buffer);

  for (uint8_t i = 0; i < arraySize(daysOfWeek); i++) {

    // Just take every Day and his color as enum from PROGMEM array of structures
    memcpy_P(&someDayId,   &(daysOfWeek[i].id),      sizeof(dayId_t));
    memcpy_P(&someColorId, &(daysOfWeek[i].colorId), sizeof(colorId_t));

    // Fetch day's data from PROGMEM store
    PGM_P someDayName = getNameById(someDayId, daysOfWeek, arraySize(daysOfWeek));
    PGM_P someDayHtmlClass = getHtmlClassById(someDayId, daysOfWeek, arraySize(daysOfWeek));
    PGM_P isTodayHtmlClass = (todayId == someDayId) ? html_CLASS_IS_TODAY : text_EMPTY_STRING;

    // Fetch color's info from PROGMEM store
    PGM_P socksColorName = getNameById(someColorId, colorsOfSocks, arraySize(colorsOfSocks));
    PGM_P socksColorHtmlClass = getHtmlClassById(someColorId, colorsOfSocks, arraySize(colorsOfSocks));

    // Print out the table row
    snprintf_P(buffer, sizeof(buffer), PSTR("<tr class=\"%S %S\"><td>%S</td><td class=\"%S\">%S</td><tr>\n"), someDayHtmlClass, isTodayHtmlClass, someDayName, socksColorHtmlClass, socksColorName);
    _stream.print(buffer);
  }

  // Print the footer of the page and table
  snprintf_P(buffer, sizeof(buffer), PSTR("</table>\n<body><html>\n") );
  _stream.print(buffer);
}

void setup() {
  char today[] = "Sunday";
  dayId_t todayId;

  Serial.begin(115200);
  Serial.println(F("PROGMEM: Superhero's schedule page generator\n\n"));

  // Take today's id
  todayId = getIdByName<dayId_t, dayOfWeek_t>(today, daysOfWeek, arraySize(daysOfWeek));
  // Make HTML page
  printPage(Serial, todayId);
}

void loop() { }