покритикуйте вывод на экран

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

заглушка

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

Критикую

Voodoo Doll пишет:

заглушка

С заглавной буквы нужно было!

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016
#define INT_UPD_DIG (500)

byte digits[13]={B01000000,B01111001,B00100100,B00110000,B00011001,B00010010,B00000010,B01111000,B00000000,B00010000,
               //    0         1         2         3         4         5         6         7         8         9
                 B01111111,B00001110,B01000110};
               //  blank      freq      cap

byte n=0;
unsigned long last_dig_upd=millis(),
              read_data, read_div, read_mod;
byte disp_data[12]={0,0,0,0,0,0,0,0,0,0,0,0};  // 0..6: physical display shadow, 7..11: divide shadow

void setup(){
  DDRD|=B11011111;
  DDRB|=B00000111;
  DDRC|=B00111000;
  PORTD|=B11000011;
  PORTB|=B00000111;
}

void loop(){
  byte i=6,j=0;
  bool found_nonzero=false;

  while(i<11){
    divmod10(read_data, read_div, read_mod);
    fill_disp_data(i);
    read_data=read_mod;
    i++;
  }
  fill_disp_data(11);

  for(i=11;i>=6;i--){
    disp_data[j]=disp_data[i];
    if(disp_data[i]>0) found_nonzero=true;
    if(!found_nonzero) disp_data[j]=10; // write blank to kill leading zero
    j++;
  }
  
  proc_disp();
}

void divmod10(uint32_t in, uint32_t &div, uint32_t &mod){
  uint32_t x=(in>>1);
  uint32_t q=x;
  q= (q>>8) + x;
  q= (q>>8) + x;
  q= (q>>8) + x;
  q= (q>>8) + x + 1;
  x= q;
  q= (q>>1) + x;
  q= (q>>3) + x;
  q= (q>>1) + x;
  div = (q >> 3);
  mod = in - (((div << 2) + div) << 1);
}

void proc_disp(){
  byte n_dig=0;
  switch(n_dig){
    case 0: PORTC|=B00110000; PORTD|=B00011100; PORTC&=B11110111; break; // whether common anode 1 is on
    case 1: PORTC|=B00011000; PORTD|=B00011100; PORTC&=B11011111; break; // ca 2
    case 2: PORTC|=B00101000; PORTD|=B00011100; PORTC&=B11101111; break; // ca 3
    case 3: PORTC|=B00111000; PORTD|=B00001100; PORTD&=B11101111; break; // ca 4
    case 4: PORTC|=B00111000; PORTD|=B00011000; PORTD&=B11111011; break; // ca 5
    case 5: PORTC|=B00111000; PORTD|=B00010100; PORTD&=B11110111; break; // ca 6
  }
  n_dig++;
  if(n_dig>5) n_dig=0;

  if(millis()-last_dig_upd>=INT_UPD_DIG){
    if(digits[n]&B00000001){ PORTD|=B00000001; }else{ PORTD&=B11111110; }  // whether G is off
    if(digits[n]&B00000010){ PORTD|=B00000010; }else{ PORTD&=B11111101; }  // F
    if(digits[n]&B00000100){ PORTB|=B00000001; }else{ PORTB&=B11111110; }  // E
    if(digits[n]&B00001000){ PORTD|=B01000000; }else{ PORTD&=B10111111; }  // D
    if(digits[n]&B00010000){ PORTD|=B10000000; }else{ PORTD&=B01111111; }  // C
    if(digits[n]&B00100000){ PORTB|=B00000100; }else{ PORTB&=B11111011; }  // B
    if(digits[n]&B01000000){ PORTB|=B00000010; }else{ PORTB&=B11111101; }  // A
    n++;
    if(n>12) n=0;
    last_dig_upd=millis();
  }
}

