2x2キューブの簡易攻略法

ボケる前に、2x2の最終簡易攻略法を記録しておく。
1)白パーツを雑に下段に集める
2)下段から上段に規律良くパーツを移し、白完全一面を作る
  ・最初は青がターゲット
  ・上段左上の色のパーツを右上に持ってくる
   ・右下直下に現れたら、L’F L
   ・直下底側に現れたら、B R B’
   ・左下に現れたら、R’ D2 R 後、直下底から B R B’
  上側を90°回転し、4個実施したら、完全一面を確認する
  本規律が実際にありがたいのは、最後の1個の時だけかもしれない。
3)下段の黄色パーツの4つ角の位置合わせをする
  隣接交換または、対角交換が1組必要になっている。
  隣接交換:X U’R U L’U’R’U R U
  対角交換:X2 R’U’F’U F R U
4)下段の黄色パーツの黄色の向きを下面に合わせる
  ・下段右下に来たパーツが、黄色横向きなら、
    セクシームーブ:R U R’ U’
  ・下段右下に来たパーツが、黄色手前向きなら、
    逆セクシームーブ:U R U’ R’
5)黄色完全一面を確認し、横回転で上段と面を合わせ完成!

シミュレーションツール、「お告げNavi」は次のURL.

https://mori1-hakua.tokyo/CubeV4/navigation-22to44.html


  

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

2022年間歩行数・4,196,753歩

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

Androidでの自動運転

白堊芸術祭で、初めての試みとしてアプリ・デモの動的展示を実施した。
Windowsでは難なくセットアップできるアプリの自動起動・Shutdownが
Androidではコツが必要だったので、ボケる前に記録しておく。

1)自動電源ON/OFF
  Androidの version10あたりから、システム設定画面に次の項目が登場
  している。
  「自動電源オン/オフ」
  それぞれの時刻を設定し、Activeにしておけばよい。
  なお、オフ中であっても夜中などに、「充電完了」を報告しようとして
  勝手に電源が入るので、要注意!

2)アプリの自動起動/シャットダウン
  システムの設定にもデフォルトアプリの設定があるが、これは常駐設定の
  ことなので、趣旨が違っている。
  そこで、自動運転のためには、著名なMacroDroidアプリをインストールする。
  設定内容について、画面コピーを貼り付けておくことにする。

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

CLOVER-USB版でのWindows11稼働

CLOVER-USB版でのWindows11稼働と、その後の手続きを説明する。

1.NVMe SSDを設置後、NVMeではないSSD/HDDからの旧Windows起動
  なお、ESP(EFI System Boot Partition)は、ここに作成する。
  GPTタイプで、Windows partition前に500MB程度の空き領域があると良い。
2.Rufusのインストール
  https://forest.watch.impress.co.jp/library/software/rufus/
3.Rufusの起動
  ここまでは、CLOVERのインストールで実施済みの作業なので、同様に。
4.Windows11のダウンロード
  「ブートの種類」の「選択」の横の▼マークをクリックし、ダウンロード
  を選択する(オプション設定でUPDATE確認なしだと、マークは出ない)。
  ・その後、「ダウンロード」をクリックする。
  ・バージョンの選択Popupで、「Windows11」を選択し「続ける」。
  ・リリースの選択が追加されるので、「最新のもの」を選択し「続ける」
  ・エディションの選択が現れるので、そのまま「続ける」
  ・「ダウンロード」ボタンが表示されたら、8GB以上の空きのある所に
   ダウンロードを実施する。
5.Windows11のインストール媒体作成
  ・ダウンロードが完了すると、ブートの種類には、ダウンロードした
   ISOイメージファイルが表示されている。
  ・デバイス欄で、インストールに用いるUSBメモリが表示されている。
  ・イメージオプションが、(TPM2.0)になっているので、プルダウンから
   Extended windows(NoTPM)を選択する。
  ・パーティション構成を「GPT」とし「スタート」をクリックして、
  インストール媒体を作成する。

