bool arr[]={0,1,0,0,0,0,0,0} сконвертировать в byte B01000000

pahuchiy
Offline
Зарегистрирован: 04.03.2018

Приветствую. Имею массив, к примеру bool arr[]={0,1,0,0,0,0,0,0}

Мне нужно сконвертировать этот массив в byte следующего формата - B01000000.

Это нужно для использования в библиотеке LedControl: LC.setRow(int address, int row, byte value);

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

pahuchiy, конвертировать-то его нетрудно, вот только нафига? Может лучше изнчально не создавать его и не транжирить память. Он же по байту на бит жрёт! Что мешет сразу записать в виде битов? Задача-то какая?

pahuchiy
Offline
Зарегистрирован: 04.03.2018

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

pahuchiy, конвертировать-то его нетрудно, вот только нафига? Может лучше изнчально не создавать его и не транжирить память. Он же по байту на бит жрёт! Что мешет сразу записать в виде битов? Задача-то какая?

Я ж делаю миди-секвенсор))). Так вот хочу записывать ноты в двумерный массив: по вертикали - ноты, по горизонтали время. Мне кажется, удобно. Не?

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

А зачем их так записывать? В восемь раз память перерасходвать? Сделайте union на байт и массив из восьми битовых полей по одному биту  и пишите свои биты прямо в этот байт безо всяких конверсий. Визульно это будет выглядеть также (последовательность нулей и единиц). Если не знаете что такое union и "битовые поля", то ключевые слова для поиска у Вас теперь есть.

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

pahuchiy пишет:

Приветствую. Имею массив, к примеру bool arr[]={0,1,0,0,0,0,0,0}

Мне нужно сконвертировать этот массив в byte следующего формата - B01000000.

bool arr[] = { 0, 1, 0, 0, 0, 0, 0, 0 };
byte b = 0;
for( int i = 0; i < size( arr ) / size( arr[ 0 ] ) /* 8 */; i++ )
   b = b << 1 + arr[ i ] ? 1 : 0;

А нужно ли оно вам, и зачем - это вы думайте сами.

 

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

Olej, Вы биты случаем не перевернули? Хотя, никто не знает как ТС нужно LSB или MSB вперёд пихать.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

Olej пишет:

pahuchiy пишет:

Приветствую. Имею массив, к примеру bool arr[]={0,1,0,0,0,0,0,0}

Мне нужно сконвертировать этот массив в byte следующего формата - B01000000.

bool arr[] = { 0, 1, 0, 0, 0, 0, 0, 0 };
byte b = 0;
for( int i = 0; i < size( arr ) / size( arr[ 0 ] ) /* 8 */; i++ )
   b = b << 1 + arr[ i ] ? 1 : 0;

А нужно ли оно вам, и зачем - это вы думайте сами.

 

#include "LedControl.h"
LedControl lc=LedControl(12,11,10,1);
bool arr[] = { 0, 1, 0, 0, 0, 0, 0, 0 };
byte b = 0;

void setup() {
  Serial.begin (9600);
   lc.shutdown(0,false);
  // выставляем яркость на среднее значение:
  lc.setIntensity(0,1);
  // очищаем дисплей:
  lc.clearDisplay(0);    
  
}

void loop() {
  b = 0;
  for( int i = 0; i < size( arr ) / size( arr[ 0 ] ) /* 8 */; i++ )
   b = b << 1 + arr[ i ] ? 1 : 0;  
  lc.setRow(0,0,b);
}
exit status 1
'size' was not declared in this scope

Как исправить?

после autoit и lua, С++ очень сложен....

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

pahuchiy пишет:

void loop() {

  b = 0;
  for( int i = 0; i < size( arr ) / size( arr[ 0 ] ) /* 8 */; i++ )
   b = b << 1 + arr[ i ] ? 1 : 0;  
  lc.setRow(0,0,b);
}
exit status 1
'size' was not declared in this scope

sizeof( ... ) - не дописал ;-)