void fill_disp_data(byte pos){
  switch(pos){
    case 6:  if(read_div==0)      disp_data[pos]=0;
             if(read_div==100000) disp_data[pos]=1;
             if(read_div==200000) disp_data[pos]=2;
             if(read_div==300000) disp_data[pos]=3;
             if(read_div==400000) disp_data[pos]=4;
             if(read_div==500000) disp_data[pos]=5;
             if(read_div==600000) disp_data[pos]=6;
             if(read_div==700000) disp_data[pos]=7;
             if(read_div==800000) disp_data[pos]=8;
             if(read_div==900000) disp_data[pos]=9; break;
    case 7:  if(read_div==0)      disp_data[pos]=0;
             if(read_div==10000)  disp_data[pos]=1;
             if(read_div==20000)  disp_data[pos]=2;
             if(read_div==30000)  disp_data[pos]=3;
             if(read_div==40000)  disp_data[pos]=4;
             if(read_div==50000)  disp_data[pos]=5;
             if(read_div==60000)  disp_data[pos]=6;
             if(read_div==70000)  disp_data[pos]=7;
             if(read_div==80000)  disp_data[pos]=8;
             if(read_div==90000)  disp_data[pos]=9; break;
    case 8:  if(read_div==0)      disp_data[pos]=0;
             if(read_div==1000)   disp_data[pos]=1;
             if(read_div==2000)   disp_data[pos]=2;
             if(read_div==3000)   disp_data[pos]=3;
             if(read_div==4000)   disp_data[pos]=4;
             if(read_div==5000)   disp_data[pos]=5;
             if(read_div==6000)   disp_data[pos]=6;
             if(read_div==7000)   disp_data[pos]=7;
             if(read_div==8000)   disp_data[pos]=8;
             if(read_div==9000)   disp_data[pos]=9; break;
    case 9:  if(read_div==0)      disp_data[pos]=0;
             if(read_div==100)    disp_data[pos]=1;
             if(read_div==200)    disp_data[pos]=2;
             if(read_div==300)    disp_data[pos]=3;
             if(read_div==400)    disp_data[pos]=4;
             if(read_div==500)    disp_data[pos]=5;
             if(read_div==600)    disp_data[pos]=6;
             if(read_div==700)    disp_data[pos]=7;
             if(read_div==800)    disp_data[pos]=8;
             if(read_div==900)    disp_data[pos]=9; break;
    case 10: if(read_div==0)      disp_data[pos]=0;
             if(read_div==10)     disp_data[pos]=1;
             if(read_div==20)     disp_data[pos]=2;
             if(read_div==30)     disp_data[pos]=3;
             if(read_div==40)     disp_data[pos]=4;
             if(read_div==50)     disp_data[pos]=5;
             if(read_div==60)     disp_data[pos]=6;
             if(read_div==70)     disp_data[pos]=7;
             if(read_div==80)     disp_data[pos]=8;
             if(read_div==90)     disp_data[pos]=9; break;
    case 11: disp_data[pos]=read_mod;               break;
  }
}

гавно?

Вопросы:

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

    case 9:  /*......*/
             if(read_div==400)    disp_data[9]=4;

вместо

    case 9:  /*......*/
             if(read_div==400)    disp_data[pos]=4;

- как оно вообще, сравнить вместо деления, по скорости? всё равно в той переменной будут только цифры аля 400, 70000, 200000 и т д, то есть одна полезная цифра плюс куча нулей, которые надо делить только ради того чтобы понять что это допустим 2 раза по 100000.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

по схеме: kingbright ba-56 два штуки, общие кинуты на pnp-транзисторы (т. е нулём включаются и аноды и катоды)

upd: на процедуру proc_disp пока можно не обращать внимания, там тестовая версия из голого loop() (тикающие 0-9, blank, F, C цифры)

фак, только что дошло что я считаю деление не с той стороны числа. ладно пофиг, перепишу и выложу, думаю ясен принцип? вопрос тот же.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Там не то что принцип, там вообще ниуя не ясно.
Особенно непонятно, зачем в сетапе так порты инициализировать.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016
#define INT_UPD_DIG (500)

byte digits[13]={B01000000,B01111001,B00100100,B00110000,B00011001,B00010010,B00000010,B01111000,B00000000,B00010000,
               //    0         1         2         3         4         5         6         7         8         9
                 B01111111,B00001110,B01000110};
               //  blank      freq      cap