6.Windows11のインストール
  ・NVMe以外のドライブにESPを確実に設置することが肝要なので、ESP
   パーティションの場所を確認する。
  ・作成されたUSBメモリからBootし、インストールを実施する。
   WindowsのインストールISOファイルには、NVMeドライブへのドライバー
   も搭載されているので、インストール先にNVMeドライブを指定できる。
   インストール中に再起動されると、NVMeドライバーなしの状態で一時域
   をアクセスするので、最初の再起動のタイミングで、CLOVERのUSBメモリ
   に差し替える。
  ・インストール先の全領域は、diskpart→ list volume→ select volume→
   clean のあと、convert gpt コマンドで初期状態にしておく。
  ・インストール・プロセスをすべて完了したら、次のコマンド群を投入して、
   ESPに従来のOSを追加登録することもできる。
   OS本体のパーティションコピーを実施後、
   diskpart→ list volume
    (下記コマンドで使うパーティション文字がわかる)
   bcdedit /copy {current} /d “新しい識別文字列(Windows10NVMなど)”
   diskpart→ list volume→ select volume→ uniqueid volume
      (COPYしたOSボリューム・エントリのIDがわかる)
   bcdedit /set 獲得ID device partition=xx: 
   bcdedit /set 獲得ID osdevice partition=xx: 
  ・CLOVER-USB起動から、CLOVERのWindows EFI Boot from EFIを選択して
   Windows11などのOS立ち上げ動作を確認する。

7.CLOVER Boot Loaderの旧Windowsドライブへの搭載
  毎回USBメモリからのWindows起動だと耐久性が心配なので、旧Windowsを
  入れたESPのあるドライブにCLOVER本体を入れ、先頭Bootmgrにリンクする。
   bcdedit /set “{bootmgr}” path \EFI\CLOVER\CLOVERX64.efi
  このリンクは新規にWindowsインストールを実施するごとにもとに戻される
  ので、その都度、再設定する。
  ESPに diskpart→ select volume→ assign letter=S などでドライブレター
  を割り当てるが、Explorerでは管理者モードでもアクセス出来ないので、
   xcopy /e xxxxxx\CLOVER S:\EFI\CLOVER
  のコマンドを管理者コンソールから投入する。

8.USBドライブなしの動作を確認

  USBを差し込まなくても、そのままNVMeドライブの起動を含むアクセスが
  問題ないことを確認する。
  BIOS設定画面では、起動順位の1番が「Windows Boot Manager」と設定されて
  いるが、7.の手順で、次のコマンドを入力しておくと、その記述名に
  変更されて設定されるのでわかりやすい。
   bcdedit /set “{bootmgr}” description “Clover Boot Manager”

なお、再インストールの場合は、USBからのBootにしておく必要がある。


                               以上

カテゴリー: お知らせ | 4件のコメント

PCへのNVMe-SSDの取り付けと設定手順

スロットのないPCへのNVMe-SSDの取り付けと設定手順

1.Storageのパーティション方式は、MBRの世界からGPTの世界へ大変身
2.PCデバイスは、どのようにBootパーティションを辿るか
  NVRAM(不揮発)のエントリーからBoot Managerを探す。
  (bcdedit /enum firmware で定義が見える。例では、MBRやGPTハードの存在定義)
   ファームウェアのブート マネージャー
   ——————————–
   identifier {fwbootmgr}
   displayorder {bootmgr}
    {0210a6f8-841b-11ec-be14-806e6f6e6963}
    {f21ca4b8-83c9-11ec-9e05-806e6f6e6963}
    {338c29dd-8425-11ec-a441-001bdc0fee26}
   timeout 1
 ・MBRは歴史的遺産の方法で、ひたすらドライブの先頭セクターを探している
 ・GPT形式のUEFIだと、FAT32フォーマットのセクターをドライブ内に探す。
  4Kセクターサイズもあるため、最小260MBに及ぶ場合もある。
 ・SATA/AHCIに代わるNVMeプロトコルは、2018年以降の設計ハードでないと
  Firmドライバー未搭載で、ドライブの存在が見えない。
3.旧式マザーボードのNVMeドライブのためのドライバー後付け補給
 ・後付けには、旧式Bootファーム(ROM)への機能追加update と
  エミュレーション型Wrapperソフトの方式があるが、ROM Updateは限定品。
 ・Wrapperでは、フリーソフトのCLOVERが有名だが、USB Bootを標準としており、
  USBメモリの耐久性が心許ない。(USB Bootまでは、ここが参考になる)
4.CLOVERのHDD/SSDドライブへの搭載について
  BCDEDITコマンドで、{bootmgr}へCLOVERを定義する方法で、移行できる。
  CLOVER本体の登録は、EPSパーティションへのドライブレターの割り当て
  (DISKPARTコマンド)と、XCOPY /e コマンドの活用が鍵になる。
  (explorerを管理者モードで起動しても、アクセスはできない。)