Но можете просто заменить на 8:  for( int i = 0; i < 8; i++ ) ...

pahuchiy
Offline
Зарегистрирован: 04.03.2018
#include "LedControl.h"
LedControl lc=LedControl(12,11,10,1);
bool arr[] = { 0, 1, 0, 0, 0, 0, 0, 0 };
byte b = 0;

void setup() {
  Serial.begin (9600);
   lc.shutdown(0,false);
  // выставляем яркость на среднее значение:
  lc.setIntensity(0,1);
  // очищаем дисплей:
  lc.clearDisplay(0);    
  
}

void loop() {
  b = 0;
  for( int i = 0; i < 8; i++ )
   b = b << 1 + arr[ i ] ? 1 : 0;  
  lc.setRow(0,1,b);
}

не горит(

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

А так горит - lc.setRow(0,1,B01000000); ?

pahuchiy
Offline
Зарегистрирован: 04.03.2018

да

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

pahuchiy пишет:

не горит(

Я вам не обещал что будет гореть. 

Я обещал преобразовать в byte. 

P.S. Ну выведите b в Serial и наблюдайте значение.

 

pahuchiy
Offline
Зарегистрирован: 04.03.2018

Olej пишет:

pahuchiy пишет:

не горит(

Я вам не обещал что будет гореть. 

Я обещал преобразовать в byte. 

P.S. Ну выведите b в Serial и наблюдайте значение.

 

выводит 0

Olej
Olej аватар
Offline
Зарегистрирован: 05.03.2018

pahuchiy пишет:

Olej пишет:

P.S. Ну выведите b в Serial и наблюдайте значение.

выводит 0

Ну, может с приоритетами операций там что-то не так ... поэкспериментируйте со скобками, например так:

b = ( b << 1 ) + ( arr[ i ] ? 1 : 0 ); 

Расстановка скобок для управления приоритетами должно быть обычной практикой. 

Но, в конечном итоге, должно быть как-то так... Вы должны видеть значение b по Serial - 64 (для вашего примера). После того, как добьётесь отладкой результата, лишние скобки можете убрать. 

pahuchiy
Offline
Зарегистрирован: 04.03.2018

Olej пишет:

pahuchiy пишет:

Olej пишет:

P.S. Ну выведите b в Serial и наблюдайте значение.

выводит 0

Ну, может с приоритетами операций там что-то не так ... поэкспериментируйте со скобками, например так:

b = ( b << 1 ) + ( arr[ i ] ? 1 : 0 ); 

Расстановка скобок для управления приоритетами должно быть обычной практикой. 

Но, в конечном итоге, должно быть как-то так... Вы должны видеть значение b по Serial - 64 (для вашего примера). После того, как добьётесь отладкой результата, лишние скобки можете убрать. 

спасибо, горит!

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

pahuchiy пишет:

Я ж делаю миди-секвенсор))). Так вот хочу записывать ноты в двумерный массив: по вертикали - ноты, по горизонтали время. Мне кажется, удобно. Не?

А какая предполагаемая длина последовательности секвенора?

Для 4 тактов 4/4 получается: (4 такта) * (96 MIDI Clock) * (97 нот) * (1 байт) = 37248 байта, т.е. более 32 KiB. Даже для Arduino Due весьма существенная величина, а для MEGA 2560 - и вовсе неподъемная.

fogary
Offline
Зарегистрирован: 05.03.2016

Olej пишет:

Но можете просто заменить на 8:  for( int i = 0; i < 8; i++ ) ...

Только не на 8, а на 7.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

andriano пишет:

pahuchiy пишет:

Я ж делаю миди-секвенсор))). Так вот хочу записывать ноты в двумерный массив: по вертикали - ноты, по горизонтали время. Мне кажется, удобно. Не?

А какая предполагаемая длина последовательности секвенора?

Для 4 тактов 4/4 получается: (4 такта) * (96 MIDI Clock) * (97 нот) * (1 байт) = 37248 байта, т.е. более 32 KiB. Даже для Arduino Due весьма существенная величина, а для MEGA 2560 - и вовсе неподъемная.