unsigned long read_data, read_div, read_mod;
byte disp_data[6]={0,0,0,0,0,0};  // display shadow

void setup(){
  DDRD|=B11011111;
  DDRB|=B00000111;
  DDRC|=B00111000;
  PORTD|=B11000011;
  PORTB|=B00000111;
}

void loop(){
  byte i;
  bool found_nonzero=false;

  read_data=228420; //debug

  for(i=5;i>=1;i--){
    divmod10(read_data, read_div, read_mod);
    disp_data[i]=read_mod;
    read_data=read_div;
  }
  disp_data[0]=read_data;

  for(i=0;i<=5;i++){
    if(disp_data[i]>0) found_nonzero=true;
    if(!found_nonzero) disp_data[i]=10; // write blank to kill leading zero
  }
  
  proc_disp();
}

void divmod10(uint32_t in, uint32_t &div, uint32_t &mod){
  uint32_t x=(in>>1);
  uint32_t q=x;
  q= (q>>8) + x;
  q= (q>>8) + x;
  q= (q>>8) + x;
  q= (q>>8) + x + 1;
  x= q;
  q= (q>>1) + x;
  q= (q>>3) + x;
  q= (q>>1) + x;
  div = (q >> 3);
  mod = in - (((div << 2) + div) << 1);
}

void proc_disp(){
  byte n_dig=0;
  for(n_dig=0;n_dig<=5;n_dig++){
    switch(n_dig){
      case 0: PORTC|=B00110000; PORTD|=B00011100; PORTC&=B11110111; break; // whether common anode 1 is on
      case 1: PORTC|=B00011000; PORTD|=B00011100; PORTC&=B11011111; break; // ca 2
      case 2: PORTC|=B00101000; PORTD|=B00011100; PORTC&=B11101111; break; // ca 3
      case 3: PORTC|=B00111000; PORTD|=B00001100; PORTD&=B11101111; break; // ca 4
      case 4: PORTC|=B00111000; PORTD|=B00011000; PORTD&=B11111011; break; // ca 5
      case 5: PORTC|=B00111000; PORTD|=B00010100; PORTD&=B11110111; break; // ca 6
    }
    if(disp_data[n_dig]&B00000001){ PORTD|=B00000001; }else{ PORTD&=B11111110; }  // whether G is off
    if(disp_data[n_dig]&B00000010){ PORTD|=B00000010; }else{ PORTD&=B11111101; }  // F
    if(disp_data[n_dig]&B00000100){ PORTB|=B00000001; }else{ PORTB&=B11111110; }  // E
    if(disp_data[n_dig]&B00001000){ PORTD|=B01000000; }else{ PORTD&=B10111111; }  // D
    if(disp_data[n_dig]&B00010000){ PORTD|=B10000000; }else{ PORTD&=B01111111; }  // C
    if(disp_data[n_dig]&B00100000){ PORTB|=B00000100; }else{ PORTB&=B11111011; }  // B
    if(disp_data[n_dig]&B01000000){ PORTB|=B00000010; }else{ PORTB&=B11111101; }  // A
  }
}

доделанная версия

Kakmyc, так быстрее

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

Voodoo Doll пишет:
<

Вопросы:

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

    case 9:  /*......*/
             if(read_div==400)    disp_data[9]=4;

вместо

    case 9:  /*......*/
             if(read_div==400)    disp_data[pos]=4;


Константа - она завсегда быстрее и предсказуемей в работе, но сложнее в саппорте.

Деление потенциально тяжелее сравнения, если только деление при оптимизации на битшифт не заменяется.

Green
Offline
Зарегистрирован: 01.10.2015

Быдлокод. DDR-ы, PORT-ы, всякие B000000 заменяешь смысловыми значениями. Определяешь сегменты, общие, начертание отображаемых символов и т.д. Пример индикации.
 

uint8_t segment[COM_MAX];
bool dot;