5.マルチブートの定義
  すべてBCDEDITコマンドでEPSを保守実施するのが確実である。
  通常許されない、複数のEPSをCLOVERで切り替えながら運用することもできた。
6.コマンド・ログ
  ドライバー搭載とWindows11のマルチブートインストールを実施した実例

カテゴリー: お知らせ | 2件のコメント

本年もよろしくお願いします

https://www.facebook.com/photo/?fbid=4607435852656643&set=a.423777297689207

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

Raspberry Pi Picoでアナログ時計(原子精度)

MicroPythonで楽々プログラミング。十分に高速処理してくれます。
舐めてかかったら、色々、初心に帰ることに(笑い)。
1)UTC(グリニッジ)からLOCAL時間に+9時間・・・・
  桁上りが複雑だったのに、Simpleに組む方法を試行錯誤。
2)針が通過したところの絵を戻すのに、スプライトなんてものは
  無いから、針の汚したところを裏絵で描き戻し。
3)12時の通過時にたくさんの処理が集中しないように、分散化。
4)Core1も使ったスレッド処理を試みるもSMP-OSの無い中では、
  制限がきつい。
5)GPS情報に曜日は載らないので、計算するのね。
  def week(yy, feb):
    days = (125+yy[0]+yy[0]//4+int(“*033614625035″[yy[1]])+yy[2])
    wday = (days-1)%7 if feb==29 and yy[1]<3 else days%7
    return wday

などなど・・・

https://github.com/NorioFujii/GitPython/


カテゴリー: RaspberryPi, お知らせ | 1件のコメント

RaspberryPi Pico で 高度Lチカ 音の光出力

銭湯の料金1回分で買えるRaspberryPi Pico、恐ろしい能力を秘めていました。
専用ICチップ無しにSPDIFで音楽を光送出するのにも使えるPIO機能の装備は、
他の廉価マイコンボードに真似ができません。
Example Programとして用意されている、Sine波出力プログラムを
https://github.com/raspberrypi/pico-playground/tree/master/audio/sine_wave

アレンジして、好みの楽曲のWAVファイルから、高度Lチカによって光再生する
Cソースコードを生成し、コンパイルして書き込む手順をここに公開します。

表面実装タイプのボード1枚のまま、何も増設せずに再生できるように、Flash
2MBの範囲(10秒程度繰返し)で書き込めるサンプルプログラムとします。
Example ProgramのSine波の代わりにWAVファイルから取り出したPCMデータの
先頭から10秒程度を与える形のソースコード生成をツールで支援してくれます。

ソースコード生成のためにPythonプログラムを用意しています。
母艦はWindowsでもMacでもOKですが、ここではPico親類のRaspberry Pi3Bや4B
での操作例をハードコピーしています。

用意すべきWAVファイルは、16BitモードでMonoにフォーマット変換したリアルPCM
のものです。Stereoでの実装は、まだ少しチューニングが必要なようです。

1)ツールによるソースコード生成
(cmd)python3 uf2convWav.py -o sine_wave_spdif.c  -C 入力WAVファイル名
次の uf2convWav.py を実行することで、ソースコード sine_wave_spdif.c
が生成されます。
https://mori1-hakua.tokyo/test/uf2convWav.txt (拡張子変更)

2)Pico開発環境のセットアップ
クイック・セットアップとして紹介されている手順で整備します。
https://www.raspberrypi.org/blog/how-to-blink-an-led-with-raspberry-pi-pico-in-c/
blink.uf2 を作って書き込んでみるのは、いい予行演習になりますね。

3)sine_wave のアレンジ
2)の「cd pico/pico-examples」の代わりに「cd pico/pico-playground」と
入力し、お定まりの手順を実行し、配下のaudio/sine_wave に移動します。
mkdir build
cd build
cmake ..
make
次に、CMakeLists.txtのadd_executable(sine_wave_spdif sine_wave.c)を、
add_executable(sine_wave_spdif sine_wave_spdif.c)に替えます。
また、同じディレクトリ内に、1)で生成したsine_wave_spdif.cを追加します。

4)コンパイルしターゲットファイル作成
再び、buildディレクトリで、
cd build
cmake ..
make
によって、配下のaudio/sine_waveディレクトリに出力されたuf2ファイルを
確認します。(Flash2MBを超えても、平気で書き込むので要注意です)