спасибо, да, уже пересмотрел способ хранения данных. Буду записывать только существующие ноты, а всё остальное по умолчанию будет false

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

Странный Вы человек, я Вам рассказал как хранить в восемь раз компактнее, но Вы упорно цепляетесь за то, чтобы хранить именно так, как никуда не влазит и мастырить костыли.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014
struct byte {
    unsigned a0: 1;
    unsigned a1: 1;
    unsigned a2: 1;
    unsigned a3: 1;
    unsigned a4: 1;
    unsigned a5: 1;
    unsigned a6: 1;
    unsigned a7: 1;
};
 
loop() {
    struct byte x = {0, 0, 0, 1, 0, 0, 0, 0};
    Serial.println(x.a0);
    Serial.println(x.a1);
    Serial.println(x.a2);
    Serial.println(x.a3);
    Serial.println(x.a4);
    Serial.println(x.a5);
    Serial.println(x.a6);
    Serial.println(x.a7);
}

Ему надо увидеть это.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

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

Странный Вы человек, я Вам рассказал как хранить в восемь раз компактнее, но Вы упорно цепляетесь за то, чтобы хранить именно так, как никуда не влазит и мастырить костыли.

Я вам крайне благодарен за совет.  Я скорее всего так или подобным образом и сделаю в будущем. Но на данном этапе моих навыков в C++ не достаточно чтобы реализовать это (собственно, я около недели назад начал разбираться в C++). То что я делаю сейчас - это промежуточный вариант. Для тренеровки, так сказать.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

brokly пишет:

struct byte {
    unsigned a0: 1;
    unsigned a1: 1;
    unsigned a2: 1;
    unsigned a3: 1;
    unsigned a4: 1;
    unsigned a5: 1;
    unsigned a6: 1;
    unsigned a7: 1;
};
 
loop() {
    struct byte x = {0, 0, 0, 1, 0, 0, 0, 0};
    Serial.println(x.a0);
    Serial.println(x.a1);
    Serial.println(x.a2);
    Serial.println(x.a3);
    Serial.println(x.a4);
    Serial.println(x.a5);
    Serial.println(x.a6);
    Serial.println(x.a7);
}

Ему надо увидеть это.

спасибо

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014
struct byte {
    unsigned a0: 1;
    unsigned a1: 1;
    unsigned a2: 1;
    unsigned a3: 1;
    unsigned a4: 1;
    unsigned a5: 1;
    unsigned a6: 1;
    unsigned a7: 1;
};
 
union Byte {
    unsigned char value;
    struct byte bitfield;
};
 
 
loop() {
    union Byte x;
    x.value=0xAA; 
    Serial.println(x.bitfield.a0);
    Serial.println(x.bitfield.a1);
    Serial.println(x.bitfield.a2);
    Serial.println(x.bitfield.a3);
    Serial.println(x.bitfield.a4);
    Serial.println(x.bitfield.a5);
    Serial.println(x.bitfield.a6);
    Serial.println(x.bitfield.a7);
    Serial.println(x.value,BIN);
}

Ну тогда еще чуть чуть добавлю ;) Обратите внимание, при таком подходе вам вручную ничего конвертировать не придется . 

Смысл такой. 

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

Потом описали объединение, обращаясь к полям которого вы к одному и тому же содержимому можете обратиться как к байту или как к биту. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

простите за офф

ЕвгенийП пишет:
Он же по байту на бит жрёт!

а это только массив так жрёт? bool arr[]= {0,0,0,0,0,0,0,0}

или просто переменная bool тоже 1 байт в памяти занимает? мне так, для общего развития

А я наивный думал что 1 бит))

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

MaksVV пишет:

или просто переменная bool тоже 1 байт в памяти занимает? 

Конечно. Ничего не занимает меньше, чем байт. Хотя бы уже потому, что байт - минимальная адресуемая единица.

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

