この記事は、MIDI&Audioをは無関係です。
Adafruit 8x8 Bi-Color LED MatrixをRaspberry Pi Zeroに接続し、 WiringPiライブラリを使って動作させます。Bi-Colorは、2色(赤と緑)を意味しています。 HT16K33 はLEDのドライバのチップの名前です。
HT16K33は緑を点灯させるレジスターと、赤を点灯させるレジスターがあります。 それぞれのレジスタは、8x8bit、すなわち8byteです。 1行が1byteに相当します。 点灯させたい時は、そのビットを1に設定し、消灯はゼロとします。 オレンジを点灯させたい時は、緑と赤を両方とも1に設定します。 例えばGndDotとRndDotをそれぞれ8x8bitのメモリとします。
uint8_t GndDot[8]; //緑の設定レジスタ uint8_t RedDot[8]; //赤の設定レジスタ
HT16K33のレジスタ(0x00 - 0x10)に対して、緑と赤のレジスタの値を1行づつを交互に書き込んています。
void Wiringpi_HT16K33::DisplayOutput(uint8_t *GndDot, uint8_t *RndDot)
{
uint8_t i,j;
for(i=0,j=0; i<16; i+=2,j++){
write8(i, GndDot[j]);
write8(i+1, RndDot[j]);
}
}
下のように点灯させたいとします。これを図1とします。
図1:目的の点灯図
この場合、図1を見ながらGndDotとRedDotを次のように設定するとします。
uint8_t GrnON[8]={
0b00000000,
0b01111110,
0b01000000,
0b01000000,
0b01000000,
0b01000000,
0b01111110,
0b00000000
};
uint8_t RedON[8]={
0b00000000,
0b01000000,
0b00100000,
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000000
};
GrnON、RedONを上の関数で書き込むと以下のように目的の絵を180度回転させた絵になってしまいます。
図2:実際の点灯
目的の図1のように点灯させるには、図1の絵を180度回転してGndDotとRedDotを設定します。 (180度回しておけば、レジスタに書き込んだ時180度まわしてれるので元に戻ります。)
図3:図1を180度回転
uint8_t GrnON2[8]={
0b00000000,
0b01000010,
0b01000010,
0b01000010,
0b01000010,
0b01000010,
0b01111110,
0b00000000
};
uint8_t RedON2[8]={
0b00000000,
0b01000000,
0b00100000,
0b00010000,
0b00001000,
0b00000100,
0b00000010,
0b00000000
};
GrnON2、RedON2を上の関数で書き込むと以下のように図1を得ることができます。
図4:GrnON2、RedON2を表示した結果
// main.cpp
// 赤 → 緑 → オレンジ → 消灯
// の順に点灯します。
#include <stdio.h>
#include <stdint.h>
#include <wiringPi.h>
#include <wiringPiI2C.h>
#include "Wiringpi_HT16K33.h"
int main()
{
Wiringpi_HT16K33 ht16k33(5);
while(1){
ht16k33.allRed();
delay(2000);
ht16k33.allGreen();
delay(2000);
ht16k33.allOrange();
delay(2000);
ht16k33.allClear();
delay(2000);
}
}
/*
* Wiringpi_HT16K33.h
* HT16k33 for using WiringPi
* by MikataHara
* 2024.10.26
*/
#ifndef _WIRINGPI_HT16K33_H
#define _WIRINGPI_HT16K33_H
#include <wiringPiI2C.h>
#define HT16K33_I2CADDR_DEFAULT 0x70 ///< I2C address
/* Class for Adafruit HT16K33 bi-Color */
class Wiringpi_HT16K33 {
public:
Wiringpi_HT16K33(uint8_t val);
void write(uint8_t val);
void write8(uint8_t reg, uint8_t val);
uint8_t read8(uint8_t reg);
void allClear();
void allGreen();
void allRed();
void allOrange();
private:
uint8_t _i2caddr;
};
/*
* Wiringpi_HT16K33.cpp
* Modified for Trinket 0by MikataHara
* 2024.10.26
*/
#include <stdint.h>
#include <stdio.h>
#include "Wiringpi_HT16K33.h"
/* val : 輝度(0x0〜0xF) */
Wiringpi_HT16K33::Wiringpi_HT16K33(uint8_t val)
{
_i2caddr = wiringPiI2CSetup(HT16K33_I2CADDR_DEFAULT);
// オシレータを有効化
wiringPiI2CWrite(_i2caddr, 0x21); // 0x21: システムオシレータON
// 表示点灯
wiringPiI2CWrite(_i2caddr, 0x81); // 0x81: 表示ON、ブリンクなし
// 輝度設定
wiringPiI2CWrite(_i2caddr, 0xE0 | val); // 0xE0 + 輝度(0x0〜0xF)
}
void Wiringpi_HT16K33::write(uint8_t val)
{
wiringPiI2CWrite(_i2caddr, val);
}
void Wiringpi_HT16K33::write8(uint8_t reg, uint8_t val)
{
wiringPiI2CWriteReg8(_i2caddr, reg, val);
}
uint8_t Wiringpi_HT16K33::read8(uint8_t reg)
{
uint16_t result = wiringPiI2CReadReg8(_i2caddr, reg);
return result;
}
void Wiringpi_HT16K33::allClear()
{
for(uint8_t i=0; i<16; i+=2){
write8(i, 0x00);
write8(i+1, 0x00);
}
}
void Wiringpi_HT16K33::allRed()
{
for(uint8_t i=0; i<16; i+=2){
write8(i, 0x00);
write8(i+1, 0xFF);
}
}
void Wiringpi_HT16K33::allGreen()
{
for(uint8_t i=0; i<16; i+=2){
write8(i, 0xFF);
write8(i+1, 0x00);
}
}
void Wiringpi_HT16K33::allOrange()
{
for(uint8_t i=0; i<16; i+=2){
write8(i, 0xFF);
write8(i+1, 0xFF);
}
}
DEMOプログラムをGithubに置きました。