SPI使用9bit転送のOLED接続

手元にあったMARY-OBというOLEDボード(2011)を整備が進んできたSPIドライバー
経由で接続することにチャレンジしたので、まとめておく。

SPIドライバーは当初、GPIOが26ピンだったためSPIがバス1本のStandardSPIのみの
サポートで、基本的に8bit単位の転送しかできなかった。
40ピンの時代になってBCM2835が搭載され、拡張SPIへの本格的取組が行われてきた。
カーネルが4.4.13以降、何回かの錯誤を経て、SPIバス2本が使える形に仕上がって
来ている。
拡張されたauxiliary SPI側では、LoSSIやワードサイズの指定が(限定的に)できる。
詳細は、ここを参照するとよい。

【準備】

1.BCM2835が載ったRaspberryPiを用意する。
2.カーネル4.4.y(又は4.9.y)のRaspbianOSを
  インストールして起動する。
3.「 ls /dev/spi*」コマンドで、
  /dev/spidev0.0 /dev/spidev0.1 /dev/spidev1.0 /dev/spidev1.1
  の4ポートが出現するように設定する。そのためには、
 ・config.txtに
  dtoverlay=pi3-disable-bt
  dtoverlay=spi1-2cs
  を追加する。       (注意:/dev/ttyS0との共存はできない)
 ・/boot/cmdline.txtに
  console=ttyS0,115200
  があれば、この部分を削除する。
4.pigpioライブラリーをインストールする。
  http://abyz.co.uk/rpi/pigpio/download.html (ガイド付き)
  または、いつもの、
  sudo apt-get install pigpio python-pigpio python3-pigpio
5.環境をテストする(make -j4を実施した時)。
  sudo ./x_pigpio

【OLEDサンプルプログラム】
  OLEDユニット UG-2828GDEDF11 に使われているコントローラーは、
  SOLOMON SYSTECH社のSSD1351でした。

SPIのピンヘッダの利用は次の通り。
    

SPI Function Header Pin Broadcom Pin Name Broadcom Pin Function
MOSI P1-38 GPIO20 SPI1_MOSI
SCLK P1-40 GPIO21 SPI1_SCLK
CE0 P1-12 GPIO18 SPI1_CE0_N
CE1 P1-11 GPIO17 SPI1_CE1_N

GPIO16をVCC_POWER_ONに利用している。焼き付き防止に有効。
任意のOUTPUT端子で良いが、ここではGPIO23をモジュールのリセットに使う。
この他に、VCC5V、VDD3.3V、GNDの接続がそれぞれ必要である。

SPIバスのオープン
int spiOpen(unsigned spiChan, unsigned baud, unsigned spiFlags);
spiChanでチップセレクトの出力先を、baudにはクロックスピードを設定する。
spiFlagsの意味
spiFlagsは下位22ビットが次のように定義されている。
21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
 b  b  b  b  b  b  R  T  n  n  n  n  W  A u2 u1 u0 p2 p1 p0  m  m

    このサンプルでは、次のようにオープンしている。

static uint16_t mode = 0x160;

    Aをオンにし、auxSPIを使用する。
    u0,u1をオンにし、二つのポートCE0,1の制御をライブラリに委ねている。

static uint16_t bits = 9;

    bits of word は9ビットを指定

static uint32_t speed = 10000000;

    speedはPiZeroやPi3に合わせて要求した。P12は倍でもOK。実速度は異なる。

spiOpen(0, speed, bits<<16 | mode );

    /dev/spidev1.0 のオープン

ソースファイル

//=========================================================
// File Name : oledspi2.c
// Function  : OLED Control
//---------------------------------------------------------
//---------------------------------------------------------
// Copyright (C) 2010-2011 Munetomo Maruyama
//=========================================================
// ---- License Information -------------------------------
// Anyone can FREELY use this code fully or partially
// under conditions shown below.
// 1. You may use this code only for individual purpose,
//    and educational purpose.
//    Do not use this code for business even if partially.
// 2. You can copy, modify and distribute this code.
// 3. You should remain this header text in your codes
//   including Copyright credit and License Information.
// 4. Your codes should inherit this license information.
//=========================================================
// ---- Patent Notice -------------------------------------
// I have not cared whether this system (hw + sw) causes
// infringement on the patent, copyright, trademark,
// or trade secret rights of others. You have all
// responsibilities for determining if your designs
// and products infringe on the intellectual property
// rights of others, when you use technical information
// included in this system for your business.
//=========================================================
// ---- Disclaimers ---------------------------------------
// The function and reliability of this system are not
// guaranteed. They may cause any damages to loss of
// properties, data, money, profits, life, or business.
// By adopting this system even partially, you assume
// all responsibility for its use.
//=========================================================
#include <stdio.h>
#include <inttypes.h>
#include <pigpio.h>
#include "oled.h"
#include "font.h"

//=================
// Font Parameters
//=================
#define OLED_FONT_XSIZE 8
#define OLED_FONT_YSIZE 8

