2024年3月30日土曜日

LS-GLがTFTPでしか起動しなくなったら・・・ [ LS-GL(Debian) ]

LS-GLを久しぶりにセットアップしたい気分になったので、やってみたのですが・・・
なんと、TFTPモードでしか起動しなくなっちったよ???

理由はわからんが起動しないものはしないので、世の中の人に聞いてみることに・・・


U-Bootで起動するための方法を調べてくれている人たちがいるではないですか!!
R.Shingenさんによると、LS-GLには前期型と後期型があるようで、HDDを指定する部分が違うようです!
家のはどうやら後期型らしいのでハードディスクの指定 ide 0:1 みたい。
ちなみに前期型は ide 1:1 らしい。

で、R.Shingenさんのブログのように設定してみるものの家のLS-GLは言うことを聞いてくれな〜い!

仕方なく、さらに世の中の人に頼ることにした・・・

すると!「パソコンと会話ができる男 Livingston のブログ」という、まさに新人類(古)が残してくれた素晴らしい遺産を発見!!


どうしても、
** Too many args (max. 16) **

となってしまって・・・うまくいかない・・
でも、R.Shingenさんのものとよく見くらべてみると、変数内で setenv している部分を発見!!
んん? これって、中で設定しなくてもいいんじゃね?
ってことで、外で設定したら・・・

パンパカパーン!!
大成功でした!!


では、以下に方法を残すこととする。。。


まずは、シリアルコンソールで接続する。
速度は115200bpsですよ!

関係ないけど、速度で「通信速度はボーレートと呼び、単位は [bps] ・・・」とか、平気で言ってるサイトとかがあるけど、どうなの?
まあ、たまたまUARTなどでは同じなだけで、ボーレートの単位は [baud(ボー)] だろ!! ボーだ!ボーだ!
昔々カセットテープでデータセーブしてた データレコーダ をなめんな(笑)


[Ctrl] + [c] などして、U-Bootのコマンドラインに入る。

環境変数を printenv コマンドで確認してみる。
U-BOOTの現状の環境変数(一部伏字)
Marvell>> printenv bootargs=$(bootargs_base) $(bootargs_root) baudrate=115200 loads_echo=0 rootpath=/nfs/arm cpuName=926 CASset=min MALLOC_len=4 bootargs_end=:::XXXXXXXXX:eth0:none ethact=egiga0 ethaddr=xx:xx:xx:xx:xx:xx buffalo_ver=BOOTVER=1.10 buffalo_minor_ver=BOOT_MINOR_VER=1.00 build_time=18:35:39 initrd=initrd.buffalo kernel=uImage.buffalo bootargs_base=console=ttyS0,115200 def_tftp=tftp 0x00100000 $(kernel);tftp 0x00800000 $(initrd);setenv bootargs $(bootargs_base) $(bootargs_root) $(buffalo_ver) tftpboot=yes;bootm 0x00100000 0x00800000 ipaddr=192.168.X.Y bootargs_root=root=/dev/sdaX rw panic=5 filesize=682A84 serverip=192.168.X.Z stdin=serial stdout=serial stderr=serial enaMonExt=no enaFlashBuf=yes enaCpuStream=no ethprime=egiga0 bootdelay=3 disaMvPnp=no overEthAddr=no usb0Mode=host usb1Mode=host force_tftp=1 bootcmd=tftp 0x00100000 $(kernel);tftp 0x00800000 $(initrd);setenv bootargs $(bootargs_base) $(bootargs_root) $(buffalo_ver) tftpboot=yes;bootm 0x00100000 0x00800000

書き換えてみる・・・
ついでにrootパーテーションも変更しておく
U-BOOTでコマンド実行
Marvell>> setenv bootargs_root 'root=/dev/sda2 rw panic=5' Marvell>> setenv bootargs $(bootargs_base) $(bootargs_root) $(buffalo_ver) Marvell>> setenv bootcmd 'ide reset; ext2load ide 0:1 0x00100000 /$(kernel);ext2load ide 0:1 0x00800000 /$(initrd);bootm 0x00100000 0x00800000;'

環境変数を見てみる。
U-BOOTの変更箇所の環境変数
Marvell>> printenv ... bootargs_root=root=/dev/sda2 rw panic=5 bootargs=console=ttyS0,115200 root=/dev/sda2 rw panic=5 BOOTVER=1.10 bootcmd=ide reset; ext2load ide 0:1 0x00100000 /$(kernel);ext2load ide 0:1 0x00800000 /$(initrd);bootm 0x00100000 0x00800000; ...

起動テスト
Marvell>> boot