5)Picoボードへの書き込み
Blinkプログラムと同様の方法です。
PicoボードのBOOTSELボタンを押したまま、母艦からのUSBケーブルを接続し、
次のCopyコマンドを実行します(ケーブル抜差しを避けるにはRUN端子を使う)。
cp build/audio/sine_wave/sine_wave_spdif.uf2 /media/pi/RPI*

6)オーディオ装置への光入力
Picoボードに5Vを供給、光デジタル入力のあるオーディオ装置で、入力形式を
PCMと設定し、光ケーブルの一方をPicoボードのLEDに近づけます。
GPIO12をGNDに落とせば、用意した楽音とサイン波とを交互に切り替えることが
出来ます。
なお、オーディオ装置の初期ボリューム設定には、十分に留意してください。

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

Raspberry Pi Picoで美咲フォントの常駐が出来た

Micro:bit V2に続いて出荷された、RasPIの4ドルのプロセッサボード、
Raspberry Pi Pico。なんと、Flash Memoryに美咲フォントを常駐化できた。
貴重なSRAM領域を殆ど消費しない(Flashからseekで利用)。
電子ペーパー書き込み機や、OLEDのディスプレイなど、日本語の表示が
電池搭載軽端末として実現できる。
産業的にも廉価ツールを普及できるかもしれない。

次にライブラリのソースコードを載せる。

font_read16.py

import os, sys, binascii
from micropython import const
TEXT_NORMAL = const(2)
COLBYTES = const(25)
yoko = 94
tate = 12
fontL = 84
img = [[0 for x in range(yoko)] for y in range(tate)]
# kanjiL = [[0 for x in range(yoko*2)] for y in range(2)]
kanjiL = ""
last_seek = -1
last_eye = 0
# BMPデータを取り込む
fbm = open("images/k8x12L_jisx0208_r.bmp", "rb")
# headerとpadding zero を取り除いたBitmapファイル

