objcopyで textセクションの抽出

諸事情があって自分の書いたMIPSアセンブリを純粋に機械語に変換しただけの16進数表示のテキストが
ほしいという状況になった。
今回はMIPSでそういう状況だったがgccを使っているのでアセンブラのところを切り替えれば
x86でもx64でもarmでもなんでも同様の手順でできると思う。

準備

UbuntuやWSLなどを想定している。

$ sudo apt-get install gcc-mips-linux-gnu

50MB近くあるので待つ。

アセンブリコードを用意する。

ラベルも追加しておけばループできる

addi $3, $0, 5
addi $4, $0, 0
L: addi $4, $4, 1
BNE $3, $4, L
nop
nop
nop
....

nopは00000000となる

アセンブラする
$ mips-linux-gnu-as source.s -o source

これは色々と別のセクションやelfヘッダもくっついている

$ mips-linux-gnu-objdump source -h
Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         00004010  00000000  00000000  00000040  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00000000  00000000  00004050  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00000000  00000000  00004050  2**4
                  ALLOC
  3 .reginfo      00000018  00000000  00000000  00004050  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_SIZE
  4 .MIPS.abiflags 00000018  00000000  00000000  00004068  2**3
                  CONTENTS, ALLOC, LOAD, READONLY, DATA, LINK_ONCE_SAME_SIZE
  5 .pdr          00000000  00000000  00000000  00004080  2**2
                  CONTENTS, READONLY
  6 .gnu.attributes 00000010  00000000  00000000  00004080  2**0
                  CONTENTS, READONLY

バイナリを直接表示

$ xxd source
textセクション抽出
$ mips-linux-gnu-objcopy -O binary --only-section=.text ./source ./source.bin
$ xxd source.bin
16進数テキストにする

出力したいフォーマットによってオプションの数字を変える必要がある。

$ xxd -ps -c 4 source.bin > program.hex

-c 4.. 4byte(32bit)単位で表示

$ cat program.hex | head
20030005
20040000
20840001
1464fffe
00000000
00000000
00000000
00000000
00000000
00000000

Rust入門 セットアップ

Bash On Windowsをインストールし直すたびにこれも検索し直しているのは時間がかかって仕方がないのでメモ(2017/12)

WSL上でRust install

$ curl https://sh.rustup.rs -sSf | sh
Current installation options:

   default host triple: x86_64-apple-darwin
     default toolchain: stable
  modify PATH variable: yes

1) Proceed with installation (default)
2) Customize installation
3) Cancel installation

ここではdefaultで、あとで変える。

source $HOME/.cargo/env

を.bashrcにでも.zshrcにでもconfig.fishにでも入れる。

Rust.vimのためにdein.vimを入れる

$ mkdir ~/.cache/dein
$ cd ~/.cache/dein
$ curl https://raw.githubusercontent.com/Shougo/dein.vim/master/bin/installer.sh > installer.sh
$ sh ./installer.sh ~/.cache/dein

.vimrcにRust.vimを追加

" Add or remove your plugins here:
...
call dein#add('rust-lang/rust.vim')

この状態でvimを起動すると、(start時のプラグインチェックが有効になっていれば)
初回起動時に勝手にrust.vimを入れてくれる。

Rust fmtのインストール
だいたいココらへんなのだが
github.com
(nightlyじゃないと動かない?)

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install build-essential
$ rustup install nightly
$ rustup default nightly
$ cargo install rustfmt-nightly

nightlyをデフォルトにしたくなかったらnightlyのライブラリをインストールしたあとに

export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib:$LD_LIBRARY_PATH

を追加すれば良い気がする。

その後。
.vimrcで

let g:rustfmt_autosave = 1
let g:rustfmt_command = '$HOME/.cargo/bin/rustfmt'

とすれば保存時にフォーマッティングシてくれるらしいが、
:RustFmtを実行すると
シンタックスハイライトが消えてカーソルが下まで降りるという現象になった。

以下のようにすれば良いらしい
github.com
よって
.vimrcは

let g:rustfmt_autosave = 1
let g:rustfmt_command = 'cargo fmt -- '

とした。

rust/vim-racerのインストール
github.com