うまくいったら、再起動して、もう一度 setenvコマンドで設定後、saveenv コマンドで保存しておく・・・

でも、ちょっと問題も・・・この方法だと bootargs を書き換えちゃうので、

bootargs=$(bootargs_base) $(bootargs_root) $(buffalo_ver)

この並びを忘れないようにしないと・・・

あっ!環境変数に備忘録として、フォーマットを書いておけばいいじゃん!
(変数展開しないように、クォーテーションで囲ってね!)

ってことで save の前に
Marvell>> setenv bootargs_FORMAT '$(bootargs_base) $(bootargs_root) $(buffalo_ver)'

これでよし!!
 
Marvell>> saveenv

あ〜今日もめでたい一日でした(笑)

ふんどしの持ち主

2023年7月30日日曜日

PlatformIOでATTiny13A開発 (AVRISP mk II を使う) [ AVR ]

久々にAVRマイコンを使って開発しようと思ったら!!

世の中の変化にびっくりです。

なんと!AVRのATTiny13Aの価格が!!秋月で150円になってる!!

たしか・・・8年ぐらい前に60円ぐらいで買ったような気が!!

いつの話だよってことですが(笑)


その時、喜んで5個ぐらい買って、1個使って4個は大切にしまわれていました。

そんなこんなで、のんきに暮らしているうちに、AtmelはMicrochipに買収されちゃうし、ATTiny202とかの新しくて良さげなチップが70円で買えるし・・・

なので、ATTiny13Aの在庫整理のために使うことにしたのですが・・・

今どきはATTiny13AもArduinoとして開発できるらしいので、そうすることにする。

で、Arduino IDEは使いづらいので、いろいろ探してたら、流行りは PlatformIOらしいのですよ!!

そういうわけで、VSCode上でPlatformIOを使うことにしたのですが、Arduino UNO とかの USBシリアル変換が載ってるボードは簡単に接続して書き込みできるんだけど・・・

ATTiny13Aは、書き込み装置が別に必要なので、虎の子の AVRISPmkIIを使うことにしたのですが、そのままでは認識しないみたい・・・


検索しても、日本語の記事はあまり見つからなかった。
でも、公式ページにはありました。


まあ、その通りに書けばいいのでしょうが、使うライターはAVRISPmkIIだとわかっているので、自分なりに書いてみました。
ようは、avrudeに渡すパラメータupload_flags で指定すれば良いようです。


platformio.ini
[env:attiny13a] platform = atmelavr board = attiny13a framework = arduino upload_flags = -c avrisp2 -p $BOARD_MCU upload_command = avrdude $UPLOAD_FLAGS -U flash:w:$SOURCE:i

こんな感じになりましたとさ・・・

注意点として upload_flags = の次の行からの オプション指定時にオプション文字の後ろに空白を入れて -c avrisp2 などとすると 空白も名前として含まれてしまうので -cavrisp2 というように続けて書くか、上記のように改行して次の行に書かないといけないようです。




2023年3月3日金曜日

できるかな Python:全角文字でもPython書式を揃えたい [ Python ]

[ できるかな Python ] のコーナー


ここでは実用になるかはさておき、Pythonで出来たら楽しいって事をやってみるだけのコーナーです。

前回前々回と全角文字が揃わない問題を取り扱ってきたのだが!!
とうとう、禁断のクラスを作ることに手を染めてしまった・・・

strをサブクラス化してみるという禁断の手に!!

だって、__format__()とかオーバーライドしてみたいじゃん!

で、割とうまく言ったのだが!!
内部で使った正規表現が。。。いまいち自信ないね(笑)
まあ、動いてるっぽいよ未来の俺!


で、今回のレシピはこれ!

<材料>
  • str型
  • east_asian_width()
  • 特殊メソッド__format__()
  • 特殊メソッド__add__()
  • 特殊メソッド__radd__()

<作り方のポイント>
  • __format__()メソッドで全角文字の時に対応する
  • __add__()および__radd__()をオーバーライドして文字列の結合に対応する
  • east_asian_width()で全角文字を判断する
  • formatを正規表現を使って上手に料理する ※これは保証できない(笑)