//======================
// Define OLED Commands
//======================
#define OLED_COMMAND 1
#define OLED_DATA    2
//
#define C_SET_COLUMN_ADDRESS 0x0215
#define C_SET_ROW_ADDRESS    0x0275
#define D_START_ADDRESS 2
#define D_END_ADDRESS   3
//
#define C_WRITE_RAM_COMMAND 0x005c
#define C_READ_RAM_COMMAND  0x005d
//
#define C_SET_REMAP_COLOR_DEPTH 0x01a0
#define D_SET_REMAP_COLOR_DEPTH 2
//
#define C_SET_DISPLAY_START_LINE 0x01a1
#define D_SET_DISPLAY_START_LINE 2
//
#define C_SET_DISPLAY_OFFSET 0x01a2
#define D_SET_DISPLAY_OFFSET 2
//
#define C_SET_DISPLAY_MODE_ALL_OFF 0x00a4
#define C_SET_DISPLAY_MODE_ALL_ON  0x00a5
#define C_SET_DISPLAY_MODE_RESET   0x00a6
#define C_SET_DISPLAY_MODE_INVERSE 0x00a7
//
#define C_FUNCTION_SELECTION 0x01ab
#define D_FUNCTION_SELECTION 2
//
#define C_SET_SLEEP_MODE_ON  0x00ae
#define C_SET_SLEEP_MODE_OFF 0x00af
//
#define C_SET_RESET_PRECHARGE_PERIOD 0x01b1
#define D_SET_RESET_PRECHARGE_PERIOD 2
//
#define C_ENHANCE_DRIVING_SCHEME_CAPABILITY 0x03b2
#define D_ENHANCE_DRIVING_SCHEME_CAPABILITY_1 2
#define D_ENHANCE_DRIVING_SCHEME_CAPABILITY_2 3
#define D_ENHANCE_DRIVING_SCHEME_CAPABILITY_3 4
//
#define C_FRONT_CLOCK_DRIVER_OSCILLATOR_FREQUENCY 0x01b3
#define D_FRONT_CLOCK_DRIVER_OSCILLATOR_FREQUENCY 2
//
#define C_SET_SEGMENT_LOW_VOLTAGE 0x03b4
#define D_SET_SEGMENT_LOW_VOLTAGE_1 2 // 0xa0 or 0xa2
#define D_SET_SEGMENT_LOW_VOLTAGE_2 3 // 0xb5
#define D_SET_SEGMENT_LOW_VOLTAGE_3 4 // 0x55
//
#define C_SET_GPIO 0x01b5
#define D_SET_GPIO 2
//
#define C_SET_SECOND_PRECHARGE_PERIOD 0x01b6
#define D_SET_SECOND_PRECHARGE_PERIOD 2
//
#define C_LOOKUP_TABLE_FOR_GRAY_SCALE_PULSE_WIDTH 0x3fb8
static const uint8_t GAMMA_TABLE[63] =
{
    0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
    //
    0x12, 0x13, 0x15, 0x17, 0x19, 0x1b, 0x1d, 0x1f,
    0x21, 0x23, 0x25, 0x27, 0x2a, 0x2d, 0x30, 0x33,
    //
    0x36, 0x39, 0x3c, 0x3f, 0x42, 0x45, 0x48, 0x4c,
    0x50, 0x54, 0x58, 0x5c, 0x60, 0x64, 0x68, 0x6c,
    //
    0x70, 0x74, 0x78, 0x7d, 0x82, 0x87, 0x8c, 0x91,
    0x96, 0x9b, 0xa0, 0xa5, 0xaa, 0xaf, 0xb4
};
//
#define C_USE_BUILT_IN_LINEAR_LUT 0x00b9
//
#define C_SET_PRECHARGE_VOLTAGE 0x01bb
#define D_SET_PRECHARGE_VOLTAGE 2
//
#define C_SET_VCOMH_VOLTAGE 0x01be
#define D_SET_VCOMH_VOLTAGE 2
//
#define C_SET_CONTRAST_CURRENT_FOR_COLOR_ABC 0x03c1
#define D_SET_CONTRAST_CURRENT_FOR_COLOR_A 2
#define D_SET_CONTRAST_CURRENT_FOR_COLOR_B 3
#define D_SET_CONTRAST_CURRENT_FOR_COLOR_C 4
//
#define C_MASTER_CONTRAST_CURRENT_CONTROL 0x01c7
#define D_MASTER_CONTRAST_CURRENT_CONTROL 2
//
#define C_SET_MUX_RATIO 0x01ca
#define D_SET_MUX_RATIO 2
//
#define C_SET_COMMAND_LOCK 0x01fd
#define D_SET_COMMAND_LOCK 2
//
#define C_HORIZONTAL_SCROLL 0x0596
#define D_HORIZONTAL_SCROLL_A 2
#define D_HORIZONTAL_SCROLL_B 3
#define D_HORIZONTAL_SCROLL_C 4
#define D_HORIZONTAL_SCROLL_D 5
#define D_HORIZONTAL_SCROLL_E 6
//
#define C_STOP_MOVING  0x009e
#define C_START_MOVING 0x009f

#define MAX_WORKBUF 64
uint8_t *xvsnprintf(uint8_t *str, int32_t length, const char *format)
{
    uint8_t *ptr;

    ptr = (uint8_t*) format;
    while(*ptr != '\0')
    {
            if (length > 0) {*str++ = *ptr; length--;}
            ptr++;
    }
    //
    if (str != NULL) *str = '\0';
    return str;
}

#
//=============
// Globals
//=============
volatile uint32_t gOLED_printf_Font   = OLED_FONT_SMALL;
volatile uint32_t gOLED_printf_ColorF = OLED_WHT;
volatile uint32_t gOLED_printf_ColorB = OLED_BLK;
volatile uint32_t gOLED_printf_PosX = 0;
volatile uint32_t gOLED_printf_PosY = 0;
//
volatile uint32_t gOELD_Orientation_Mode = OLED_TOP_N;

static uint16_t mode = 0x160;	/* SPI1,u1,u0 */
static uint16_t bits = 9;
static uint32_t speed = 10000000;
    uint32_t oled[65];
//======================
// Initialize OLED
//======================


/*
int gpioSetMode(unsigned gpio, unsigned mode);
int gpioGetMode(unsigned gpio);
int gpioSetPullUpDown(unsigned gpio, unsigned pud);
int gpioRead(unsigned gpio);
int gpioWrite(unsigned gpio, unsigned level);
int gpioTrigger(unsigned user_gpio, unsigned pulseLen, unsigned level);
int spiRead(unsigned handle, char *buf, unsigned count);
int spiWrite(unsigned handle, char *buf, unsigned count);
int spiXfer(unsigned handle, char *txBuf, char *rxBuf, unsigned count);
*/
int Init_OLED(void)
{
    uint32_t i;

    // Display OFF

    oled[OLED_COMMAND] = C_SET_DISPLAY_MODE_ALL_OFF;
    OLED_Send_Command(oled);
    //
    // Initialization Sequence of OLED
    //
    oled[OLED_COMMAND] = C_SET_COMMAND_LOCK;
    oled[D_SET_COMMAND_LOCK] = 0x112; // unlock
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_COMMAND_LOCK;
    oled[D_SET_COMMAND_LOCK] = 0x1b1; // unlock
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_SLEEP_MODE_ON;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_FRONT_CLOCK_DRIVER_OSCILLATOR_FREQUENCY;
    oled[D_FRONT_CLOCK_DRIVER_OSCILLATOR_FREQUENCY] = 0xf1;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_MUX_RATIO;
    oled[D_SET_MUX_RATIO] = 0x17f;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_DISPLAY_OFFSET;
    oled[D_SET_DISPLAY_OFFSET] = 0x100;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_DISPLAY_START_LINE;
    oled[D_SET_DISPLAY_START_LINE] = 0x100;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_REMAP_COLOR_DEPTH;
    oled[D_SET_REMAP_COLOR_DEPTH] = 0x174; // 64k colors
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_GPIO;
    oled[D_SET_GPIO] = 0x100;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_FUNCTION_SELECTION;
    oled[D_FUNCTION_SELECTION] = 0x101;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_SEGMENT_LOW_VOLTAGE;
    oled[D_SET_SEGMENT_LOW_VOLTAGE_1] = 0x1a0; // use external VSL
    oled[D_SET_SEGMENT_LOW_VOLTAGE_2] = 0x1b5;
    oled[D_SET_SEGMENT_LOW_VOLTAGE_3] = 0x155;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_CONTRAST_CURRENT_FOR_COLOR_ABC;
    oled[D_SET_CONTRAST_CURRENT_FOR_COLOR_A] = 0x1c8;
    oled[D_SET_CONTRAST_CURRENT_FOR_COLOR_B] = 0x180;
    oled[D_SET_CONTRAST_CURRENT_FOR_COLOR_C] = 0x1c8;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_MASTER_CONTRAST_CURRENT_CONTROL;
    oled[D_MASTER_CONTRAST_CURRENT_CONTROL] = 0x10f;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_LOOKUP_TABLE_FOR_GRAY_SCALE_PULSE_WIDTH;
    for (i = 2; i < 65; i++)
    {
        oled[i] = (uint32_t) GAMMA_TABLE[i - 2] | 0x100;
    }
    OLED_Send_Command(oled);
    //
  //oled[OLED_COMMAND] = C_USE_BUILT_IN_LINEAR_LUT;
  //OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_RESET_PRECHARGE_PERIOD;
    oled[D_SET_RESET_PRECHARGE_PERIOD] = 0x132;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_ENHANCE_DRIVING_SCHEME_CAPABILITY;
    oled[D_ENHANCE_DRIVING_SCHEME_CAPABILITY_1] = 0x1a4;
    oled[D_ENHANCE_DRIVING_SCHEME_CAPABILITY_2] = 0x100;
    oled[D_ENHANCE_DRIVING_SCHEME_CAPABILITY_3] = 0x100;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_PRECHARGE_VOLTAGE;
    oled[D_SET_PRECHARGE_VOLTAGE] = 0x117;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_SECOND_PRECHARGE_PERIOD;
    oled[D_SET_SECOND_PRECHARGE_PERIOD] = 0x101;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_VCOMH_VOLTAGE;
    oled[D_SET_VCOMH_VOLTAGE] = 0x105;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_DISPLAY_MODE_RESET;
    OLED_Send_Command(oled);
    //
    // Clear Screen
    oled[OLED_COMMAND] = C_SET_COLUMN_ADDRESS;
    oled[D_START_ADDRESS] = 0x100;
    oled[D_END_ADDRESS]   = 0x17f;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_SET_ROW_ADDRESS;
    oled[D_START_ADDRESS] = 0x100;
    oled[D_END_ADDRESS]   = 0x17f;
    OLED_Send_Command(oled);
    //
    oled[OLED_COMMAND] = C_WRITE_RAM_COMMAND;
    OLED_Send_Command(oled);
    //
}