vimプラグインに追加する。

call dein#add('racer-rust/vim-racer')

補完プログラムインストール

$ cargo install racer

補完のためのソースコードをもらう

$ rustup component add rust-src
$ rustc --print sysroot
$(rustc --print sysroot)/lib/rustlib/src/rust/src

が保存されている場所。
このパスを
bashrcなりzshrcなりのRUST_SRC_PATHとしてexportする。
fishなら

set -gx RUST_SRC_PATH $HOME/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/src

のような感じ。

補完したい場所で
insert modeのまま
Ctrl+x -> Ctrl+o
とすると
f:id:katakanan:20171128213137p:plain
補完候補が出る。

WSL(Bash On Windows)を再セットアップ

色々とめんどくさくなったときに再設定するためのメモ

cmd.exeから

オプションなしの削除

>lxrun /uninstall

すべて削除

>lxrun /uninstall /full

最近のWindowsのアップデートでWSLが標準機能になったのでストアからインストール
www.microsoft.com

起動するとroot passwordを設定する。

WSLで
ユーザーの追加 (rootで実行)
(同時にホームディレクトリ作成)

$adduser (new_user)

パスワード設定

$passwd (new_user)

sudoに追加

$usermod -G sudo (new_user)

最後に
cmd.exeから

>ubuntu config --default-user (new_user)

として、ログインユーザーを変更する。

fishをインストールする。
e-tipsmemo.hatenablog.com

KiCADのモデル Fusion360

KiCADには3Dmodelを表示・出力機能がデフォルトであるが、
対応フォーマットがwrlというものだけだ。
一方でフリーの3DCADとしては最も優秀だと思われる
Fusion360の出力フォーマットにwrlはない。
これをFreeCADを使って変換するプラグインがあるらしいのでそれの導入手順をメモる。

0. install

KiCADはVer4.0以降、FreeCADはVer0.15以降
Fusion 360 とFreeCADをインストールしておく。
f:id:katakanan:20171119125757p:plain

ここからFreeCADの補助ツールをダウンロード(インストール不要)
sourceforge.net

解凍したら中のlaunch-kicad_StepUp-Tools.batを編集する必要があるかもしれない。
f:id:katakanan:20171119130227p:plain

1. Footprintは作っておく

f:id:katakanan:20171119130930p:plain:w300

2. Stepファイルの用意

Fusion360で作る。(位置は原点に近い方がいい(あとで調節する))
ここで色付けしてしまう
f:id:katakanan:20171119131242p:plain
Exportでstep file形式を指定。
最終的にwrlファイルを出力したい場所にstpファイルをExportする。

3. 位置調整とwrl出力

launch-kicad_StepUp-Tools.batを起動する。
右側にツールバーのあるFreeCADとなる。
f:id:katakanan:20171119131809p:plain

load kicad footprintで先程作ったフットプリントを読み込む
f:id:katakanan:20171119132039p:plain
f:id:katakanan:20171119132233p:plain

stepファイルをドラッグ&ドロップし、読み込ませる。
位置調整はモデルを選択状態にして右のボタン郡で行う。
選択状態にしないとおこられる。
f:id:katakanan:20171119132526p:plain

位置の調整が終わったら
一旦Ctrl+SでFreeCadのフォーマットで
先程のstepファイルの場所に保存する
export kicadでwrlと位置を調整したstepを出力する。
f:id:katakanan:20171119132911p:plain

いっろいろとメッシュの細かさなどを聞かれるが、全部デフォルトでOK
stepファイルを上書きするかどうか聞かれる。無視。

wrlが出力される。
f:id:katakanan:20171119133039p:plain

4. フットプリントと紐付け

footprintの作成画面上の設定で先程のwrlを設定。
(ここで位置の調整をする必要はない)
f:id:katakanan:20171119133333p:plain

表示→3Dビューアー で
全体が見える(この時点ですでに位置があっているはず)
f:id:katakanan:20171119133612p:plain

これで終了

KiCADは全体的には悪くないCADだが
まったく使いにくいところ(先程の3Dの設定やschとlayout画面での統一性のないキー操作)
があるのでアップデートに期待している。

Verilog ビデオ信号出力(アナログRGB)