# 文字列の入力と変換
def dispUTF(strg, disp=None, rot=None):
    global img, kanjiL, last_seek, last_eye
    strg1 = bytes(strg,'utf-8')
    strg2 = ""
    if strg1[0]==0:  # 半角の時、全角に
        i = strg1[1]+0x20
        strg1 = chr(strg1[1]).encode()
        strg2 = "ff" + ('%02x' % (i^0xC0 if i&0x80 else i^0x40)) 
    elif 0xc2<=strg1[0]<=0xdf:
        strg2 = ('%02x' % (strg1[0]&0x1f)>>2) \
              + ('%02x' % (((strg1[0]&0x1f)<<6)|(strg1[1]&0x3f))%256)
    elif 0xe0<=strg1[0]<=0xef:
        strg2 = ('%02x' % ((strg1[0]&0x0f)<<4 | (strg1[1]&0x3f)>>2)) \
              + ('%02x' % ((strg1[1]<<6)&0xff | strg1[2]&0x3f))
    with open("images/JIS16_tbl.txt", "rb") as ftx:
        # UTF-16(BE) BOM付きで94字/行にcr改行されたFontファイル
        dmy = ftx.read(2)
        i = last_eye
        j = -1
        k = 0
        key = strg2  # '%02x%02x' % (strg1[0],strg1[1])
        x = kanjiL.find(key)
        if x >= 0 and x % 4 == 0:
            j = x // 4
        else:
            for i in range(fontL): # 一定長の読み込みを続ける
                kanjiL = str(binascii.hexlify(ftx.read(yoko*2+2)),'utf-8')
                x = kanjiL.find(key)
                if x < 0 or x & 1 > 0:
                    n = kanjiL[0:yoko*4].find("000d")
                    if n != -1:
                        k += 1
                        dmy = ftx.read(n//2 + 2) # 4バイト文字以降は捨てる
                    continue
                j = x // 4
                break
            if j==-1:
                print('Kanji Not found',key,'from',strg)
                return
            last_eye = i + k
    print(strg1.decode(), last_eye, j, k, key)
    new_seek = tate*(fontL-last_eye-1)*yoko
    if last_seek != new_seek:
        last_seek = new_seek
        fbm.seek(new_seek)
        for y in range(tate):
            img[11-y] = fbm.read(yoko)
    dots = ""
    fontw = 8
#    tate  = 12
    for q in range(tate) :
        c = img[q][j]
        for r in range(0, fontw) :
            dots += ("●●" if (c & (0x80 >> r))==0 else " ")
            if disp:
                pos = disp.x + r*TEXT_NORMAL
                bufc = disp.on if (c & (0x80 >> r))>0 else disp.on ^ 1
                disp.set_pixel(pos,disp.y+q*TEXT_NORMAL, bufc, rotate=rot)
                disp.set_pixel(pos+1,disp.y+q*TEXT_NORMAL, bufc, rotate=rot)  # TEXT_NORMAL times
                disp.set_pixel(pos,disp.y+1+q*TEXT_NORMAL, bufc, rotate=rot)
                disp.set_pixel(pos+1,disp.y+1+q*TEXT_NORMAL, bufc, rotate=rot)  # TEXT_NORMAL times
        dots += "\n"
    if disp :
        disp.x += fontw*TEXT_NORMAL
    else:
        print(dots)

def reptTXT(strg, disp=None, rot=None):
    strg1 = strg.encode() if len("日本語")==3 else bytes(strg, 'utf-8')
    skip=0
    for i in range(len(strg1)):
        if (skip>0):
            skip -= 1
            continue
        code=ord(strg1[i:i+1]) & 0xFF
        if (code<=0x1F):
            if (code==0) :
                break
        elif (code<=0x7F):
            dispUTF(chr(0x00)+chr(code), disp=disp, rot=rot)
        elif (code & 0xe0)==0xe0:
            dispUTF(strg1[i:i+3], disp=disp, rot=rot)
            skip = 2
        elif (code & 0xc0)==0xc0:
            dispUTF(strg1[i:i+2], disp=disp, rot=rot)
            skip = 1

カテゴリー: RaspberryPi, お知らせ | 2件のコメント

Micro:bit V2 で 電子ペーパー表示ができた!

micro:bit v1だと、メモリ不足で歯が立たない
>>> microbit.reset()
MemoryError:
MicroPython v1.9.2-34-gd64154c73 on 2017-09-01; micro:bit v1.0.1 with nRF51822
Type “help()” for more information.
>>>
>>> micropython.mem_info()
stack: 516 out of 1800
GC: total: 10048, used: 672, free: 9376
No. of 1-blocks: 18, 2-blocks: 9, max blk sz: 3, max free sz: 562
>>>

micro:bit v2では、8KBのソースが複数個ロードでき、余裕で動作する。
>>> microbit.reset()
MicroPython v1.13 on 2020-12-21; micro:bit v2.0.0-beta.3 with nRF52833
Type “help()” for more information.
>>>
>>> micropython.mem_info()
stack: 392 out of 7680
GC: total: 64512, used: 24832, free: 39680
No. of 1-blocks: 583, 2-blocks: 199, max blk sz: 189, max free sz: 1266
>>>

# MemoryDisplayライブラリ (MemoDisp.py)

# The MIT License (MIT)
#
# Copyright (c) 2018 ladyada for Adafruit Industries
# pylint: disable=line-too-long
"""
`adafruit_sharpmemorydisplay`
====================================================
  https://github.com/adafruit/circuitpython/releases

"""
from microbit import *
from micropython import const
# import sharp_memorydisp
_SHARPMEM_BIT_WRITECMD = const(0x80)  # in lsb
_SHARPMEM_BIT_VCOM = const(0x40)  # in lsb
_SHARPMEM_BIT_CLEAR = const(0x20)  # in lsb
spi_clk = pin13
spi_scs = pin12

CS_ACTIVE = const(1)
CS_INACTIVE = const(0)
# Colors
BLACK = const(0)
WHITE = const(255)
# Parameters to Change
COLS = const(144)
ROWS = const(168)
COLBYTES = const(COLS // 8)
TEXT_NORMAL = const(2)
ROTATION = list(range(4))

_icons = [getattr(Image, x) for x in dir(Image)
          if hasattr(getattr(Image, x), 'get_pixel')]

def reverse_bit(num):
    """Turn an LSB byte to an MSB byte, and vice versa. Used for SPI as
    it is LSB for the SHARP, but 99% of SPI implementations are MSB only!"""
    result = 0
    for _ in range(8):
        result <<= 1
        result += num & 1
        num >>= 1
    return result
class SharpMemoryDisplay():
    """A driver for sharp memory displays, you can use any size but the
    full display must be buffered in memory!"""

    def __init__(self, spiP, width, height, *,
                 baudrate=2000000, portrait=True, bottom=False):
        self._scs_pin = spi_scs
        # The SCS pin is active HIGH so we can't use bus_device. exciting!
        # scs_pin.switch_to_output(value=True)
        self._baudrate = baudrate
        self._portrait = portrait
        self._bottom = bottom
        self._spi = spiP
        self.width = width
        self.height = height
        # prealloc for when we write the display
        self._buf = bytearray(1)
        self.buffer = bytearray((width // 8) * height)
        # Set the vcom bit to a defined state
        self._vcom = True

    def fill(self, color, start=0, stop=0):
        """completely fill/clear the buffer with a color"""
        if color == 1:
            fill = WHITE
        else:
            fill = BLACK
        if stop == 0:
            bufl = len(self.buffer)
        else:
            bufl = stop*COLBYTES
        if not self._portrait:
            start = 0
            bufl = len(self.buffer)
        elif self._bottom :
            bufl = (self.height - start)*COLBYTES
            if stop>0:
                start = (self.height - stop)*COLBYTES
        for i in range(start, bufl):
            self.buffer[i] = fill

    def clear(self):
        """completely fill/clear the buffer """
        self._scs_pin.write_digital(CS_ACTIVE)
        self._buf[0] = _SHARPMEM_BIT_CLEAR
        self._spi.write(self._buf)
        self._buf[0] = 0
        self._spi.write(self._buf)  # we send one last 0 byte
        self._scs_pin.write_digital(CS_INACTIVE)

    def show(self, start=1, stop=0, rotate=0):
        portrait, bottom = ROTATION[rotate]
        # CS pin is inverted so we have to do this all by hand
        self._scs_pin.write_digital(CS_ACTIVE)
        # toggle the VCOM bit
        self._buf[0] = _SHARPMEM_BIT_WRITECMD
        if self._vcom:
            self._buf[0] |= _SHARPMEM_BIT_VCOM
        self._vcom = not self._vcom
        self._spi.write(self._buf)

        if (not portrait) or stop == 0:
            start = 1
            stop = self.height
            stopl = self.height + 1
        else:
            stopl = stop + 1
        if portrait and bottom :
            stopl = (self.height - start+1) + 1
            start = (self.height - stop) + 1
        line_len = COLBYTES
        slice_from = (start-1) * line_len
        for line in range(start, stopl):
            self._buf[0] = reverse_bit(line)
            self._spi.write(self._buf)
            self._spi.write(
                 memoryview(self.buffer[slice_from : slice_from + line_len]))
            slice_from += line_len
            self._buf[0] = 0
            self._spi.write(self._buf)
        self._spi.write(self._buf)  # we send one last 0 byte
        self._scs_pin.write_digital(CS_INACTIVE)

    def draw_line(self, x0, y0, x1, y1, color=1, rotate=0):
        dx = abs(x1 - x0)
        sx = 1 if x0 < x1 else -1
        dy = -abs(y1 - y0)
        sy = 1 if y0 < y1 else -1

        err = dx + dy
        while True:
            self.set_pixel(x0, y0, color, rotate=0)
            if x0 == x1 and y0 == y1:
                break
            e2 = 2 * err
            if e2 > dy:
                err += dy
                x0 += sx
            if e2 <= dx:
                err += dx
                y0 += sy

    def set_pixel(self, x, y, color=1, rotate=0):
        portrait, bottom = ROTATION[rotate]
        if portrait :
            if bottom :
                x = COLS - x
            shift = 7 - x % 8
            x //= 8
            offset = y
            if bottom :
                offset = ROWS - offset
            offset = offset * COLBYTES + x
        else:
            if not bottom :
                y = COLS - y
            shift = 7 - y % 8
            y //= 8
            offset = x
            if bottom :
                offset = ROWS - offset
            offset = offset * COLBYTES + y
        if offset >= len(self.buffer):
            return
        byte_b = self.buffer[offset]
        if color == 1:
            # Mask *out* a bit to set as black
            byte_b &= ~(0b1 << shift)
        if color == 0:
            # a bit to set as white
            byte_b |= (0b1 << shift)
        self.buffer[offset] = byte_b

    def draw_bin(self, filename):
        with open(filename, "rb") as f:
            f.readinto(self.buffer)

spi.init(baudrate=8000000, bits=8, mode=0)
# Create blank image for drawing.

# デモプログラム

# ここにコードを書いてね :-)
from microbit import *
from micropython import const
import time
import MemoDisp

COLS = const(144)
ROWS = const(168)
COLBYTES = const(COLS // 8)
# Colors
BLACK = const(0)
WHITE = const(255)

# Parameters to Change
WIDTH = 144
HEIGHT = 168
PORTRAIT = (HEIGHT > WIDTH)
BOTTOMUP = True
BORDER = 5
OFFSET_X = 4
OFFSET_Y = 4
TEXT_NORMAL = const(2)

MemoDisp.ROTATION[0] = (PORTRAIT, BOTTOMUP)
MemoDisp.ROTATION[1] = (not PORTRAIT, BOTTOMUP)
MemoDisp.ROTATION[2] = (PORTRAIT, not BOTTOMUP)
MemoDisp.ROTATION[3] = (not PORTRAIT, not BOTTOMUP)

def char_len(char, text_size=TEXT_NORMAL):
    if char in b"\"*+-0123<=>ABCDEFHKLOPQSUXZ[]^bcdefghjklnopqrsxz{":
        return 4 * text_size
    if char in b"!'.:i|":
        return 2 * text_size
    if char in b" (),;I`}":
        return 3 * text_size
    return 5 * text_size

def text_len(text, text_size=TEXT_NORMAL):
    return sum(char_len(c, text_size=text_size) + text_size for c in text)

def draw_image(icon, x, y, color=1, type="T", size=TEXT_NORMAL, rotate=0):
    cols = 5 * size
    rows = 5 * size
    for ox in range(cols):
        if x + ox < 0:
            continue
        if x + ox >= WIDTH:
            return False
        for oy in range(rows):
            if (not icon.get_pixel(ox // size,
                                   oy // size)) and type == "T":
                disp.set_pixel(ox + x + OFFSET_X,
                               oy + y + OFFSET_Y, color ^ 1, rotate=rotate)
                continue
            try:
                disp.set_pixel(ox + x + OFFSET_X,
                               oy + y + OFFSET_Y, color, rotate=rotate)
            except IndexError:
                pass
    return True

def write_text(text, x, y, color=1, text_size=TEXT_NORMAL, rotate=0):
    image = None
    for letter in text:
        image = None
        letter_width = char_len(letter, text_size=text_size)
        if x+letter_width >= WIDTH or ord(letter) == 13:
            y += text_size*5+2
            x = OFFSET_X
        if letter != " " and (x + letter_width) >= 1:
            if ord(letter) > 127:
                image = MemoDisp._icons[ord(letter) - 128]
            else:
                try:
                    image = Image(letter)
                except:
                    pass
        if image is not None:
            if not draw_image(image, x, y, color,
                              type="T", size=text_size, rotate=rotate):
                return
        if ord(letter) != 13:
            x += letter_width + text_size

    del image

# display = adafruit_sharpmemorydisplay.SharpMemoryDisplay(spi, scs, 96, 96)
disp = MemoDisp.SharpMemoryDisplay(spi, COLS, ROWS,
                          portrait=PORTRAIT, bottom=BOTTOMUP)

# Clear display.
disp.fill(1)
disp.show()
# Draw Some Text
text = "Hello World! Good morning."
write_text(text, 0, 5, rotate=0)
disp.draw_line(0, 5+OFFSET_Y + TEXT_NORMAL*5, text_len(text),
                  5+OFFSET_Y + TEXT_NORMAL*5, color=1)
disp.show(5, 35)
write_text(text, 0, 5, rotate=1)
disp.show(5, 35, rotate=1)
write_text(text, 0, 5, rotate=2)
disp.show(5, 35, rotate=2)
write_text(text, 0, 5, rotate=3)
disp.show(5, 35, rotate=3)
sleep(300)
disp.show(5, 35)
disp.fill(1, 5, 35)
sleep(500)
disp.show(5, 35)
write_text("Time = ", 0, 5)
start = time.ticks_ms()
while not button_a.is_pressed():
    past = time.ticks_diff(time.ticks_ms(), start)
    if past % 100 == 0:
        write_text(str(past // 100), TEXT_NORMAL*5*7, 5)
        disp.show(5, 35)
    if past > 800:
        start = time.ticks_ms()
# Display image
with open('Screen1.bin', "wb") as f:
    f.write(disp.buffer)
    
disp.fill(0)
disp.show()
sleep(1000)
disp.draw_bin('Screen1.bin')
disp.show()
# disp.clear()
カテゴリー: Micro:bit, お知らせ | コメントする