//==================================
// Initialize OLED with Orientation
//==================================
void Init_OLED_with_Orientation(uint32_t mode)
{
    uint8_t command;

    Init_OLED();
    gOELD_Orientation_Mode = mode;
    //
    command = (mode == OLED_TOP_W)? 0x25 :
              (mode == OLED_TOP_S)? 0x26 :
              (mode == OLED_TOP_E)? 0x37 : 0x34;
    oled[OLED_COMMAND] = C_SET_REMAP_COLOR_DEPTH;
    oled[D_SET_REMAP_COLOR_DEPTH] = command | 0x100;
    OLED_Send_Command(oled);
}

//=====================
// OLED Send Command
//=====================
void OLED_Send_Command(uint32_t *oled)
{
    uint32_t i;
    uint32_t count,countR;
    uint16_t bus;

    count = (oled[OLED_COMMAND] >> 8) & 0x0ff;

    bus = oled[OLED_COMMAND] & 0xFF;
    for (i=0;i<=count;i++) {
        countR = spiWrite( oled[0], (char *)&bus, 2);
        bus = oled[OLED_DATA+i] | 0x100;
    }	
    //
}

//=====================
// OLED Send Data
//=====================
void OLED_Send_Data(uint32_t *oled, int count)
{
    uint32_t i;
    uint16_t bus;

    for (i=0;i<count;i++) {
       bus = (oled[OLED_DATA+i] & 0xff) | 0x100;
       spiWrite( oled[0], (char *)&bus, 2);
    }	
}

//====================
// OLED Send a Pixel
//====================
void OLED_Send_Pixel(uint32_t color)
{
    oled[OLED_DATA+0] = (color >> 8) ;
    oled[OLED_DATA+1] = color;

    OLED_Send_Data(oled, 2);
}
//===================
// OLED Clear Screen
//===================
void OLED_Clear_Screen(uint32_t color)
{
    uint32_t i;
    uint32_t bus;

    oled[OLED_COMMAND] = C_WRITE_RAM_COMMAND;
    OLED_Send_Command(oled);
    bus = (color & 0xff00)<<8  | (color & 0xff) | 0x01000100;
    for (i=0;i<128*128;i++) {
       spiWrite( oled[0], (char *)&bus, 4);
    }	
}

//=======================
// OLED Draw a Character
//=======================
// scale should be 0, 1 or 2
void OLED_Draw_Char(char ch, uint32_t posx, uint32_t posy, uint32_t color_f, uint32_t color_b, uint32_t scale)
{
    uint32_t x0, y0;
    uint32_t xsize, ysize;
    uint32_t x, y;
    uint32_t xfont, yfont;
    uint32_t pixel;
    uint32_t color;
    //
    uint32_t col0, col1, row0, row1;

    ch = (ch < 0x20)? 0x20 : (ch > 0x7f)? 0x7f : ch;
    //
    x0 = posx * (OLED_FONT_XSIZE << scale);
    y0 = posy * (OLED_FONT_YSIZE << scale);
    //
    xsize = OLED_FONT_XSIZE * (1 << scale);
    ysize = OLED_FONT_YSIZE * (1 << scale);
    //
    if ((x0 <= (128 - xsize)) && (y0 <= (128 - ysize)))
    {
        col0 = (gOELD_Orientation_Mode == OLED_TOP_W)? y0       :
               (gOELD_Orientation_Mode == OLED_TOP_S)? x0 :
               (gOELD_Orientation_Mode == OLED_TOP_E)? y0 : x0;
        col1 = (gOELD_Orientation_Mode == OLED_TOP_W)? y0 + ysize - 1 :
               (gOELD_Orientation_Mode == OLED_TOP_S)? x0 + xsize - 1 :
               (gOELD_Orientation_Mode == OLED_TOP_E)? y0 + ysize - 1 : x0 + xsize - 1;
        row0 = (gOELD_Orientation_Mode == OLED_TOP_W)? x0 :
               (gOELD_Orientation_Mode == OLED_TOP_S)? y0 :
               (gOELD_Orientation_Mode == OLED_TOP_E)? x0 : y0;
        row1 = (gOELD_Orientation_Mode == OLED_TOP_W)? x0 + xsize - 1 :
               (gOELD_Orientation_Mode == OLED_TOP_S)? y0 + ysize - 1 :
               (gOELD_Orientation_Mode == OLED_TOP_E)? x0 + xsize - 1 : y0 + ysize - 1;
        //
       
        oled[OLED_COMMAND] = C_SET_COLUMN_ADDRESS;
        oled[D_START_ADDRESS] = (col0 > 127)? 127 : col0;
        oled[D_END_ADDRESS]   = (col1 > 127)? 127 : col1;
        OLED_Send_Command(oled);
        //
        oled[OLED_COMMAND] = C_SET_ROW_ADDRESS;
        oled[D_START_ADDRESS] = (row0 > 127)? 127 : row0;
        oled[D_END_ADDRESS]   = (row1 > 127)? 127 : row1;
        OLED_Send_Command(oled);
        //
        oled[OLED_COMMAND] = C_WRITE_RAM_COMMAND;
        OLED_Send_Command(oled);
        //
        for (y = 0; y < ysize; y++)
        {
            for (x = 0; x < xsize; x++)
            {
                xfont = x >> scale;
                yfont = y >> scale;
                pixel = FONT[((uint32_t) ch - 0x20) * 8 + yfont];
                pixel = (pixel >> (OLED_FONT_XSIZE - 1 - xfont)) & 0x01;
                color = (pixel == 1)? color_f : color_b;
                OLED_Send_Pixel(color);
            }
        }
    }
}