stringw.py
from __future__ import annotations # 自分自身のクラスを型注釈できるように(必ずソースの先頭) from unicodedata import east_asian_width from functools import reduce from typing import TypeVar, Generic, Callable import re class StringW(str): @property def length(self) -> int: return len(self) @property def width(self) -> int: # Japanese wide-char size is calculated as 2 bytes. return reduce(lambda a, c: a + 1 + (east_asian_width(c) in "FWA"), self, 0) @property def diff(self) -> int: return self.width - self.length def __add__(self, other: StringW) -> StringW: return StringW(super().__add__(other)) def __radd__(self, other: StringW) -> StringW: return StringW(other.__add__(self)) def __format__(self, format: str) -> str: formatreg = r"((?:\S?[<>=^])?[-+ ]?z?#?0?)(\d*)([_,]?\.?\d*\w?)" m = re.match(formatreg, format) def convert(m): if m[2]: width = int(m[2]) - self.diff if not width < 0: return f"{m[1]}{str(width)}{m[3]}" return m[0] newformat = re.sub(formatreg, convert, format) return super().__format__(newformat)
使い方は、文字列をStringW()に渡して、オブジェクトにするだけ!!
あ〜ら不思議!文字列が崩れることなく、表示されちゃう!!
しかも!Pythonのフォーマットも使えちゃう!!

     
<例>
def example(): member: list[dict[str, str | int | float]] = [ { "user name":"あいうえ", "weight":90, "height":177 }, { "user name":"Super 真理雄", "weight":1250, "height":188 }, { "user name":"Ninja", "weight":70, "height":160 }, { "user name":"Mr.エックス", "weight":66, "height":167 }, ] mr = StringW("こんにちは、Mr.x") mr += "!!" print(mr) print(f"length: {mr.length} width: {mr.width}\n") for m in member: name = StringW(m['user name']) print(f"{name:_<13s} : {m['weight']:>8,.1f}Kg : {m['height']:>5}cm") if __name__ == "__main__": example()

<表示結果>
こんにちは、Mr.x!! length: 12 width: 18 あいうえ_____ : 90.0Kg : 177cm Super 真理雄_ : 1,250.0Kg : 188cm Ninja________ : 70.0Kg : 160cm Mr.エックス__ : 66.0Kg : 167cm

ちなみに、プロパティの length はlen()関数と同じ文字数で、
width全角文字を2とした幅を表していますぞ!

めでたしめでたし!
おお!今日は『ひな祭り』ではないですか!!
めでたい!めでたい!


2023年2月21日火曜日

できるかな Python : 辞書(dict)をプロパティの様に参照したい [ Python ]

[ できるかな Python ] のコーナー


ここでは実用になるかはさておき、Pythonで出来たら楽しいって事をやってみるだけのコーナーです。

Pythonで辞書型を使ってる時に、ついつい、Javascriptのように『.』で参照しようとしてしまうってことあるよね。

ん?ない?
まあ、そういう人もいるでしょう・・・

でも、『 [ "  " ] 』をタイプするのは面倒なことってあるよね。
ん?ない?
じゃあいいです。そういう人はキライです・・・


なので、私は、あるということで話を進めるのです。
何がしたいかというと・・・
member = { "name" : "あいうえ", "height" : 177 }
みたいな辞書があった時に、
Javascriptなら・・・
Javascriptの場合
member["name"] member.name
上記のどちらでも参照できるってことですよ!
Pythonは上の方しかできないんだよね〜

そこで、Pythonも『.』方式で値が取れたら、うれしいなぁと・・・

といっても、やることは簡単なのですが(笑)


では早速、今回のレシピです。

<材料>
  • 辞書型のオブジェクト
  • 特殊メソッド__getattr__()
  • 特殊メソッド__getitem__()

<作り方のポイント>
  • __getattr__()メソッドの利用
  • [ ]でのアクセスもできるように__getitem__()も利用
Pythonで頑張る
from __future__ import annotations from typing import TypeVar, Generic T = TypeVar("T") class Prop(Generic[T]): def __init__(self, param: dict[str, T]) -> None: self.param = param def __getattr__(self, key: str) -> T: if isinstance(key, str): key = key.replace("_", " ") return self.param[key] def __getitem__(self, key: str) -> T: return self.param[key] def main(): members: list[dict[str, str | float | int]] = [ { "user name":"あいうえ", "weight":90.0, "height":177 }, { "user name":"Super 真理雄", "weight":250.0, "height":188 }, { "user name":"Ninja", "weight":70.5, "height":160 }, { "user name":"Mr.エックス", "weight":66.5, "height":167 }, ] for m in members: mem = Prop(m) print(f"{mem.weight:5.1f}cm {mem.height:5d}Kg : {mem.user_name}") print(f"{mem['weight']:5.1f}cm {mem['height']:5d}Kg : {mem['user name']}") if __name__ == "__main__": main()
今回は特殊メソッド__getattr__()を使えば解決です!!
簡単な料理でした。。。。。

Prop()に辞書を渡せば、『.』で参照できるオブジェクトを返してくれます。
は〜い。便利???