忘れないように。
1920x1080@60fpsの場合
ビデオ期間とhsyncの関係
f:id:katakanan:20171114115612p:plain

ビデオ期間とvsyncの関係
f:id:katakanan:20171114115713p:plain:w400

50fpsだとフロントポーチ、バックポーチの各値が違う。
hが横方向のピクセルを、vを縦のラインを数えていくカウンターを用意して、
適当な値になったらvsyncやhsyncを上げればよさそう。

module main(
    clk,
    resetn,
    rout,
    gout,
    bout,
    vsync,
    hsync    
    );

    localparam HDISP = 1920;
    localparam HSSTART = 2008;
    localparam HSEND = 2052;
    localparam HTOTAL = 2200;

    localparam VDISP = 1080;
    localparam VSSTART = 1084;
    localparam VSEND = 1089;
    localparam VTOTAL = 1125;

    input wire clk;
    input wire resetn;
    output reg[7:0] rout;
    output reg[7:0] gout;
    output reg[7:0] bout;
    output reg vsync;
    output reg hsync;
    
    reg[10:0] vcounter;//0 ~ 1124
    reg[11:0] hcounter;//0 ~ 2199
    wire vcount;
    wire disp;
    
    assign vcount = (hcounter == HTOTAL-1)? 1:0;
    assign disp = ((hcounter < HDISP) && (vcounter < VDISP))?1:0; 

    always@(posedge clk)begin
        if(resetn == 1'b0)begin
            vcounter <= 12'b0;
            hcounter <= 12'b0;
    end
        else begin  
            hcounter <= hcounter + 1;

        
            if(hcounter == HTOTAL-1)begin
                hcounter <= 12'b0;
            end
            
            if(vcount == 1'b1)begin
                        vcounter <= vcounter + 1;
            
                        if(vcounter == VTOTAL-1)begin
                            vcounter <= 11'b0;
                        end
            end
            
        end
    end
        
    wire rpattern;
    wire gpattern;
    wire bpattern;
    
    wire vsync_b;
    wire hsync_b;
    
    ///<240 <480 <720 <960 <1200 <1440 <1680 <1920 hcounter
    //r 0    0     0    0   1      1     1     1
    //g 0    0     1    1   0      0     1     1
    //b 0    1     0    1   0      1     0     1
    
    assign rpattern =   ((960 <= hcounter)&&(hcounter < 1920))? 1:0;
    assign gpattern =   (((480  <= hcounter)&&(hcounter < 960))||
                        ((1440 <= hcounter)&&(hcounter < 1920)))? 1:0;
    assign bpattern =   (((240  <= hcounter)&&(hcounter < 480))||
                        ((720  <= hcounter)&&(hcounter < 960))||
                        ((1200  <= hcounter)&&(hcounter < 1440))||
                        ((1680  <= hcounter)&&(hcounter < 1920)))? 1:0;
    
    assign vsync_b = ((VSSTART <= vcounter) && (vcounter <  VSEND))? 1:0;
    assign hsync_b = ((HSSTART <= hcounter) && (hcounter <  HSEND))? 1:0;
    
    always@(posedge clk)begin
        if(resetn == 1'b0)begin
            vsync <= 1'b0;
            hsync <= 1'b0;
            rout <= 8'b0;
            gout <= 8'b0;
            bout <= 8'b0;
        end
        else begin
            vsync <= vsync_b;
            hsync <= hsync_b;
            
            if(disp == 1'b1)begin
                rout <= {8{rpattern}};
                gout <= {8{gpattern}};
                bout <= {8{bpattern}};
            end
            else begin
                rout <= 8'b0;
                gout <= 8'b0;
                bout <= 8'b0;
            end
            
        end
    end

endmodule

clkはFullHDのピクセルクロックの148.5MHzを入れる。
とりあえずカラーバーを表示。
f:id:katakanan:20171114120837p:plain
よさそう。
ここに8bitのDACなどをつければビデオが表示できるはず。

Transition Minimized Differential Signaling のメモ

毎回調べてい気がするのでメモ

#include <iostream>
#include <bitset>

int main()
{
	std::bitset<8> rline[2200] = {0};
	std::bitset<10> rout[2200] = {0};

	//init
	for(int i=0;i<1920;i++)
	{
		rline[i] = 0x50;
	}

	int cnt = -2;

	for(int i=0;i<1920;i++)
	{
		std::cout << rline[i];
		int n0 = 0;
		int n1 = 0;

		if((rline[i].count() >= 5) || ((rline[i].count() == 4) && (rline[i][0] == 0)))
		{
			//XNOR
			std::cout << " XNOR\t";
			bool x = rline[i][0];
			bool y;
			
			for(int j=0;j<=7;j++)
			{
				if(j!=7){y = rline[i][j+1];}
				rout[i][j] = x;
				x = !(x^y);
			}
	
			rout[i][8] = 0;
			rout[i][9] = 0;

			n1 = rout[i].count();
			n0 = rout[i].size() - n1;
			n0 -= 2;

			std::cout << rout[i] <<"\t" << n1 << "\t" << cnt << "\t";
		}
		else
		{
			//XOR
			std::cout << " XOR\t";
			bool x = rline[i][0];
			bool y;
			
			for(int j=0;j<=7;j++)
			{

				if(j!=7){y = rline[i][j+1];}
				rout[i][j] = x;
				x = (x^y);
			}
	
			rout[i][8] = 1;
			rout[i][9] = 0;

			n1 = rout[i].count();
			n0 = rout[i].size() - n1;
			n0--;
			n1--;

			std::cout << rout[i] <<"\t" << n1 << "\t" << cnt << "\t";
		}

		if((cnt == 0) || (n1 == 4))
		{
			rout[i][9] = ~rout[i][8];
			if(rout[i][9])
			{
				rout[i] = ~rout[i];
				rout[i][8] = false;
				rout[i][9] = true;
				cnt = cnt + n0 - n1;
			}
			else
			{
				cnt = cnt - (n0 - n1);
			}
		}
		else
		{
			if(((cnt > 0) && (n1 > 4))||((cnt < 0)&&(n1 < 4)))
			{
				bool tmp = rout[i][8];
				rout[i] = ~rout[i];
				rout[i][8] = tmp;
				rout[i][9] = true;
				if(!rout[i][8])
				{
					cnt = cnt + (n0 - n1);
				}
				else
				{
					cnt = cnt + (n0 - n1) +2;
				}
			}
			else
			{
				rout[i][9] = false;
				if(!rout[i][8])
				{
					cnt = cnt + (n1 - n0) - 2;
				}
				else
				{
					cnt = cnt + n1 - n0;
				}
			}
		}

		std::cout << rout[i] << "\t" << cnt << std::endl ;
	}

	return 0;
}

参考にしたサイト
http://ijarcet.org/wp-content/uploads/IJARCET-VOL-4-ISSUE-4-1576-1579.pdf

だが最後が少し間違っている。

Disp=disp+onesX-zerosX-zerosX

のところを

Disp=disp+onesX-zerosX

であるはず。

ElectronでJCanvasを使う

Javascriptがよくわからなかったので導入がよくわからなかった。


electronのアプリの場所でローカルインストールする

npm install --save-dev jquery
npm install --save-dev jcanvas
index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
	<link href="./style.css" rel="stylesheet">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    <script>
      require('./renderer.js')
    </script>
    <canvas id="pallet" width="300" height="300"></canvas>
  </body>
</html>
renderer.js
window.jQuery = window.$ = require('jquery');
var JCanvas = require('jcanvas');
JCanvas($, window);


$(function(){

	$('#pallet').drawPolygon({
		layer: true,
		fillStyle: '#c33',
		x: 200, y: 200,
		radius: 50,
		sides: 5,
		concavity: 0.5,
		click: function(layer) {
		// Spin star
		$(this).animateLayer(layer, {
		rotate: '+=144'
		});
		}
	});	

});

f:id:katakanan:20171029101251p:plain

CSS内だけでcanvasのサイズを指定すると、表示がおかしくなる。

f:id:katakanan:20171029101318p:plain

その場合は、index.htmlに直接書くか、
jsに以下を追加する。

$('#pallet')[0].width=300;
$('#pallet')[0].height=300;