//====================
// OLED Make Color
//====================
//      RGB num
// BLK  000 0000-003f (< 64)
// BLU  001 0040-007f (<128)
// CYN  011 0080-00bf (<192)
// GRN  010 00c0-00ff (<256)
// YEL  110 0100-013f (<320)
// WHT  111 0140-017f (<384)
// MAG  101 0180-01bf (<448)
// RED  100 01c0-01ff (<512)
// BLK  000

//===========================
// OLED Set printf() Position
//===========================
void OLED_printf_Position(uint32_t posx, uint32_t posy)
{
    gOLED_printf_PosX = posx;
    gOLED_printf_PosY = posy;
}

//=====================
// OLED printf
//=====================
void OLED_printf(const char *format, ...)
{
    uint8_t buf[256];
    uint8_t *pStr;

    xvsnprintf(buf, 256, format);

    pStr = buf;
    while(*pStr != '\0')
    {
        if (*pStr == '\n')
        {
            gOLED_printf_PosX = 0;
            gOLED_printf_PosY++;
        }
        else
        {
            OLED_Draw_Char(*pStr, gOLED_printf_PosX, gOLED_printf_PosY,
                    gOLED_printf_ColorF, gOLED_printf_ColorB, gOLED_printf_Font);
            gOLED_printf_PosX++;
        }
        pStr++;
        //
        if (gOLED_printf_PosX >= (128 / (OLED_FONT_XSIZE << gOLED_printf_Font)))
        {
            gOLED_printf_PosX = 0;
            gOLED_printf_PosY++;
        }
        if (gOLED_printf_PosY >= (128 / (OLED_FONT_YSIZE << gOLED_printf_Font)))
        {
            gOLED_printf_PosY = 0;
        }
    }
}
//=====================
// Display BITMAP
//=====================
//-----------------------
// Main Routine
//-----------------------
#define BMP 1   // select which BMP you want to see.
#define BUD 30  // select which BUD part you want to see.


  #include "../bmp/lego8.bmp.plt.h"
  #include "../bmp/lego8.bmp.rgb.h"


  #include "../bmp/nana8.bmp.plt.h"
  #include "../bmp/nana8.bmp.rgb.h"


int main() {
    uint32_t x, y, i;
    uint8_t  index, orien;
    uint32_t palette;
    uint32_t red, blu, grn;
    uint32_t oled1, oled2, pixel;

   if (gpioInitialise() < 0) return -1;

    gpioSetMode(16,1);
    gpioSetMode(23,1);

    gpioWrite(16,1);    // OLED Vcc PowerON
    time_sleep( 0.1 );  // wait for 100ms
    // OLED Reset
    // OLED_/RES GPIO OUT
    gpioWrite(23,0);
    time_sleep( 0.1 );  // wait for 100ms
    gpioWrite(23,1);    // high (reset)
    time_sleep( 0.1 );  // wait for 100ms

    // Initialize Hardware
    oled1 = spiOpen(0, speed, bits<<16 | mode );
    oled2 = spiOpen(1, speed, bits<<16 | mode );
  for (orien=100; orien>0; orien--) {
    // Initialization
    //
    oled[0] = oled1;	
    Init_OLED_with_Orientation(orien & 3);
	OLED_Clear_Screen(OLED_BLK) ;   
    //
    // Send Bitmap Data1
    //
    i = 0;
    for (y = 0; y < 128; y++)
    {
        for (x = 0; x < 128; x++)
        {
            index = BMP_RGB[i++];
            palette = BMP_PLT[index];

            red = (palette >> (16 + 3)) & 0x01f;
            grn = (palette >> ( 8 + 2)) & 0x03f;
            blu = (palette >> ( 0 + 3)) & 0x01f;
            pixel = (red << 11) + (grn << 5) + (blu << 0);
            OLED_Send_Pixel(pixel);
        }
    }
    // Display ON
    oled[OLED_COMMAND] = C_SET_SLEEP_MODE_OFF;
    OLED_Send_Command(oled);
    // Dummy Print (to make correct link)
    OLED_printf_Position(0, 0);
    OLED_printf("RaspberryPi");
    //
    // Send Bitmap Data2
    //
    time_sleep( 1 );  // wait for 1s
  }
   gpioWrite(16,0);    // OLED Vcc PowerOFF
   spiClose(oled1);
   spiClose(oled2);
   gpioTerminate();

}
//=========================================================
// End of Program
//=========================================================

oled.h

ifndef __OLED_H__
#define __OLED_H__

//===============
// Define Colors
//===============
#define OLED_RED_MAX 0x1f
#define OLED_GRN_MAX 0x3f
#define OLED_BLU_MAX 0x1f
#define OLED_RED_MIN 0x00
#define OLED_GRN_MIN 0x00
#define OLED_BLU_MIN 0x00
#define OLED_RED_MID 0x10
#define OLED_GRN_MID 0x20
#define OLED_BLU_MID 0x10
//
#define OLED_RED ((OLED_RED_MAX << 11) + (OLED_GRN_MIN << 5) + (OLED_BLU_MIN << 0))
#define OLED_GRN ((OLED_RED_MIN << 11) + (OLED_GRN_MAX << 5) + (OLED_BLU_MIN << 0))
#define OLED_BLU ((OLED_RED_MIN << 11) + (OLED_GRN_MIN << 5) + (OLED_BLU_MAX << 0))
#define OLED_BLK ((OLED_RED_MIN << 11) + (OLED_GRN_MIN << 5) + (OLED_BLU_MIN << 0))
#define OLED_WHT ((OLED_RED_MAX << 11) + (OLED_GRN_MAX << 5) + (OLED_BLU_MAX << 0))
#define OLED_YEL ((OLED_RED_MAX << 11) + (OLED_GRN_MAX << 5) + (OLED_BLU_MIN << 0))
#define OLED_CYN ((OLED_RED_MIN << 11) + (OLED_GRN_MAX << 5) + (OLED_BLU_MAX << 0))
#define OLED_MAG ((OLED_RED_MAX << 11) + (OLED_GRN_MIN << 5) + (OLED_BLU_MAX << 0))
#define OLED_GRY ((OLED_RED_MID << 11) + (OLED_GRN_MID << 5) + (OLED_BLU_MID << 0))

//=================
// Font Parameters
//=================
#define OLED_FONT_SMALL  0
#define OLED_FONT_MEDIUM 1
#define OLED_FONT_LARGE  2

//=================
// Orientation Mode
//=================
enum OELD_ORIENTATION_MODE {OLED_TOP_N, OLED_TOP_W, OLED_TOP_S, OLED_TOP_E};