void ledExe() {
  static uint8_t com;
  
  segment_off();                        //выключим всё
  com_off();
  switch (com) {                        //включим один общий
    case 0: com1_on(); break;
    case 1: com2_on(); break;
    case 2: com3_on(); break;
  }
  segment_on(segment[com]);             //включим сегменты
  if (++com >= COM_MAX)                 //следующая позиция  
    com = 0;                            
}

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Voodoo Doll, почему форумчане не кинулись править ваш код? Так это из-за уважения. Но по факту вы нарушили все написанные и ненаписанные правила при написании кода. Так что подымайте литературу и учите.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Мне вот не понятно все же, почему ТС твердо уверен , что все поняли о каком дисплее ("экране") идёт речь ?

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

О семисегментном LED.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот про это я и говорю. Язык Си создавался как язык высокого уровня, который может работать на низком уровне. Что такое язык высокого уровня? Это любой программист средней квалификации глядя на код, сразу поймет какое железо и софт используется в программе. Но зачем писать на Си словно это ассемблер. 

sadman41 пишет:
О семисегментном LED.

Семисегментные LED бывают разные одиночные, двойные и так далее.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Ппц сразу ясно стало какой экран.
Теперь осталось узнать о каком типе индикации идёт речь

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

Бл. Написано же: kingbright ba-56.
И этот сегментник не мой, не надо меня пригружать.

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

qwone пишет:
Что такое язык высокого уровня? Это любой программист средней квалификации глядя на код, сразу поймет какое железо и софт используется в программе.

Такого определения ещё не видел! Буду знать.

Logik
Offline
Зарегистрирован: 05.08.2014

qwone пишет:

Это любой программист средней квалификации глядя на код, сразу поймет какое железо...

Очень смешно ляпнул про кросплатформенный язык.

Но код таки гамно.

Чего бы не написать стр.66 и далее типа 

byte Seg[]={B00000001,B00000010,B00000001,B01000000,B10000000,B00000100,B00000010}; // эти константы и именовать не грешно бы

..

for(byte a=digits[n_dig], i=0;i<7;i--,a>>=1)
{
  if(a&1){ PORTD|=Seg[i]; }else{ PORTD&=~Seg[i]; }
}

а то что в свиче fill_disp_data - адское адище.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Зачем вообще нужно это недоразумение , если все намного проще ?

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

Люди, а ассемблер сложно учить? Может быть я реально зря на c (даж не c++) пишу...

nik182
Offline
Зарегистрирован: 04.05.2015

Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.

Voodoo Doll
Voodoo Doll аватар
Offline
Зарегистрирован: 18.09.2016

Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

nik182 пишет:

Изначально не сложно. Нужно выучить все команды процессора, структуру регистров процессора и их ограничения. Дальше правила оформления кода. Но зачем? Си даёт эффективный код. Очень редко, когда требуется или точный по времени или кратчайший код может потребоваться ассемблерная вставка. Писать целиком на ассемблере в современных условиях развития компиляторов чистой воды мазохозм.

Ассемблер полезно представлять себе хотя бы затем, чтобы проверить, а чего же там намудрил компилятор. Потому как бывают варианты.

Ну и еще полезно представлять, во что именно выльется та или иная строка на Си. Потому как одна строка превращается в 2-3 оператора, которые выполняются 2-3 такта, а другая - ведет к вызову функции, которая может выполняться не одну тысячу тактов.

nik182
Offline
Зарегистрирован: 04.05.2015

Ну да. Однако знать ассемблер, что бы посмотреть, что там намудрил компилятор не обязательно. Достаточно знать ассемблерные комаманды процессора - это необходимый минимум.

Green
Offline
Зарегистрирован: 01.10.2015

Voodoo Doll пишет:

Да чёт подумал что по стилю мои скетчи больше напоминают ассемблер, чем обычный ардуинный wiring/c. Ну и плюс привычка оптимизировать по размеру кода.


Для себя вы можете писать как угодно. Только критерии нужно установить - быстро, компактно, хитронакручено и т.д. Как правило, в большинстве случаев, это всё лишнее. Иначе, пишите на ассемблере.
Если выставляете на оценку - должны понимать что читают люди. А значит лаконично и понятно (а не хитрозакручено), правильно оформлено и переносимо.