brokly пишет:

struct byte {
    unsigned a0: 1;
    unsigned a1: 1;
    unsigned a2: 1;
    unsigned a3: 1;
    unsigned a4: 1;
    unsigned a5: 1;
    unsigned a6: 1;
    unsigned a7: 1;
};
 
union Byte {
    unsigned char value;
    struct byte bitfield;
};
 
 
loop() {
    union Byte x;
    x.value=0xAA; 
    Serial.println(x.bitfield.a0);
    Serial.println(x.bitfield.a1);
    Serial.println(x.bitfield.a2);
    Serial.println(x.bitfield.a3);
    Serial.println(x.bitfield.a4);
    Serial.println(x.bitfield.a5);
    Serial.println(x.bitfield.a6);
    Serial.println(x.bitfield.a7);
    Serial.println(x.value,BIN);
}

Если вместо поля bitfield поставить безымянное поле, то запись получается компактнее

union Byte {
	unsigned char value;
	struct {
		unsigned a0: 1;
		unsigned a1: 1;
		unsigned a2: 1;
		unsigned a3: 1;
		unsigned a4: 1;
		unsigned a5: 1;
		unsigned a6: 1;
		unsigned a7: 1;
	};
};
 
 
void loop(void) {
    union Byte x;
    x.value=0xAA; 
    Serial.println(x.a0);
    Serial.println(x.a1);
    Serial.println(x.a2);
    Serial.println(x.a3);
    Serial.println(x.a4);
    Serial.println(x.a5);
    Serial.println(x.a6);
    Serial.println(x.a7);
    Serial.println(x.value,BIN);
}

 

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

ЕвгенийП пишет:
по байту на бит жрёт

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

Клапауций 555
Offline
Зарегистрирован: 10.03.2018

Voodoo Doll пишет:

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

О_О sizeof(boolean) == 1 байт, а не 1/8-я байта

у компиллятора нет мозга - мозг птички у программиста

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

Voodoo Doll пишет:

Откуда инфа?

Инфа из понимания программирования и знания языка.

Запомните, ни одна самостоятельная сущность (переменная, экземпляр класса, любая сущность) не может занимать в памяти меньше одного байта и не может занимать нецелое количество байтов.

(Чтобы сразу закрыть вопрос о битовых полях - битовое поле не является самостоятельной сущностью - оно существует только в составе группы полей. Самостоятельной сущностью является группа полей, а не отдельное поле. Причём любая группа битовых полей, хоть состоящая из одного поля - всё равно занимает целый байт (или целое количество байтов))

Voodoo Doll пишет:

Где менять ключи оптимизации компилятора?

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

Более того, представим себе класс в котором вообще нет ни одного свойства - ну ни одного и, стало быть, память занимать просто нечему. Вот, например:

class Kaka {
	int sum (const int a, const int b) { return a + b; }
	int mul (const int a, const int b) { return a * b; }
};

Kaka kaka;

Сколько по Вашему места занимает переменная kaka? Можете проверить - один байт. Нафига ей нужен этот байт? Чего в нём хранить? А ничего - просто она обязана иметь адрес, а пустота адреса не имеет. Отдельно взятый бит адреса тоже не имеет. Адрес может быть только у байта или группы байтов.

Voodoo Doll пишет:

такие вещи должны сжиматься автоматически. Не?

Ну, Вы уже поняли, что "не".
MaksVV
Offline
Зарегистрирован: 06.08.2015

Теперь понятно, спасибо! Это типа как кластер на жестком диске или флешке. Минимальная единица хранения информации. Меньше его не могут объекты занимать. 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Евгений, думаю, что еще стоит добавить про округление структур и юнионов в памяти кратно байту. То есть структура из одного бита, все равно займет байт. Ну это в наших 8 битных ардуинах.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

Voodoo Doll пишет:

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

Тут кстати не авторы компилятора виноваты, а стандарт.

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

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

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

Ну да.

Только язык здесь ни при чем. 

 

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