//==============
// Prototypes
//==============
int  Init_OLED(void);
void Init_OLED_with_Orientation(uint32_t mode);
void OLED_Send_Command(uint32_t *oled);
void OLED_Send_Pixel(uint32_t color);
uint32_t OLED_Draw_Text_Small(char *pStr, uint32_t posx, uint32_t posy, uint32_t color_f, uint32_t color_b);
uint32_t OLED_Draw_Text_Medium(char *pStr, uint32_t posx, uint32_t posy, uint32_t color_f, uint32_t color_b);
uint32_t OLED_Draw_Text_Large(char *pStr, uint32_t posx, uint32_t posy, uint32_t color_f, uint32_t color_b);
void OLED_Draw_Char(char ch, uint32_t posx, uint32_t posy, uint32_t color_f, uint32_t color_b, uint32_t scale);
void OLED_Draw_Dot(int32_t x, int32_t y, int32_t size, uint32_t color);
void OLED_Clear_Screen(uint32_t color);
void OLED_Fill_Rect(int32_t x0, int32_t y0, int32_t xsize, int32_t ysize, uint32_t color);
char OLED_Num4_to_Char(uint32_t num4);
uint32_t OLED_Draw_Hex(uint32_t bitlen, uint32_t hex, uint32_t posx, uint32_t posy, uint32_t color_f, uint32_t color_b);
uint32_t OLED_Make_Color(uint32_t num);
//
void OLED_printf_Font(uint32_t font);
void OLED_printf_Color(uint32_t color_f, uint32_t color_b); // corrected 2011.03.20 MM
void OLED_printf_Position(uint32_t posx, uint32_t posy);
void OLED_printf(const char *format, ...);

#endif // __OLED_H__
カテゴリー: RaspberryPi | コメントする

WiringPi-Python最新対応

WiringPiはPi2として最新化されているが、Python対応はメンテが止まったように
見えて困っていた。
次のUpdateによるインストールで、4.4系や4.9系のPython,Python3 共に対応できた
のでまとめておく。

1)Raspbianの、この時点の最新バイナリをダウンロードしインストールする。
  https://downloads.raspberrypi.org/raspbian_latest
2)4.9系にUPしたい人は、次を実施する。
  sudo rpi-update
  sudo reboot
3)sudo apt-get update;sudo apt-get upgrade -y
4)sudo apt-get install -y python-dev python-setuptools swig
5)WiringPiのPython wrapper をダウンロードする。
  git clone https://github.com/Gadgetoid/WiringPi2-Python.git
  cd WiringPi2-Python
6)WiringPi部分を最新化する。
  wget -O wiring.tar.gz https://git.drogon.net/?p=wiringPi;a=snapshot;h=96344ff7125182989f98d3be8d111952a8f74e15;sf=tgz
    (?とp=は空けないこと)
  tar xzf *.gz
  cp -r wiringPi*/* WiringPi
7)setup.py の Extension の途中に次の行を追加
    extra_link_args=[‘-lrt’,’-lcrypt’],
8)不要ファイルの削除
  WiringPi/devLib 配下の不要な piFaceOld.c を削除
9)wiringpi.i の398行目の修正
  PyString_FromStringAndSize( ⇒ PyUnicode_FromStringAndSize(
10)./build.sh で最終インストール
  build.sh はPython とPyhton3 を同時にインストールできるように編集

swig2.0 -python -threads wiringpi.i
sudo python setup.py build install
sudo python3 setup.py build install
sudo python test.py
sudo python3 test.py

カテゴリー: RaspberryPi | 1件のコメント

【訃報】水野さん

47東京白堊会 各位

こんばんは。
悲しいお知らせですが、同期5組だった水野(藤原)明美さんが7月25日に
ご入院中の病院にてご逝去されました。
肺に転移して、息苦しいと感じ受診したら、原発は乳がんで最終ステージ
だったとのことです。
ご家族から、次のとおりご葬儀のお知らせをいただきましたので、
お知らせ申し上げます。

通夜式 7月27日(水) 18時~
告別式 7月28日(木) 12時
場所  さがみ典礼・土浦ホール 〒300-0048 茨城県土浦市田中1-6-9
    ℡:029-823-4999  (JR常磐線土浦駅から車で7分)

カテゴリー: お知らせ | コメントする

PiZeroでUSB接続インターネット

USBドライバーとDNSサーバーの設定でつまづいたので、ノウハウをメモ。

1)最新Jessieをダウンロードし、マイクロSDを作る。
2)Windows上で、config.txt file に dtoverlay=dwc2 を行追加し、保存する。
3)Windows上で、cmdline.txt file の rootwait の後ろに modules-load=dwc2,g_ether を追記し、保存する。
4)これで一旦、コンソール環境のある構成にて、SDからRaspbianOSを立ち上げ、
次の設定をする。
5)/etc/network/interfacesに次を書き込む。

allow-hotplug usb0
iface usb0 inet static
address 192.168.137.2
netmask 255.255.255.0
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf
dns-nameservers 192.168.1.1

6)SDメモリカードをPiZeroに入れ、マイクロUSBケーブルをPCに接続する。
  PowerUSBではなく内側のUSB端子です。
7)PCのデバイスマネージャーで、ポートCOMnにシリアルIOとして現れたら、
  そのドライバを、このモジュールで更新する。
  
8)デバイスマネージャーのネットワークアダプターのところに、
  USB Ethernet/RNDIS Gadget が現れることを確認する。
9)コントロールパネルのネットワーク接続のところにイーサネットとして、
  新しい接続が現れることを確認する。
10)「新しい接続のプロパティ」の「プロトコルバージョン4プロパティ」に
  IPアドレスが 192.168.137.1 と設定されることを確認。違っていれば
  修正する。
11)メイン接続のプロパティの共有タブで、共有を許可し、許可プロトコルを
  確認・設定する。LANのアドレスが、137に変わるという警告は無視する。
12)PiZeroを再起動する。

これで、PiZeroからインターネットにUSB経由で出ることができる。

カテゴリー: RaspberryPi | 1件のコメント

Arduinoで、LCD日本語表示

ArduinoMEGA用のスケッチができたので、メモしておきます。
【追記】漢字ROM判断や縦横切替、スクロールなどの機能追加
実際の表示例は、こんな風になります。
追加ライブラリ:
  Adafruit_TFTLCD
  Adafruit_GFX
  fontx  TFTKanji
  fontR  ここ・漢字ROM無しなら、SD内のフォントfileを使う
追加フォント:
  VMNL12.lzh http://homepage3.nifty.com/silo/FONTV/
  漢字ROM   スイッチサイエンス
入力データ中の特殊コード:
  \n 改行
  \a この行をSDへ追加保存
  \c 色を変更する(次が0~7)
  \d 保存ファイル削除
  \f 表示データを保存ファイルからとする
  \s スクリーンクリア
  \1~4 倍角表示
  \6~9 画面回転(0~3)、0,2はスクロールモード

// IMPORTANT: Adafruit_TFTLCD LIBRARY MUST BE SPECIFICALLY
// CONFIGURED FOR EITHER THE TFT SHIELD OR THE BREAKOUT BOARD.
// SEE RELEVANT COMMENTS IN Adafruit_TFTLCD.h FOR SETUP.
//Technical support:goodtft@163.com
// SDカード用ライブラリ
#include <SD.h>
#include <SPI.h>

// FONTライブラリ
#include <fontR.h>
#include <fontx.h>
// 漢字パターン格納用
unsigned char matrixdata32[32]; //16×16用表示データ
unsigned char matrixdata16[16]; //16× 8用表示データ
int s;                          //a font memory size

#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_TFTLCD.h> // Hardware-specific library

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// Assign human-readable names to some common 16-bit color values:
#define	BLACK   0x0000
#define	BLUE    0x001F
#define	RED     0xF800
#define	GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF

Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Adafruit_TFTLCD tft;
int16_t x = 0; int16_t y = 0;
File dispF;
uint8_t size = 2, xsize = size, yf = 0, ROM = 1;
uint16_t color = WHITE, bg = BLUE;
uint16_t palette[8] = {BLACK,BLUE,RED,GREEN,CYAN,MAGENTA,YELLOW,WHITE};
char input[12] = "dispMsg.txt";
 
void setup(void) {
  // ROMの初期化               53,51,50,52
  //                  Unoでは、10,11,12,13
  pinMode (SS, OUTPUT);
  Serial.begin(115200);
 /*SPI通信の設定*/
  SPI.begin ();
  SPI.setBitOrder(MSBFIRST);
  SPI.setDataMode(3);
  SPI.setClockDivider(SPI_CLOCK_DIV16);
  Serial.println(F("TFT LCD Kanji test"));
  readFontASCII(0x70, 260048);
  if (matrixdata16[8]==0) {
    ROM = 0;
    Serial.println(F("SD Font is used"));
  }
  Serial.println(F("Using Adafruit 3.5\" TFT Mega Board Pinout"));
  Serial.print("TFT size is "); Serial.print(tft.width());
  Serial.print("x"); Serial.println(tft.height());

  tft.reset();

  uint16_t identifier = tft.readID();
  if (identifier == 0x9481) {
    Serial.println(F("Found ILI9481 LCD driver"));
  }
  else {
    Serial.print(F("Unknown LCD driver chip: "));
    Serial.println(identifier, HEX);
    return;
  }
  // SDカードの初期化               35,51,50,52
  if (!SD.begin(35)) {  // Unoでは、 9,11,12,13
    Serial.println(F("SD card error !"));
    return;
  }

  tft.begin(identifier);
  tft.setRotation(3);
  tft.fillScreen(BLUE);
  tft.setCursor(0, 0);
  // 準備ができたら「準備完了!」と送信。
  // ArduinoIDEはShift_JISなのでエスケープ文字をつけて文字コードを送信する。
  Serial.print("Arduino,\x8F\x80 \x94\xF5 \x8A\xAE \x97\xB9 \x81\x49\n");
