All streams
Search
Write a publication
Pull to refresh
4
0.3
Send message

только у производителей носителей информации

Там не прижились. Прижились в некотором софте - Linux в целом, ffmpeg...

именно для того, чтобы отличать от тех, которые 1000 байт

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

"10.4 KB per track" - даташит на диск от пре-WD (Tandon)

"Head setting time: 15 Msec" - на диск из того диска

"768.0 Kbit/s" - пишет организация со 100-летней историей, National Association of Broadcasters.

"128 Kbps" - говорит американская ГКРЧ (FCC)

"9.6 Kbaud"

То есть 80.06 GB = 74.56 GiB. Это норма. А надо найти найти хоть один обратный случай (и с учётом вероятного округления заявленной ёмкости вниз, а не до ближайшего).

Постарайтесь вспомнить. На этикетках 40-гиговых Maxtor'ов в гугле везде есть либо количество LBA, указывающее на десятичные гигабайты*, либо сразу приписка "1 GB=1,000,000,000 Bytes".

* например, продаётся как 40 ГБ и 80 293 248 LBA * 512 bytes = 41.1 GB = 38.3 GiB.

Если ещё кто-нибудь вспомнит, то мы-таки получим настоящий эффект Манделы.

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

Можно, конечно, поискать конспирологию в том, что это производители накопителей пролоббировали IEC

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

Жёсткие диски всегда использовали десятичные приставки, это прослеживается до их появления в 50-х годах.

Покупаешь жёсткий диск — на коробке написано 500 ГБ, а на самом деле там 465 ГиБ

Но на плашках RAM — «честные» гибибайты: сколько указано, столько и получаешь, только пишут всё равно 16 GB, а не 16 GiB

То есть правила СИ&IEC соблюдаются в HDD и нарушаются в RAM, но вы пытаетесь это вывернуть так, чтобы получить больше заявленного.

Ранние ОС действительно использовали систему подсчёта данных, основанную на степенях двойки

Ранняя macOS. Windows и дальше продолжает использовать двоичные килобайты, в Linux перешли на кибибайты. Если же смотреть из современной macOS, то вы увидите жёсткий диск на 500 ГБ как жёсткий диск на 500 ГБ и всё равно недовольны.

Или всё-таки на заре компьютеров бумеры-основатели зря решили пойти против существующих стандартов

Вы не предлагаете решения для тех времён и почему-то считаете систему СИ нерушимым абсолютом, хотя у Международного бюро мер и весов нет своей армии. Правила СИ&IEC до сих пор нарушаются и у Apple (в оперативной памяти), и у производителей различных микросхем. В Android с измерением свободного места было что-то ещё более странное. Они обычно смотрят на вопрос с рекламной стороны (как "1.44 МБ" раньше), а вы не замечаете.

так скорость выглядит в 8 раз больше

А размеры аудио-/видеофайлов в 8 раз больше? Битрейт (не байтрейт) - обычная практика.

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

Но не дала механизма, который бы позволил отличить старые контекстно-зависимые килобайты от новых точно-десятичных килобайтов. Даже если все бы одновременно перешли на новые правила, старые тексты бы не исчезли. По ссылке выше такую ошибку допустили.

И вообще вроде бы есть специальные названия для ... «ровных»

сетевыми инженерами, которые считают 1 Гбит/с = 1 048 576 бит/с

В существование этих точек зрения после перечисленного не верится.

Зачем там больше гигабита?

Наверное, никак - в новые 8K-телевизоры 100 мбит/с ставят, прогоняя пользователей на Wi-Fi.

В даташите найти можно, хотя лучше знать, что искать.
https://ww1.microchip.com/downloads/en/DeviceDoc/doc8246.pdf#page=57

Да, этот прирост не нужен. Такие оптимизации пригодились бы, если бы у микроконтроллера были другие задачи, тогда ещё были бы нужны неблокирующие задержки, пришлось бы думать про (не)атомарность изменения PORTx.

использования регистров PINx (переключение пина без read-modify-write).

Я тут не подумал, что строка PORTB |= (1 << PB3); должна компилироваться в одну инструкцию SBI (Set Bit in I/O Register).

Так как почти весь прирост должен быть от зажигания 8 светодиодов вместо 1 и задержки во включённом состоянии, не стал писать про отказ от digitalWrite().

Но вообще тогда думал, что можно упороться вплоть до использования регистров PINx (переключение пина без read-modify-write). И чересстрочной развёртки, чтобы достичь незаметности мерцания на более низкой частоте:

Идеи
for (uint8_t rowIdx_ = 0; rowIdx_ < 8; rowIdx_++) {
	uint8_t rowIdx = rowIdx_;
#if defined(USE_INTERLACED_SCAN)
	rowIdx = rowIdx_/4 + 2*(rowIdx_%4); // 0,2,4,6,1,3,5,7
#endif

    // 1. prepare columns
#define H(X) readAndUnpackPixel(frame, X, rowIdx) // helper macro
	setMatrixColumns(H(0), H(1), H(2), H(3), H(4), H(5), H(6), H(7));
#undef H
	
	// 2. activate row
	ToggleRow(rowIdx);
	
	// 3. delay in active state
	delayMicroseconds(1000);
	
	// 4. deactivate row
	ToggleRow(rowIdx);
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

// Для инициализации; в т.ч. когда обновление прерывается, 
//  оставляя матрицу в неизвестном состоянии.
void SetRowsToHigh() {
	PORTD |= ((1 << 2) | (1 << 1) | (1 << 4) | (1 << 5));
	PORTB |= ((1 << 1) | (1 << 2) | (1 << 4));
	PORTA |= ((1 << 1));
}

void ToggleRow(uint8_t rowIdx) {
	switch(rowIdx) {
		case 0: PIND = (1 << 2); break;
		case 1: PINB = (1 << 1); break;
		case 2: PINB = (1 << 2); break;
		case 3: PIND = (1 << 1); break;
		case 4: PINB = (1 << 4); break;
		case 5: PINA = (1 << 1); break;
		case 6: PIND = (1 << 4); break;
		case 7: PIND = (1 << 5); break;
	}
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

inline bool readAndUnpackPixel(frame, uint8_t colIdx, uint8_t rowIdx) {
	return (bool)(pgm_read_byte(frame + colIdx) & (1 << rowIdx));
    //     ^^^^^^~~~~ изначально написал !! вместо этого, но не знаю,
    //                 что лучше выразит намерение нормализовать bool
}

/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */

inline void setMatrixColumns(bool b0, bool b1, bool b2, bool b3,
							 bool b4, bool b5, bool b6, bool b7) {
	PORTD &= ~((1 << 0) | (1 << 3) | (1 << 6));
	PORTB &= ~((1 << 6) | (1 << 5) | (1 << 0) | (1 << 3));
	PORTA &= ~((1 << 0));
    // ^~~~~ можно вызывать реже, 
    // если в PINx передавать изменения относительно предыдущей строки
	PIND = (b0 << 0) | (b1 << 3) | (b4 << 6);
	PINB = (b2 << 6) | (b5 << 5) | (b6 << 0) | (b7 << 3);
	PINA = (b3 << 0);
}

С последними стандартами плюсов, наверное, можно без особых ужасов проинициализировать массив consteval-функцией, которая бы делала необходимые оптимизации (повернуть массив в compile-time при необходимости и класть дельту начиная со второй строки матрицы, чтобы не считать её в рантайме).

О, классно.

____

Заодно поправлю себя в прошлом комменте:

резистор параллельно каждому светодиоду
(8+2)*8 = 64 80

*Некропост*

эти RGB можно считать за 1

Это что-то вроде простого баланса белого, но такого подхода недостаточно, чтобы определить RGB-пространство, в котором находимся, а из неизвестного пространства нельзя перейти в CIE XYZ, чтобы дальше перейти в OKLab.

Clear вроде приспосабливали для программной фильтрации инфракрасного света.

Этот датчик оказывается шатким фундаментом для OKLab, особенно если без калибровки по ColorChecker'у.

____

Заодно поправка к статье: адекватный перевод для gamut - это "цветовой охват", точно не "спектр".

Ещё, получается, displayFrame() занимается переворачиванием транспонированием кадра, от которого особенно не захочется избавляться из-за возможности "рисовать кадр" двоичными литералами.

И от которого нельзя удачно избавиться изменением направления сканирования матрицы (не построчно, а по столбцам), потому что зажигая строку мы имеем резистор параллельно каждому светодиоду, а при зажигании столбца такой "гарантии равномерного свечения" на этой плате не будет - будет один резистор на все светодиоды.

Я бы в такую сторону думал (выделил русским временные комменты):

for (uint8_t rowIdx = 0; rowIdx < 8; rowIdx++) {
	// 1. prepare columns (stored in transposed state)
	for (uint8_t i = 0; i < 8; i++) {
        // надо сделать указатель frame видимым отсюда
		uint8_t val = pgm_read_byte(frame + i);
		// viewed from software, val is bit-packed row of one frame
		// viewed from hardware, val is one column of LED matrix
		//  and we need rowIdx'th bit from each column here
		digitalWrite(col[i], val & (1 << rowIdx));
	}
	
	// 2. activate row
	digitalWrite(row[rowIdx], 0);
	
	// 3. delay in active state
	delayMicroseconds(1000);
	// итого частота обновления всей матрицы: до 1/(8*1000 мкс) = 125 Гц
	// ещё добавить к знаменателю время на (8+2)*8 = 64 вызовов digitalWrite():
	// до 1/(8*(1000 мкс) + 64*(5 мкс)) = 120 Гц
	
	// 4. deactivate row
	digitalWrite(row[rowIdx], 1);
	
	// 5. delay in inactive state for brightness adjustment
    // ...
}

Кажется, оно должно плохо работать из-за ошибок в алгоритме.

Динамическая индикация не даёт зажечь все светодиоды одновременно, из-за неё мы можем одновременно зажечь только 1 строку (или столбец). То есть одновременно может гореть только 1/8 часть матрицы.

Но из-за этого кода во внутреннем цикле получается сокращение до 1/64:

digitalWrite(col[thisCol], thisPixel);
if (thisPixel == HIGH) {
	// <-- неявная задержка из-за медленности digitalWrite,
    //      благодаря которой матрица вообще светится.
	digitalWrite(col[thisCol], LOW);
}

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

Из delayWithRefresh() можно почти всё убрать.

void delayWithRefresh(unsigned long d) {
	unsigned long prevTime = millis();
	unsigned long duration = 0;

	while (true) {
		unsigned long time = millis();
		unsigned long tmp = (time - prevTime);
		prevTime = time;
		duration += tmp;
		if (duration > d) {
			break;
		}

		refreshScreen();
	}
}
void delayWithRefresh(uint32_t durationInMs) {
	uint32_t startTime = millis();
	while(millis() - startTime < durationInMs) {
		refreshScreen();
	}
}

Регулировка яркости если работает, то из-за аналогичной неявной задержки (на вызов milis() и т.д.) - у условия if (_pwm < _intensity) {<проводим здесь xxx времени>} нет ветки else с аналогичной задержкой.

В displayFrame() (который всё-таки не показывает, а загружает в SRAM) заранее упакованные (1 строка - 1 байт) значения из флеш-памяти распаковываются (8 проходов по каждому байту) и снова упаковываются, хотя их достаточно только прочитать из флеша. А читать их можно побайтово там, где они используются в коде - эта функция и массив _pixels оказываются не нужны[*].

Можно двоичные литералы применить здесь:

const uint8_t ghost_Frame_1[8] PROGMEM = { 0x1c, 0x3e ...

C++14 их даёт в таком виде: 0b0010'1111, но если компилятор старее, то библиотеки Arduino дают их в виде констант препроцессора типа B00101111.

const uint8_t ghost_Frame_1[8] PROGMEM = {
	0b00011100, 
	0b00111110,
	0b01101011,
	0b01001001,
	0b01111111,
	0b01100011,
	0b01111111,
	0b01010101 
};

Как видится полноценный алгоритм для матрицы:

Для каждой строки:

  • Подготовить столбцы - подать напряжение (логическую единицу) на нужные аноды диодов[**]

  • Включить строку - подать лог.0 на строку (т.е. на катоды диодов, чтобы ток втекал в мк)

  • Задержка - такая, чтобы получить частоту обновления в 100..1000 Гц

  • Выключить строку - подать лог.1 на строку

  • <-- сюда можно перекинуть часть задержки для реализации регулировки яркости

[*] вообще, особое отношение к константам во флеше требуется из-за того, что AVR с его гарвардской архитектурой слишком старый с точки зрения C++ - расширение Named Address Spaces есть только для C.

[**] без Arduino-фреймворка это можно сократить до PORTB = _pixels(i); (вместо того внутреннего цикла), если развести плату так, чтобы выводы столбцов приходились на один порт. Но в любом случае, фреймворк здесь добавляет проблем - заставляет думать о тяжести восьми вызовов digitalWrite().

___

Какая-то статья про динамическую индикацию с хорошим описанием алгоритма: https://microsin.net/programming/avr/led-matrix-dynamic-indication.html

___

Исправление алгоритма повысит ток (как и уменьшение резисторов), надо подумать:

  • насколько просядет напряжение питания (=> стабильность микроконтроллера)

  • не станет ли яркость строки зависеть от количества включённых светодиодов из-за просадки напряжения (сейчас она не может зависеть, потому что одновременно горит только 1 светодиод)

  • насколько безопасно для выходов микроконтроллера

Расстояние между цветами в пространстве OKLCH как считается?

Как евклидово расстояние в цилиндре - т.е. не надо OKLab переводить в его версию с полярными цилиндрическими координатами (OKLCH), надо остаться в OKLab

"Because Oklab is more perceptually uniform than CIE Lab, the color difference is a straightforward distance in 3D space (root sum of squares)" https://www.w3.org/TR/css-color-4/

Ну dE в CIELab тоже нифига не евклидово.

Этот вариант и в CIELab имеет право на жизнь, только CIELab хуже (неравномернее) и сильно стандартизирован, что, видимо, подкрепляло идею улучшать "perceptually uniformness" у вариантов вычисления расстояния, а не у пространства (не менять пространство). И с уклоном в науку, а не красивые градиенты - "Международная комиссия" может больше углубляться в измерение расстояния.

В них ничего не совпадает, кроме идеи кодировать тон (hue) одной компонентой.

HSV и HSL - это наивный подход к проблеме. Можно было бы сказать, вычислительно облегчённый, если бы не наивность в V=max(R,G,B) и L=0.5*(max(R,G,B)-min(R,G,B)).

OKLCH - современный (в плане вычислительной сложности - тоже...). Это новая вариация на тему CIELab (OKLab), только в полярных координатах (прямоугольные координаты a и b в радиус Chroma и угол Hue).
https://bottosson.github.io/posts/oklab/#motivation-and-derivation-of-oklab

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

Скажу сам про первоисточники - есть ещё комментарии Симпликия к "Физике", которые оказываются не только комментариями, но и вторым первоисточником, потому что апория там описывается подробнее (т.е. видимо, Симпликий опирался на что-то ещё, дошедшее через 800 лет до него, но не дожившее до нас).

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

Симпликий тоже так не считает.

Скрытый текст

Зенон утверждает, что между громкостями такая же пропорция, как между количеством:

мешок : 1 зерно : 1 / 10 000 зерна

‘Well, then, is there not a ratio [logos] of a medimnus of millet seeds to one [millet seed] and to a ten-thousandth of one?’ When [Protagoras] asserted that there was, Zeno said, ‘Well, then, will not the ratios of the sounds to one another be the same?

Hagen, Charles (1994). Simplicius: On Aristotle Physics 7

Аристотель возражает, что можно наблюдать, как при делении такая пропорция нарушается и имеет в виду появление нелинейности.

But when the force has been partitioned, he says, the proportion is not preserved, though it is preserved when it is combined

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

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

Из статьи получается, что Аристотель Зенона не понял, Симпликий не понял, Фома Аквинский не понял и только сейчас поняли Зенона. А может, сейчас стали придумывать преемственность между древней философией (в современном значении слова) и современной наукой, чтобы извлекать из этого выгоду? Известные имена и заявления про плечи гигантов придают вес, привлекают внимание и работают на разных уровнях (приносят выгоду как одному философу, так и всей Западной цивилизации). Также удобно, что Зенон не может возразить и что философия в принципе достаточно размыта, чтобы скрыть негативные утверждения (Из правоты Зенона следует неправота Аристотеля? Ответим уклончиво...).

Какой-то особый вид мазохизма?:)

Мальчик записывает в соавторы профессора, муж ссылается на древних философов.

_____

Апория звучит следующим образом: "Каждое отдельное зерно падает на землю бесшумно <...>

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

"Ведь из того, что целая сила продвинула [тело] на определенную длину, не следует, что половина силы продвинет [это же тело] на сколько-нибудь в какое бы то ни было время <...> Поэтому-то неправильно рассуждение Зенона, что любая часть просяного зерна произведет шум" - https://ru.wikisource.org/wiki/Физика_(Аристотель;_Карпов)/Книга_7/Глава_5#:~:text=Ведь из

"Hence Zeno's reasoning is false when he argues that there is no part of the millet that does not make a sound" - https://isidore.co/aquinas/Physics7.htm#8:~:text=Hence Zeno

Фома Аквинский Аристотеля трактует так - Зенон ошибался, считая, что из звучание одного зерна следует из звучания целого мешка (и где-то вокруг витают заблуждения насчёт трения покоя?).

"argument of Zeno who wished to prove that each grain of millet falling to the earth makes a sound, because an entire bushel of it, when poured to the earth, makes a sound ... it is not the part but the whole that acts" - https://isidore.co/aquinas/Physics7.htm#8:~:text=960. Then

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

+1, надо было сказать, что риск кажется пренебрежимо малым, но вообще на MakeMKV есть с десяток историй о таких случаях с Blu-ray и про "зацарапывание" говорили:

The BU40N is currently the only known drive that has demonstrated it's ability to malfunction and leave the disc scratched to the point of usability

BW-16D1HT ... I've had mine scratch 2 or 3 blu-rays ... It ruined my Incredibles 2 blu-ray

Как человек без крыши сможет накопить кучу предупреждений и забить на этичное поведение? Ему объяснят, что даже этичное поведение - это правило, увидят упорное "мы ещё посмотрим, кто кого прогнёт" и накажут.

Давайте, попробуйте пообщаться там фразами "I have no idea who the fuck you are". Да и на хабре можете попробовать.

Запрос к администраторам на тему удаления обсуждений там закончился тем, что "There's no consensus for any action against Jorm here".

Выбывании из гонки. Гонки объёмов (чтобы снижать стоимость; скорости вместе с объёмом тоже часто растут). Выбывание из этой гонки не мешает ценить долговечность оптики.

Information

Rating
2,430-th
Registered
Activity