MaksVV пишет:

Теперь понятно, спасибо! Это типа как кластер на жестком диске или флешке. Минимальная единица хранения информации. Меньше его не могут объекты занимать. 

Нет, выше была правильная формулировка: минимальный адресуемый объем информации.

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

andriano пишет:

Только язык здесь ни при чем. 

Да, ладно! А что же здесь причём?

Вся байда вылезла из жёсткого требования языка, чтобы унарная операция "&" была применима к любому lvalue и любому qualified-id,  кроме битовых полей.  (ISO IEC 14882 - 2014 стр. 108, п. 5.3.1 (3-6))

Существует огромное множество языков в которых нет операции взятия адреса, и в них такой проблемы нет от слова совсем. Там разработчики компилятора могут запросто засунуть 8 bool переменных в один байт и не париться, что часто и делается.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

а почему, если 

    union Byte x;
    x.value=0xAA; 

написать не в лупе, то: 'x' does not name a type ?

Ведь, как я понимаю, - это инициализация юниона x. Да? Зачем его в лупе зацикливать?

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

pahuchiy пишет:

а почему, если 

    union Byte x;
    x.value=0xAA; 

написать не в лупе, то: 'x' does not name a type ?

Вы тут вроде довольно давно, но так и не поняли, что без кода вопросы задавать нельзя. Хрустальные шары на этом форуме запрещены, а потому мне просо неоткуда знать где Вы это написали, как написали. У меня работает нормально, где бы я не писал. Нужет отет - давайте код.

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

pahuchiy пишет:

Ведь, как я понимаю, - это инициализация юниона x. Да? Зачем его в лупе зацикливать?

Вы что нибудь про видимость переменных читали ?

В начале цикла содается переменная, доступная только в этом цикле. Вы ее используете один раз, во время прохода цикла. По окончании прохода цикла она разрушается. Мне она за пределами цикла была не нужна, поэтому я и объявил ее в начале цикла. Это и есть ответ на ваш вопрос.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

brokly пишет:

pahuchiy пишет:

Ведь, как я понимаю, - это инициализация юниона x. Да? Зачем его в лупе зацикливать?

Вы что нибудь про видимость переменных читали ?

В начале цикла содается переменная, доступная только в этом цикле. Вы ее используете один раз, во время прохода цикла. По окончании прохода цикла она разрушается. Мне она за пределами цикла была не нужна, поэтому я и объявил ее в начале цикла. Это и есть ответ на ваш вопрос.

читал про видимость. И знаю что если обьявить переменную как глобальную (а именно так я её и объявляю вне цикла, верно?), то она видна должна быть везде. Так почему ошибка возникает?

#include "LedControl.h"
#include "binary.h"
#include "string.h"
LedControl lc=LedControl(12,11,10,1);
/*
 Контакт DIN на матрице – к цифровому контакту 12 на Arduino
 Контакт CLK – к цифровому контакту 11
 Контакт CS – к цифровому контакту 10
*/


  union Byte {
    unsigned char value;
    struct {
      unsigned a0: 1;
      unsigned a1: 1;
      unsigned a2: 1;
      unsigned a3: 1;
      unsigned a4: 1;
      unsigned a5: 1;
      unsigned a6: 1;
      unsigned a7: 1;
    };
  };
    union Byte x;
    x.value=0xAA;  
void setup() {
 
  Serial.begin (9600);
 
  lc.shutdown(0,false);
  // выставляем яркость на среднее значение:
  lc.setIntensity(0,1);
  // очищаем дисплей:
  lc.clearDisplay(0);  
   
}

void loop()
{
  
lc.setLed(0, 2, 7, x.a1);
}

 

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

На глобальном уровне можно объявлять переменные, но нельзя выполнять действия.

Сделайте одно и двух:

1. Удаляйте строку 26, а в строку 25 добавляйте инициализацию (так луше)
или 2. Перенесите строку 26 внутрь функции setup

И, это, ну что-нибудь про язык-то почитайте.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