ちなみに、スペースはアンダースコアとして参照できるようにしてあります。
いわずもがな、Keyはstr型のみの対応です。。。



以上、腱鞘炎の予防対策でした(終)




できるかな Python : カリー化 [ Python ]

[ できるかな Python ] のコーナー


最近、Pythonにハマってるので、いろいろとやってみた!
ここでは実用になるかはさておき、Pythonで出来たら楽しいって事をやってみるだけのコーナーです。


今日は、関数のカリー化です。
カリー化については、Wikipediaでも見てくださいね。


<材料>
  • 引数を複数とる関数
  • lambda式
  • 特殊メソッド__call__()

<作り方のポイント>
  • __call__()の利用
  • 可変引数の利用
  • 引数展開の利用
  • lambda式の利用
  • 関数呼び出し時の引数エラー(TypeError)例外の利用

カリー化
from __future__ import annotations from typing import Callable class LikeCurry: def __init__(self, func: Callable[..., any]) -> None: self.func = func def curry(self, *args: any) -> Callable[..., any]: return lambda *a: self.func(*args, *a) def __call__(self, *args: any) -> any: try: return self.func(*args) except TypeError: return LikeCurry(self.curry(*args)) def main(): def add3(a, b, c): return a + b + c add3c = LikeCurry(add3) print(add3c(2,3,4)) print(add3c(2)(3,4)) print(add3c(2,3)(4)) print(add3c(2)(3)(4)) if __name__ == "__main__": main()

LikeCurry()に関数を渡すとカリー化された関数風味のオブジェクトを返してくれます。
後は関数っぽく使えば・・・・

はい、おいしく出来ました!!!

何が嬉しいのかって?
それは、人それぞれです(笑)




2023年2月15日水曜日

Python書式:全角文字の幅問題(完成のつもり) [ Python ]

前回のつづき「全角文字も揃えたい」です。
がんばっちゃったよ(笑) 暇ともいうが・・・

 Pythonの書式で%sの幅指定が文字数でカウントされるので、文字幅が全角と半角が混在すると全角分ずつずれてしまう問題の解決策をここに書いておくよ!将来の自分のために・・・

で、完成版です、はいこれ!

文字幅の指定を負数にすると左寄せになるのです!


<追記>ついに、禁断の手に出たぞ俺!


member.py
from unicodedata import east_asian_width from functools import reduce member = [ { "name":"あいうえ", "weight":90, "height":177 }, { "name":"Super 真理雄", "weight":250, "height":188 }, { "name":"Ninja", "weight":70, "height":160 }, { "name":"Mr.エックス", "weight":66, "height":167 }, ] padstr = lambda s,w: reduce(lambda a, c: a[east_asian_width(c) in "FWA" and 2 or 1:]+c, s[::(w < 0) and -1 or 1], " "*abs(w))[::(w < 0) and -1 or 1] print("<< padstr(+) >>") for m in member: print(f'{padstr(m["name"], 15)} : {m["weight"]:5}Kg {m["height"]:5}cm') print("-"*50) print("<< padstr(-) >>") for m in member: print(f'{padstr(m["name"], -15)} : {m["weight"]:5}Kg {m["height"]:5}cm')
はい、めっちゃ長いラムダ式になっちまいました。。。。
もう、普通の関数でいいじゃん。。。

まあ、将来の私よ!
今の私の実力はこの程度なのだよ!!
笑ってくれ(笑)


※ちなみに、ラムダ式を変数に代入することはPEP8の推奨事項を無視することになります(笑)


<追記>
んで、もうちょっと短くしてみた・・・

関数のところだけ抜粋・・・

<追記>
コピペ版用にimportも追加しておく
あ、文字幅は 日本語1文字 を としてネ!