//  if (SD.exists(input)) dispF = SD.open(input);
}

void loop(void) {
  int ix=16, iy=16, p=32, ixb;
  // 文字コード格納用
  static unsigned int kanji;
  // 受信データが届くまで待つ
  if (!dispF) while (!Serial.available());
  else if (!dispF.available()) {
    dispF.close();
    return;
  }
  // 文字コードを検知して1バイト文字なら1バイトだけ抜き出し、
  // 2バイト文字なら2バイトをくっつける
  if (dispF)
       kanji = (unsigned int)dispF.read() << 8;
  else kanji = (unsigned int)Serial.read() << 8;
  if ((kanji >= 0x8000 && kanji <= 0xA000) || kanji >= 0xE000) {
    if (!dispF) {
      while (!Serial.available());
      kanji |= Serial.read();
    } else kanji |= dispF.read();
    xsize = size;  // 全角ピッチ
    // パターン取得
    if (ROM) showSJIS2byte(kanji) ;
//    sendDotsToSerial32();
  } else { // 半角
    kanji >>= 8;
    if (kanji == 0x5C) {
      int peek,c;
      if (!dispF) {
        while (!Serial.available());
        peek = Serial.peek();
      } else peek = dispF.read();
      if (peek == 0x6E) { // \n 改行
        if (!dispF) {
          Serial.read();
        }
        x = 1000;  // 強制改行
        return;
      } else if (peek== 0x61) {  // \a ファイル追記
        Serial.println("File creation and addition");
        Serial.read();
        dispF = SD.open(input, FILE_WRITE);
        while(Serial.available()) dispF.write(Serial.read());
        dispF.close();
        return;
      } else if (peek== 0x63) {  // \c 色変更
        if (!dispF) {
          Serial.read();
          while (!Serial.available());
          c = Serial.read();
        } else c=dispF.read();
        color = palette[c-0x30];
        return;
      } else if (peek== 0x64) {  // \d ファイル削除
        Serial.println("File remove");
        dispF.close();
        SD.remove(input);Serial.read();
        return;
      } else if ((peek == 0x66) || (peek == 0x73)) {  // \f ファイル読込 \s クリア
        tft.fillScreen(BLUE);
        x=0;y=0;yf=0;
        tft.setScroll(tft.height());
        if (peek==0x66) dispF = SD.open(input);
        Serial.read();
        return;
      } else if ((peek >= 0x31) &
                 (peek <= 0x34)) {  // \w 倍角
        size = peek-0x30;
        xsize = size;  // 全角ピッチ
        Serial.read();
        return;
      } else if ((peek >= 0x36) &
                 (peek <= 0x39)) {  // \r Rotate
        tft.setRotation(peek-0x36);
        tft.setScroll(tft.height());
        Serial.read();
        return;
      } else {
        char othercode[20];
        sprintf(othercode,"Another code=%2x",Serial.peek());
        Serial.println(othercode);
      }
    }
    //    kanji = AsciiZen(kanji);
    xsize = 8;  // 半角ピッチ
    // パターン取得
    if (ROM) showSJIS1byte(kanji) ;
  }
  if (ROM==0){
       unsigned long p = KanjiReadX(kanji, matrixdata32) ;
       // 1バイトに満たない場合は穴埋めされるので
       // それに合わせて穴埋めする。
      ix = (p >> 24) & 0xff; ixb = (ix+7)>>3;
      // 戻り値からフォントサイズのみ抜き出す。
      iy = (p >> 16) & 0xff;
      s = p & 0xffff;
//      char st[16];
//      sprintf(st, "%d,%d,size=%d\n", ix, iy, s);
//      Serial.println(st);
//      sendDotsToSerial32();
  }
   if (x > tft.width() - ix * size) { // Clip right
      x = 0;
      y = (y > tft.height()-(iy*size+2)*2)? 0:y+iy*size + 2;
      if (yf || (y==0)) {
        if (yf==0) {yf = 1;}
        int rotate = tft.getRotation();
        if (rotate==0) tft.scroll(tft.height()-y-(iy*size+2));
        if (rotate==2) tft.scroll(y+(iy*size+2));
        tft.fillRect(0, y, tft.width(), iy*size+2, bg);
      }
   } 
   // 表示用ループ。
   if (ROM) { for (int i = 0; i < 8; i++) {
      char byteDigit = (1 << i);
      if (xsize<8) for (int b = 0; b < ix; b++) { // 全角をp/iy行分分散で描く
        tft.fillRect(x + b*size, y+i*size, size, size, (matrixdata32[b] & byteDigit)? color:bg);
        tft.fillRect(x + b*size, y+(8+i)*size, size, size, (matrixdata32[b+ix] & byteDigit)? color:bg);
      }
      else for (int b = 0; b < ix/2; b++) { // 半角をp/iy行分分散で描く
        tft.fillRect(x + b*size, y+i*size, size, size, (matrixdata16[b] & byteDigit)? color:bg);
        tft.fillRect(x + b*size, y+(8+i)*size, size, size, (matrixdata16[b+ix/2] & byteDigit)? color:bg);
      }}
      x += (xsize<8)? ix * size: ix/2*size;
    }
    else { // SD font
      int z = 0,ys = 0;
//     Serial.println(s);
//     Serial.println(ixb);
      while (z < s) {
        for (int i = 0; i < 8; i++)
           tft.fillRect(x + i*size, y+ys, size, size, (matrixdata32[z] & (1 << (7-i)))? color:bg);
        x += 8*size;
        if (!(++z % ixb)) {
           ys += size;
           x  -= ixb*8*size;
        }
      }
      x += ix * size;
    }
}
/*シリアルモニタへ16*16のデータを表示する
void sendDotsToSerial32()
{
    for (int i = 0; i < 8; i++) {
      char byteDigit = (1 << i);
      for (int b = 0; b < 16; b++)
         Serial.write((matrixdata32[b] & byteDigit)? "XX":"--");
      Serial.println();
    }
    for (int i = 0; i < 8; i++) {
      char byteDigit = (1 << i);
      for (int b = 16; b < 32; b++)
         Serial.write((matrixdata32[b] & byteDigit)? "XX":"--");
      Serial.println();
    }
    Serial.println();
} //sendDataToSerial32 */
カテゴリー: つれづれ | 5件のコメント