andriano пишет:

А какая предполагаемая длина последовательности секвенора?

Для 4 тактов 4/4 получается: (4 такта) * (96 MIDI Clock) * (97 нот) * (1 байт) = 37248 байта, т.е. более 32 KiB. Даже для Arduino Due весьма существенная величина, а для MEGA 2560 - и вовсе неподъемная.

Если я сделаю хранение мидисобытий таким образом (образно): {номер канала, номер строки (нота), номер столбца (время), длительность, велосити}, то чтобы прочитать их для отображения светодиодами и при этом не перебирать в цикле все миди-события, я должен каждую новую ноту (которую добавляю путём нажатия кнопки) ставить в правильном порядке. То есть, к примеру, если у меня уже есть 3 ноты: 1 - на 1-й секунде, 2- на 2-й секунде, 3-на 3-й секунде, то при добавлении новой ноты на 2,5 секунде, я должен поместить её 3-й в очереди сместив при этом одну ноту. В итоге запись произведения будет иметь такой порядок(время): 1  2  2,5  3

И если к примеру у меня в светодиодной матрице только 3 столбца, чтобы отобразить музыку, программа пройдёт все 4 значения, но увидив что 4-е значение выходит за "рамки видимости" светодиодной матрицы, остановится. И если бы дальше шли ещё какие-то ноты, то время на их чтение не тратилось бы. Я верно мыслю?

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

1. У Вас еще и номер канала есть? В своем подсчете объема информации я исходил из того, что канал единственный. Кстати, как Вы собираетесь управлять номером канала?

2. В протоколе MIDI длительности как таковой не существует. Конечно, для секвенсора ее можно ввести, но есть ряд соображений, по которым целесообразнее использовать пару сообщений Note On и Note Off вместо одного с указанием длительности.

3. Для того, чтобы вставить некоторый объект (например, ноту) в правильное место в последовательности, придумана такая структура данных как список.

Последнего абзаца я не понял.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

1. Конечно. На то он и секвенсор. Разве нет? Управление каналом: Младшая половина статус-байта https://habrahabr.ru/post/271693/

2. Да, на момент написания поста я ещё не углублялся в информацию по приведённой выше ссылке. Но теперь я в курсе как правильно.

3. Спасибо

Сейчас переформулирую последний абзац.

 

pahuchiy
Offline
Зарегистрирован: 04.03.2018

Суть в том чтобы обрабатывать (зажигать светодиоды) только те миди события которые укладываются в формат светодиодной матрицы. И работать со следющими только тогда когда настанет их черёд воспроизведения. Ну, впрочем, это и так очевидно. Не стоило, наверное об этом вообще писать.

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

Видимо, я не представляю себе Ваш проект.

В функции панели входит ввод данных? Если "да", то, думаю, все они должны как-то отображаться.

Т.е. не может быть данных, которые не попадают "в формат". Или нет?

 

Да, под "как управлять" я подразумевал не внутреннее хранение, а индикацию/ввод данных с панели.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

andriano пишет:

Да, под "как управлять" я подразумевал не внутреннее хранение, а индикацию/ввод данных с панели.

96*24 - это лишь поле ввода нот. Будут и другие органы управления. Смена каналов будет осуществляться с помощью них. Вот примерная схема http://prntscr.com/itgwgy 

Не все данные (ноты) будут помещаться на панеле. Будет прокрутка. Её прототип я даже набросал (сори за много мусора в коде):