最終版?
from unicodedata import east_asian_width from functools import reduce padstr = lambda s,w: reduce(lambda a,c:a[(east_asian_width(c)in"FWA")+1:]+c,s[::abs(w)//w]," "*abs(w))[::abs(w)//w]
よく出来ました。

でも、超読みづらい!!!

おしまい。。。




2023年2月12日日曜日

Python書式:全角文字の幅問題 [ Python ]

いやー、久しぶりにPythonやってみましたよ。
プログラミングたのしいね〜!

今回、print()関数で文字を揃えようと思って、"%-15s"みたいな書式を指定したわけですよ!!
そうしたら、なんと!
全角と半角が混在していると、見た目が崩れてしまう問題がはっせい!!

全角文字幅が1文字扱いのようです!!!

「全角文字も揃えたい」ですよね〜


<<追記>>


member.py
member = [ { "name":"あいうえ", "weight":90, "height":177 }, { "name":"Super 真理雄", "weight":250, "height":188 }, { "name":"Ninja", "weight":70, "height":160 }, { "name":"Mr.エックス", "weight":66, "height":167 }, ] for m in member: print("%-15s : %5dKg %5dcm" % (m["name"], m["weight"], m["height"]))
全角文字揃えが崩れちゃう
あいうえ : 90Kg 177cm Super 真理雄 : 250Kg 188cm Ninja : 70Kg 160cm Mr.エックス : 66Kg 167cm

困りました!てなわけで、世の中の人に聞いてみると!!
note.nkmk.meさんが教えてくれていました!感謝ですな★

なんと!unicodedata.east_asian_width()を使うと素敵になれるようです!

ただ、この関数は全角・半角というのを直接教えてくれるわけではないのです。
いろいろ複雑な事情があるようです・・・
まあ、そこは良いとして、とにかく "F" "W" "A" なら全角、それ以外なら半角ということで判断しましょう!!

よって、全角文字なら幅をもう1文字分必要とするように引き算してやればOKですな!
member.py
from unicodedata import east_asian_width from functools import reduce member = [ { "name":"あいうえ", "weight":90, "height":177 }, { "name":"Super 真理雄", "weight":250, "height":188 }, { "name":"Ninja", "weight":70, "height":160 }, { "name":"Mr.エックス", "weight":66, "height":167 }, ] for m in member: name_w = reduce(lambda a, c: east_asian_width(c) in "FWA" and a-1 or a, m["name"], 15) print("%-*s : %5dKg %5dcm" % (name_w, m["name"], m["weight"], m["height"]))
すばらしい!そろってる!
あいうえ : 90Kg 177cm Super 真理雄 : 250Kg 188cm Ninja : 70Kg 160cm Mr.エックス : 66Kg 167cm

じゃじゃ〜ん!!
素敵になりました!!!

forループとか書くとコードが長くなるので、reduce()を使いました。
これは、functoolsモジュールに入ってます。(python2の頃は組み込み関数だったらしい)

reduce()の行はちょっとゴチャッとしてますが、一行でかけるので、コードの流れがスマートになって良いと思います。(自画自賛)


ポイントは、書式幅も引数(タプル)で指定してやることですぞ!
"%-*s"の"*"が肝です!!


あっ!今気づいたけど、サンプルコードの身長と体重の書式を整数にしてしまった・・・
まあいいや。なおすのめんどい・・・・


もうちょっとすすめて、ラムダ式で関数にしてみた。

member.py
from unicodedata import east_asian_width from functools import reduce member = [ { "name":"あいうえ", "weight":90, "height":177 }, { "name":"Super 真理雄", "weight":250, "height":188 }, { "name":"Ninja", "weight":70, "height":160 }, { "name":"Mr.エックス", "weight":66, "height":167 }, ] withw = lambda s,w:(reduce(lambda a, c: east_asian_width(c) in "FWA" and a-1 or a, s, w), s) for m in member: print("%-*s : %5dKg %5dcm" % (*withw(m["name"], 15) , m["weight"], m["height"]))

このほうが使いやすいな!
ポイントは、このwithw()関数 がタプル ( 文字幅 ,  文字列 ) を返すので、で展開してやるのだ!

う〜ん。まんぞく!
めでたしめでたし!!



<追記>
いやいや、よく考えたら文字幅分をスペースで埋めとけば良かったんじゃね?
アホでした。

member.py
from unicodedata import east_asian_width from functools import reduce member = [ { "name":"あいうえ", "weight":90, "height":177 }, { "name":"Super 真理雄", "weight":250, "height":188 }, { "name":"Ninja", "weight":70, "height":160 }, { "name":"Mr.エックス", "weight":66, "height":167 }, ] padstrl = lambda s,w: reduce(lambda a, c: c+a[:east_asian_width(c) in "FWA" and -2 or -1], s[::-1], " "*w) padstrr = lambda s,w: reduce(lambda a, c: a[east_asian_width(c) in "FWA" and 2 or 1:]+c, s, " "*w) for m in member: print(f'{padstrl(m["name"], 15)} : {m["weight"]:5}Kg {m["height"]:5}cm') print("-"*50) for m in member: print(f'{padstrr(m["name"], 15)} : {m["weight"]:5}Kg {m["height"]:5}cm')

前回のwithw()関数の場合はPythonの書式の方で左寄せと右寄せを指定できたけど、
今回のラムダ式で左寄せと右寄せを一つの式にするのは、
俺の頭では短くかけないので、2つに分けた!


ちなみに、f"" 書式のこともすっかり忘れてました(汗)




ふんどしの持ち主