RasPIのミニLCD漢字表示

DSC_0672TG12864Bという128x64ドット表示の
グラフィックLCDが遊んでいたので、
RasPiにつないで、門真なむ様公開の
8x12のフォントを使い、自由に
漢字表示するプログラムを作りました。

参考にしたのは、ここですが、
次の4点を改良しました。

1)漢字コード系を自由に扱いたく、Python言語で書き替えました。
2)8×12の、割ときれいなフォントを扱うことができます。
3)GPIOピンの割り当てを自在にしました。
4)コマンドラインからも簡単に表示できます。

$ sudo python kanji812.py ☆グラフィック液晶に日本語表示☆8×12のビットマップフォントを使用して16文字を4行表示にしています。とても読み易い感触です。

<kanji812.py>

# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import sys
import time

# コマンドの発行
def command(value, mode):
 GPIO.output(pinRS, mode)
 for i in range(len(pinDB)):
  GPIO.output(pinDB[i], (value \&gt;\&gt; i) \&amp; 0x01)

 GPIO.output(pinE,True)
 GPIO.output(pinE,False)

# ページの設定(縦アドレス0~7)
def setPage(value):
 command(0xb8 | (value \&amp; 0x07), False)

# カラムの設定(横アドレス0~63)
def setColumn(value):
 command(0x40 | (value \&amp; 0x3f), False)

# 8ビットのデータを書き込む
# 書込んだ後、カラムアドレスは自動的に次へ移動する
def writeData(value):
 command(value, True)

# ディスプレイのICチップを選択
def selectIC(value):
 # 1=左側ディスプレイのIC1チップ 2=右側ディスプレイのIC2チップ
 if(value == 1):
   GPIO.output(pinCS1, True)
   GPIO.output(pinCS2, False)
 else:
   GPIO.output(pinCS1, False)
   GPIO.output(pinCS2, True)

# 初期化
def init():
 GPIO.setwarnings(False)
 GPIO.setmode(GPIO.BCM)
 time.sleep(0.05)
 GPIO.setup(pinRS, GPIO.OUT)
 GPIO.setup(pinE, GPIO.OUT)
 GPIO.setup(pinCS1, GPIO.OUT)
 GPIO.setup(pinCS2, GPIO.OUT)
 for i in pinDB:
   GPIO.setup(i, GPIO.OUT)

 GPIO.output(pinRS, False)
 GPIO.output(pinE, False)
 GPIO.output(pinCS1, False)
 GPIO.output(pinCS2, False)
 for i in pinDB:
   GPIO.output(i, False)

 for i in [1, 2]:
   selectIC(i)
   command(0xc0, False) # Display start line コマンド
   command(0x3f, False) # Display On コマンド

# 画面クリア
def cls():
 for i in [1, 2]:
   selectIC(i)
 for j in range(9):
   setPage(j)
   setColumn(0)
 for k in range(65):
   writeData(0x00)

yoko = int(1128/8-30)
tate = 752
img = [[0 for x in range(yoko)] for y in range(tate)]
# BMPデータを取り込む
def readBMAP():
 f = open("k8x12L_jisx0208.bmp", "rb")

 # ヘッダースキップ
 c = f.read(62)

 # 配列に読み込み
 global img
 for y in range(tate):
   c = f.read(30) # 未使用部分スキップ
   for x in range(yoko):
     img[y][x] = ord(f.read(1))
   c = f.read(3) # 詰め物スキップ
 f.close()

# 画面に描画
lcdLine = 0
def dispEUC(c1,txt):
 difku = (ord(txt[0:1]) -0xA1) \&amp; 0xFF
 difb = difku+(difku\&gt;\&gt;1)
 difcd = ord(txt[1:2]) -0xA1
 difcd *= 8
 c = c1 - 1
 selectIC(((c\&amp;0x8)\&gt;\&gt;3)+1)
 setPage(lcdLine)
 setColumn(8*(c\&amp;0x7))
 for y in range(8):
   bb1 = img[tate-1-difcd-y][yoko-2-difb]
   bb2 = img[tate-1-difcd-y][yoko-1-difb]
   bb = ((bb1\&lt;\&lt;8) | bb2) \&gt;\&gt; 4
   writeData(~(bb \&amp; 0xFF) if (difku%2==1) else ~bb2)
 setPage(lcdLine+1)
 setColumn(8*(c\&amp;0x7))
 for y in range(8):
   bb1 = img[tate-1-difcd-y][yoko-2-difb]
   writeData(~(((bb1\&gt;\&gt;4) if (difku%2==1) else bb1) | 0xF0))

# 文字列の入力と変換
def inputUTF():
 strg=raw_input(' 文字列を入力してください=\&gt; ')
 reptEUC(strg)
def reptEUC(txt):
 global lcdLine
 strg=txt.decode('utf-8').encode('euc-jp')
 skip=0
 c=0
 for i in range(len(strg)):
   if (skip==1):
     skip=0
     continue
   if(((c%16)==0) \&amp; (c\&gt;0)):
     lcdLine+=2
   code=ord(strg[i:i+1]) \&amp; 0xFF
   if (code\&lt;0x2F):
     if (code==0):
       break
     else:
       continue
   c+=1
   if (code\&lt;0x7F):
     if (code==0x5C):
       lcdLine+=2
       c=0
       skip=1
       continue
     dispEUC(c,chr(0xA3)+chr(code|0x80))
     continue
   dispEUC(c,strg[i:i+2])
   skip=1

pinRS = 14
pinE = 15
pinCS1 = 17
pinCS2 = 18

pinDB = 8 * [0]
pinDB[0] = 7
pinDB[1] = 8
pinDB[2] = 9
pinDB[3] = 10
pinDB[4] = 11
pinDB[5] = 22
pinDB[6] = 23
pinDB[7] = 24

param = sys.argv
init()
cls()
readBMAP()
if (len(param)\&lt;2):
 inputUTF()
else:
 reptEUC(param[1])
GPIO.cleanup()