#include "LedControl.h"
#include "binary.h"
#include "string.h"
//--ПИНЫ ЭНКОДЕРА--
#define CLK 2
#define DT 3
#define SW 4
long counter = 0;
boolean DT_now, DT_last;
boolean encoderFlag=0;
int nSdvig;
int sw=0;
int iByte=0; //текущий байт. может быть виден вместе с iByte+1
LedControl lc=LedControl(12,11,10,1);
byte sf[8];
long scrolPosition=0;
  byte rows[8][16]= {
    {B00111100,B10101010,B00110011,B10000001,B10100101,B10011001,B01000010,B00111100,B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100},
    {B00111100,B10101010,B00110011,B10000001,B10100101,B10011001,B01000010,B00111100,B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100},
    {B00111100,B10101010,B00110011,B10000001,B10100101,B10011001,B01000010,B00111100,B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100},
    {B00111100,B10101010,B00110011,B10000001,B10100101,B10011001,B01000010,B00111100,B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100},
    {B00111100,B10101010,B00110011,B10000001,B10100101,B10011001,B01000010,B00111100,B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100},
    {B00111100,B10101010,B00110011,B10000001,B10100101,B10011001,B01000010,B00111100,B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100},
    {B00111100,B10101010,B00110011,B10000001,B10100101,B10011001,B01000010,B00111100,B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100},
    {B00111100, B01010101,B00110011,B10000001,B10111101,B10000001,B01000010,B00111100,B00111100, B01000010,B10100101,B10000001,B10111101,B10000001,B01010010,B00111100}
  };
  
void byteDraw(int iMatrix, int iRow, byte u) {  
  lc.setRow(iMatrix,iRow,u);   
}  
/*
 Контакт DIN на матрице – к цифровому контакту 12 на Arduino
 Контакт CLK – к цифровому контакту 11
 Контакт CS – к цифровому контакту 10
*/

void setup() {
  Serial.begin (9600);
  pinMode (CLK, INPUT);
  pinMode (DT, INPUT);
  DT_last = digitalRead(CLK);         // читаем начальное положение CLK 
  lc.shutdown(0,false);
  // выставляем яркость на среднее значение:
  lc.setIntensity(0,1);
  // очищаем дисплей:
  lc.clearDisplay(0);  
     
}

void byteArrDraw_sdvig2(byte arr[8][16]) {  //вопрос как не указывать размерность многомерного массива
  byte toView[8]={arr[0][0],arr[1][0],arr[2][0],arr[3][0],arr[4][0],arr[5][0],arr[6][0],arr[7][0]};
  for (int i = 0; i < 8; i++) { //для кждой из 8 строк
    if (scrolPosition>0){                        //если скролим вправо
      toView[i]=arr[i][0]>>scrolPosition; 
    }
    else{                             //если скролим влево  или стоим на нуле
      if (scrolPosition<0){                //если скролим влево       
        float  f_scrolPosition=scrolPosition*-1,f_len = f_scrolPosition/8;
        iByte=((scrolPosition*-1)/8);          // номер текущего байта отсчёт с нуля
        
        if (!((scrolPosition*-1)/8==f_len)){ // если есть совмещение двух байтов на экране
          if (iByte>0){ 
            nSdvig=(scrolPosition*-1)-(iByte*8); //отсчёт с 1
            int iBit=8-((scrolPosition*-1)-(iByte*8));
          }else{
            nSdvig=scrolPosition*-1; //отсчёт с 1
            int iBit=8-scrolPosition*-1;           
          }
          toView[i]=arr[i][iByte]<<nSdvig; //сдвигаю текущий байт           
        }else{   // если только один байт вывожу
          nSdvig=0;
          int iBit=0; // сколько бит заменять
          toView[i]=arr[i][iByte];
        }
        sw=0;
        for (int i2 = 0; i2 < nSdvig; i2++) { // для каждого сдвинутого столбца
          bitWrite(toView[i],i2,bitRead(rows[i][iByte+1],8+i2-nSdvig)); // и выкатываю 2-ую 

          //sw=sw+1;
          if (encoderFlag){
            /*
            Serial.print("nSdvigPos ");
            Serial.println(nSdvigPos);
            Serial.print("i ");
            Serial.println(i);  
                        Serial.print("sw ");
            Serial.println(sw);             
            Serial.print("iByte ");
            Serial.println(iByte); 
            Serial.print("iBit ");
            Serial.println(iBit);                          
            Serial.print("bitRead ");
            Serial.println(bitRead(arr[i][iByte],iBit));   
            Serial.print("bitRead rows ");
            Serial.println(bitRead(rows[i][iByte],iBit));  
            Serial.println("-------- ");  
            */                    
          }
        }
      }else{toView[i]=arr[i][0];
      }    
    }
    //byteDraw(0, i,arr[i][0]); 
    byteDraw(0, i,toView[i]); 
   // Serial.println(bitRead(arr[0][0],0));  
    if(i==1){encoderFlag=0;
      
    }
  }   
}
void loop()
{ 

  //byteDraw(0, 3, x.value);
  //byteArrDraw(0,sf); 
  encoderTick();                      // ФУНКЦИЯ ОТРАБОТКИ ЭНКОДЕРА! СМОТРИ, ВОТ ОНА!
  //byteArrDraw_sdvig2pic(0,sf,nf);
  byteArrDraw_sdvig2(rows);
}
void encoderTick() {
  DT_now = digitalRead(CLK);          // читаем текущее положение CLK
  if (DT_now != DT_last) {            // если предыдущее и текущее положение CLK разные, значит был поворот
    if (digitalRead(DT) != DT_now) {  // если состояние DT отличается от CLK, значит крутим по часовой стрелке
      scrolPosition ++;                     // прибавить счётчик
      
    } else {                          // если совпадают, значит против часовой
      scrolPosition --;                     // убавить счётчик
    }
    
    Serial.print("Position: ");
    Serial.println(scrolPosition);
    encoderFlag=1;
  }
  DT_last = DT_now;                   // обновить значение
}

 

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