$ sudo python kanji812.py ☆グラフィック液晶に日本語表示☆8×12のビットマップフォントを使用して16文字を4行表示にしています。とても読み易い感触です。

カテゴリー: RaspberryPi, つれづれ | 1件のコメント

5GHz対応Wifiドングル NETGEAR A6100

5GHz対応Wifiドングル NETGEAR A6100
RaspberryPi2B/Jessie にインストールできたのでメモしておく。

<ツールの準備>
sudo apt-get install gcc make bc screen ncurses-dev

<Kernelの再構築作業>

Kernelソースの取得
$bash -c "$(curl -fsSSL https://raw.githubusercontent.com/moutend/raspi-kernel/master/raspi-kernel)"

#cd /usr/src/linux*   (pwd:/usr/src/linux#)
#modprobe configs
#zcat /proc/config.gz > .config
#cp ../firmware/extra/Module7.symvers Module.symvers

Kernelのコンパイル
#make oldconfig
#make -j4 zImage modules dtbs
#make modules_install

/boot下を入替
#cp arch/arm/boot/dts/*.dtb /boot/
#cp arch/arm/boot/dts/overlays/*.dts /boot/overlays/
#cp arch/arm/boot/dts/overlays/README /boot/overlays/

#ls /boot | grep kernel
kernel.img kernel7.img

#cp /boot/kernel7.img /boot/kernel7.img.old
#scripts/mkknlimg arch/arm/boot/zImage /boot/kernel7.img

#reboot

<NETGEAR A6100のドライバー構築>
GitHubからドライバー・ソースの入手
$cd /usr/src
$sudo su
#git clone https://github.com/gnab/rtl8812au.git
#cd rtl8812au

Makefileを修正して、Pi用に変更
...
CONFIG_PLATFORM_I386_PC = n
...
CONFIG_PLATFORM_ARM_RPI = y

ドライバーのコンパイル
#make -j4
#make install

<Kernelバージョンに合わせ、ドライバーモジュールを設置>
#cp -p 8812au.ko /lib/modules/`uname -r`/kernel/drivers/net/wireless/
#/sbin/depmod `uname -r`
#insmod /lib/modules/'uname -r`/kernel/drivers/net/wireless/8812au.ko
#reboot

<ドライバーの動作を確認>
pi@raspberrypi:~ $ ip addr show wlan0
3: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether a4:2b:8c:07:9d:33 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.31/24 brd 192.168.1.255 scope global wlan0
       valid_lft forever preferred_lft forever
    inet6 2408:210:2484:5800:8a3e:7111:76b4:1dc2/64 scope global noprefixroute dynamic
       valid_lft 14365sec preferred_lft 12565sec
    inet6 fe80::7dae:9f4f:6d48:1d06/64 scope link
       valid_lft forever preferred_lft forever

pi@raspberrypi:~ $ sudo iwlist wlan0 scan | grep GHz | sed 's/^ *//'
Frequency:5.22 GHz (Channel 44)
Frequency:2.412 GHz (Channel 1)
Frequency:2.412 GHz (Channel 1)
Frequency:2.442 GHz (Channel 7)
Frequency:2.447 GHz (Channel 8)
Frequency:2.462 GHz (Channel 11)
Frequency:5.5 GHz (Channel 100)
pi@raspberrypi:~ $

結果は、5GHzのAPもしっかりとSCANされている。
この後、DesktopのWirelessアイコンでAPを選択し、パスコードを入れる。

カテゴリー: RaspberryPi | コメントする

RaspBerryPiのマルチブート設定作業

複数のOSの選択起動ができるberrybootを使う時、既存のOSを追加する
ノウハウをメモしておく。

imgファイルをSquashFs形式に変換して、Addボタン長押しで指定する。

# installs kpartx and squashfs-tools
sudo apt-get install kpartx squashfs-tools
#
# This opens your image file. 
#Change the DownloadedImage.img to what your image file name is.
sudo kpartx -av DownloadedImage.img
#
# After opening the image it will give you at least two /dev/mapper/loop#p#.  
# You want the bigger of the partitions (Normally p2).  
# In this case it was loop 1 is the image and I want partition 2 because it is the bigger of the two.
# sudo mount /dev/mapper/loop1p2 /mnt
# Change # to the loop number the previous command reported.
#
sudo mount /dev/mapper/loop#p2 /mnt
#
# This is what make the image writable on berryboot
# This line should work as is.  It edits the file fstab on the image folder etc
sudo sed -i 's/^\/dev\/mmcblk/#\0/g' /mnt/etc/fstab
#
# This line is what takes the mounted image and converts it the a squashfs image.
# Note if you do this from the raspberry pi it will take several hours (dependent on the original image size).
# Change NewBerryBoot.img to the desired image name.
sudo mksquashfs /mnt NewBerryBoot.img -comp lzo -e lib/modules
#
# This unmounts the image you mounted at the beginning.
# This line should work as is
sudo umount /mnt
#
# This closes the image we opened at the beginning.
# Change the DownloadedImage.img to what your image file name is.
sudo kpartx -d DownloadedImage.img 
カテゴリー: つれづれ | コメントする

?4.4にしました

WordPressを最新の安定版の4.4.2にあげました。
メニューの部活の並びで、幹事会を最終に変更しています。

カテゴリー: つれづれ | コメントする

Raspbian Jessie版でのBluetooth接続方法

Jessie版では、Bluetooth接続に用いるbluezが大きく変更されたため、
次のようにインストール・設定を進める必要があったので、記録しておく。

Bluetoothアダプターを取り付ける。
1)アプリのインストール
 sudo apt-get install bluetooth blueman (その後、再起動)
2)Bluetoothの設定
 WiFiのアダプターが動作していれば外して実施し、Bluetooth確認後、再接続する。

$ bluetoothctl
[bluetooth]# power on
[bluetooth]# agent on
[bluetooth]# default-agent
[bluetooth]# scan on
[bluetooth]# devices
[bluetooth]# pair [TAB]
 

Attempting to pair with 98:91:20:21:5C:0F
[CHG] Device 98:91:20:21:5C:0F Connected: yes
[agent] PIN code: 230347  (ランダムに表示)

ここで、Bluetoothキーボードから、230347[Enter]

[CHG] Device 98:91:20:21:5C:0F Modalias: usb:v05ACp0239d011B
[CHG] Device 98:91:20:21:5C:0F UUIDs:
        00001124-0000-1000-8000-00805f9b34fb
        00001200-0000-1000-8000-00805f9b34fb
[CHG] Device 98:91:20:21:5C:0F Paired: yes
Pairing successful
[CHG] Device 98:91:20:21:5C:0F Connected: no
[CHG] Device 98:91:20:21:5C:0F RSSI: -63
[CHG] Device 98:91:20:21:5C:0F Connected: yes
Authorize service
[agent] Authorize service 00001124-0000-1000-8000-00805f9b34fb (yes/no): 

yes
[bluetooth]# connect [TAB]
[bluetooth]# trust [TAB]  これで、上のYes/Noは今後不要。

[CHG] Device 98:91:20:21:5C:0F Trusted: yes
Changing 98:91:20:21:5C:0F trust succeeded

[bluetooth]# quit 

カテゴリー: RaspberryPi | 1件のコメント