Круто!

Я тоже люблю большие панели http://arduino.ru/forum/proekty/analog-analogovogo-sintezatora#comment-249334

А энкодеры я бы посоветовал делать на прерываниях. Если энкодеров много - на PCINT.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

ну да, крутилки - это наше всё))).

Приятно видеть в среде рускоговорящих ардуинщиков интересующихся музыкой.

Пока что запланирован 1 энкодер и 3 фейдера. Я всегда больше интересовался "живой" музыкой. Поэтому, и девайс горожу под VSTi (рояль, саксофон, живые ударные итд). Ко мне Due  едет. А сейчас на Uno и  Nano не хочу заморачиваться с прошивками и прочими танцами чтобы как миди-контроллер стали видны в компе.

а насчёт прерываний - спасибо учту на будущее (пока что очень поверхностно понимаю о чём речь, погуглю как руки дойдут)

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

На мой взгляд, правильный MIDI должен выглядеть так:

Due - да, сейчас с ним отлаживаюсь. Из явных минусов: что-то там намудрили с разводкой земли/питания - никак не могу избавиться от помех, генеримых внешними устройствами, в частности - дисплеем.

С этим делом, вроде, намного лучше в https://ru.aliexpress.com/item/Due-Core-SAM3X8E-32-bit-ARM-Cortex-M3-Mini-Module-Compatible-UC-2102-512K-Flash-96K/32681732855.html

Но что-то там существенно хуже с процедурой прошивки. Впрочем, если отлаживаться на обычной Due, то это без разницы.

 

Ну и я как-то не понял, как согласуется живая музыка с визуальным секвенсором.

pahuchiy
Offline
Зарегистрирован: 04.03.2018

да, терминологически, она не живая. Но, скажем так, живее прочей электронщины. И, если получится, я по максимуму сделаю возможным редактирование тонких настроек звукоизвлечения (скорость нажатия, послекасание, итд). А раньше я плотно занимался именно живой музыкой (запись с микрофона живых инструментов) Но это большой труд В плане вложения психо-эмоциональной энергии. Переосмыслив всё это дело, я задался вопросом: а надо ли мне это? И понял что нет. А вот шаговый железный секвенсор - это проще. Это можно сравнить со стратегией и шутером от первого лица. (живая музыка - шутер, шаговый секвенсор - стратегия) Ну и,  есть вероятность продать девайс если удачным получится.