歴代QWERTYなガジェットリスト

(20200610 加筆)
(20210120 加筆)

小さなWindows PCは割愛。
HP200LXに手を出さなかったのは、当時熱心な林檎教信者でNewtonにハマっていたから。
漏る貧も同じ。
モバギ、シグ2、ジョルに手を出さなかったのは、当時Palmにハマっていたから。
りなざうに手を出さなかったのは、当時MFC開発にハマっていて、CE.netなSigmarion IIIの方がソフトの開発しやすかったから。

Blackberry KEYone見参


リーク情報が出回りだしてから1年、発売から1週間、ようやく手に入りましたよ、Blackberry KEYone (aka Mercury、aka DTEK70)。
米国のGSMモデルなので、BBB100-1、こちらで言うところのUSV1モデル、バンドXIX(19)対応品だ。


さて入手したら早速設定だ。

日本語化

最初から日本語ロケールがサポートされている。
起動して一番最初にロケールの設定になるのだが、ここではEnglish (United Sates)を選んでおくが吉。
なぜならここで日本語で設定してしまうと、いきなりBlackberry キーボード(日本語)が有効になる。
この先の設定で、英語入力に切り替える必要があり、英語 -> 日本語切り替えのショートカットが分からないとドツボにはまる。
ちなみに切り替えは、ALT + ENTERでできる。
全て設定が終わって、使えるようになってから、Setting -> Language and InputでLanguageを日本語にすればよろしい。

日本語入力

今回もこちらで紹介している、Wnn Keyboard Lab+外部変換Google Japan Inputの組み合わせで使用する。
導入直後はBlackberryキーボードも有効になっているため、英語入力時もカンマが「、」に、ピリオドが「。」になってしまう。
これもここで書いている通り、Blackberryキーボードを無効にすればよい。
ただ"設定" -> "アプリ"のデフォルトではBlackberryキーボードが見えないので、右上の3点メニューから「システムを表示」を選択する。
これでBlackberryキーボードが見えるようになるので、後は書いてある通りだ。

いらん・使わんアプリを消す

はみな無効化。
生産性タブも含め、使わなそうなBlackberry&Googleアプリはがんがん消す。

会社のメールの設定

で、必要最低限の動作が確認できたところで、

よく使うアプリをインスコ

  • 2chMate
  • ウィキペデイア
  • ニュース各種(毎日、BBC、現地のニュース、Feedly)
  • SNS(FB、Echofone、Line、Skype、WhatApp、インスタ)
  • 乗り換え案内
  • Perfect Viewer
  • MX Player Pro
  • オンラインバンク
  • ファイラー
  • Smart TaskKiller
  • 写真(QuickPic、FotoSwipe、Fujifilm Camera Remote)
  • Free42
  • 英辞郎 on Web
  • Weather Channel

Blackberryはこれで5台目(9700、9900、9780、Priv、KEYone)だが、史上最強な予感しかしない。
ああもう、KEYoneかわいいよKEYone。

組み込みRAMをQsysでNios IIに接続する

さて、相変わらずこちらの本。

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

今回は前回作成したような組み込みRAMをNios IIに接続してアクセスしてみる。


Mega Wizardではいろいろな構成のRAMやROMを作ることができる。
RAMやROM、ポート数、バス幅やサイズだ。
バス幅やサイズに関しては、2^nの幅・サイズで構成することができる。
8bitより大きいバス幅の場合、Nios IIからはどのように見えるのだろうか?
試しに、32bits x 32wordsのメモリを作ってみる。
組み込みRAMの宣言

module ram (
	clock,
	data,
	rdaddress,
	wraddress,
	wren,
	q);

	input	  clock;
	input	[31:0]  data;
	input	[4:0]  rdaddress;
	input	[4:0]  wraddress;
	input	  wren;
	output	[31:0]  q;

これにAvalon MMに接続できるようなラッパーを書く。

module test_ram(
	// Avalon bus
	input wire in_clk,
	input wire in_reset,
	input wire [4:0] in_address,
	input wire in_write_enable,
	input wire in_read_enable,
	input wire [31:0] in_write_data,
	output wire [31:0] out_read_data);
	//
	// 32bits x 32words eRAM
	//
	ram ram_32bitsx32words(
		.clock(in_clk),
		.data(in_write_data),
		.rdaddress(in_address),
		.wraddress(in_address),
		.wren(in_write_enable),
		.q(out_read_data));
endmodule

これをQsysでNios IIと共に組み込むと、4bytes x 32words = 128bytesのメモリー領域にマップされる。
こいつを、Nios II softwareからアクセスしてみる。

#include "system.h"
#include "io.h"
int main()
{ 
	unsigned long read_value;
	IOWR_32DIRECT(TEST_RAM_0_BASE, 0x00000000, 0x01234567);
	IOWR_32DIRECT(TEST_RAM_0_BASE, 0x00000004, 0x89abcdef);
	read_value = IORD_32DIRECT(TEST_RAM_0_BASE, 0x00000000);
	printf("%x, ", read_value);
	read_value = IORD_32DIRECT(TEST_RAM_0_BASE, 0x00000004);
	printf("%x, ", read_value);
  /* Event loop never exits. */
  while (1);

  return 0;
}

これでNios IIからDWORDサイズでword毎にアクセスできる。
モリーマップを見てみると、以下のようになっている。

  • メモリ先頭アドレス: word 0の[7:0]
  • メモリ先頭アドレス + 1: word 0の[15:8]
  • メモリ先頭アドレス + 2: word 0の[23:16]
  • メモリ先頭アドレス + 3: word 0の[31:24]

となっていることが分かる。
なのでDWORDで1 wordずつ一括で書いていく場合なら、アドレスはsizeof(DWORD) = 4ずつincrementしていく。

組み込みRAMーその1

またしてもこの本でVerilogだ。

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

今回は7-2節で出てくる組み込みRAMの検証だ。


まずはMega WizardでRAMを作る、主な設定は以下の通り。

  • RAM 2 port
  • 1 port read / 1 port write
  • 8bits/word x 16words、memory block typeはautoで選択
  • sigle clock, read enableはなし
  • read portのregisterは外す(出力はクロック非同期)

後はすべてデフォルトで作成する。
出来上がったRAMの宣言はこんな感じになる。

module eram (
	clock,
	data,
	rdaddress,
	wraddress,
	wren,
	q);

	input	  clock;
	input	[7:0]  data;
	input	[3:0]  rdaddress;
	input	[3:0]  wraddress;
	input	  wren;
	output	[7:0]  q;

テストしてみよう。
以下のようなRAMの書き込み、読み出しをするモジュールを作る。

  • 10バイト目(アドレス0x00から0x09)までそのアドレス値を書く
  • それを10バイト目(アドレス0x00から0x09)まで読み出す
module eram_wr_test(
	input wire in_clk,
	input wire in_reset,
	output reg [2:0] state_machine,
	output wire f_counter_write_expired,
	output wire f_counter_read_expired,
	output reg [3:0] _4bit_counter_write,
	output reg [3:0] _4bit_counter_read,
	output wire [7:0] read_buffer,
	output wire [7:0] sram_read_out);
	//
	// state machine
	//
	parameter INIT = 3'b000;
	parameter WRITE = 3'b001;
	parameter HOLD = 3'b010;
	parameter READ = 3'b011;
	parameter STOP = 3'b100;
	//
	always @(posedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			state_machine <= INIT;
		else
		case (state_machine)
			INIT:
					state_machine <= WRITE;
			WRITE:
				if (f_counter_write_expired)
					state_machine <= HOLD;
				else
					state_machine <= WRITE;
			HOLD:
					state_machine <= READ;
			READ:
				if (f_counter_read_expired)
					state_machine <= STOP;
				else
					state_machine <= READ;
			STOP:
					state_machine <= STOP;			
		endcase
	end
	//
	// write counter
	//
	assign f_counter_write_expired = (_4bit_counter_write == 4'd9)? 1'b1: 1'b0;
	//
	always @(negedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			_4bit_counter_write <= 4'd0;
		else if (state_machine == WRITE)
		begin
			if (f_counter_write_expired)
			begin
				_4bit_counter_write <= 4'd0;
			end
			else
			begin
				_4bit_counter_write <= _4bit_counter_write +4'd1;
			end
		end
	end
	//
	// memory writer
	//
	reg [7:0] _8bit_16word_ram [0:15];
	//
	integer counter_ram_clear;
	always @(posedge in_clk, posedge in_reset)
	begin
		if (in_reset)
		begin
			for (counter_ram_clear = 0; counter_ram_clear < 16; counter_ram_clear = counter_ram_clear + 1)
			begin
				_8bit_16word_ram[counter_ram_clear] <= 8'h0;
			end
		end
		else if (state_machine == WRITE)
			_8bit_16word_ram[_4bit_counter_write] = {4'b0000, _4bit_counter_write};
	end
	//
	// read counter
	//
	assign f_counter_read_expired = (_4bit_counter_read == 4'd9)? 1'b1: 1'b0;
	assign read_buffer = (state_machine == READ)? _8bit_16word_ram[_4bit_counter_read]: 8'h00;
	//	
	always @(negedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			_4bit_counter_read <= 4'd0;
		else if (state_machine == READ)
		begin
			if (f_counter_read_expired)
				_4bit_counter_read <= 4'd0;
			else
				_4bit_counter_read <= _4bit_counter_read + 4'd1;
		end
	end
	//
	// ERAM module
	//
	//
	wire write_enable;
	assign write_enable = (state_machine == WRITE)? 1'b1: 1'b0;
	//
	eram ERAM(
		.clock(in_clk),
		.data({4'b0000, _4bit_counter_write}),
		.rdaddress(_4bit_counter_read),
		.wraddress(_4bit_counter_write),
		.wren(write_enable),
		.q(sram_read_out));
endmodule

比較として、同じような8bit幅16wordのレジスタを作り、同時に読み書きする。
こちらがRTLシミュレーションの結果。

一番下2つのうち、上がレジスタの読み出し結果、下が組み込みRAMの読み出し結果だ。
レジスタはアドレスが変われば、読み出し値が変わる、ただのラッチなので当たり前か。
一方組み込みRAMの方はアドレスがセットされて次のクロック立ち上がりでデータが読み出される。

PS/2リーダー

またしてもこの本でVerilogだ。

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

FPGA ボードで学ぶ組込みシステム開発入門 ?Altera編?

今回は7-1節のPS/2インターフェース。
手近にPS/2マウスがなかったため、キーボードの入力を読み込むPS/2リーダーとして実装した。
まずはPS/2リーダーモジュールのVerilog、本のコードからはいくらか変更してある。

  • ステートマシンは読み込み専用に簡略化してある。
  • レジスタマップを変更。
    • アドレス0: PS/2リーダーモジュールの状態レジスタ(PS2STATUS、8bit)、[0]PS/2からの読み出しデータフラグ、1でready、0を書き込むとクリアできる、残りのビットはnull
    • アドレス1: PS/2から読み出したデータ(PS2RDARA、8bit)
  • さらにステートの定義も変更。本ではパリティを受信するステートをSETFLGとしているが、ここではそのままGETBITとしている(後でパリティチェックを実装予定)。STOPBIT(ストップビット待ちの状態)で状態レジスタを変更し、同時にPS/2読み出し値をリードバスへセットしている。
  • PS/2クロックの立下り検出を2段のFFにしている。いろいろやってみたが1段(FF一個とPS/2クロックで直接立下り検出をする)では動作が安定しなかった。
module PS2Reader(
	// Avalon Bus
	input wire in_clk,
	input wire in_reset,
	input wire in_address,
	input wire in_write,
	input wire in_read,
	input wire [7:0] in_write_data,
	output wire [7:0] out_read_data,
	// Ports
	inout wire io_PS2CLK,
	inout wire io_PS2DATA);
	//
	// PS2 Reader State Machine
	//
	reg [3:0] ps2_state;
	// state definition
	parameter HALT = 4'h0;
	parameter GETBIT = 4'h1;
	parameter STOPBIT = 4'h2;
	//
	always @(posedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			ps2_state <= HALT;
		else
		begin
			case (ps2_state)
				HALT:
				begin
					// wait for START BIT
					if (f_ps2clk_fall && (io_PS2DATA == 1'b0))
						ps2_state <= GETBIT;					
					else
						ps2_state <= HALT;
				end
				GETBIT:
				begin
					if (f_ps2clk_fall && (counter_bit_position) == 4'h8)
						ps2_state <= STOPBIT;				
					else
						ps2_state <= GETBIT;
				end
				STOPBIT:
				begin
					// wait for STOP BIT
					if (f_ps2clk_fall && (io_PS2DATA == 1'b1))
						ps2_state <= HALT;					
					else
						ps2_state <= STOPBIT;			
				end
				default:
					ps2_state <= HALT;
			endcase
		end
	end
	//
	// PS2 CLK falling edge detection = f_ps2clkfall
	//
	reg [1:0] ff_ps2clk_fall_detection;
	wire f_ps2clk_fall;
	//
	always @(posedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			ff_ps2clk_fall_detection <= 2'b00;
		else
			ff_ps2clk_fall_detection <= {ff_ps2clk_fall_detection[0], io_PS2CLK};
	end
	//
	assign f_ps2clk_fall = (ff_ps2clk_fall_detection == 2'b10)? 1'b1: 1'b0;
	//
	// S-P bit position counter
	//
	reg [3:0] counter_bit_position;
	//
	always @(posedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			counter_bit_position <= 4'h0;
		else if (ps2_state == HALT)
			counter_bit_position <= 4'h0;
		else if ((ps2_state == GETBIT) && f_ps2clk_fall)
			counter_bit_position <= counter_bit_position + 4'h1;
	end
	//
	// PS2DATA read (S-P read)
	//
	reg [9:0] _10bit_SP_buffer;
	//
	always @(posedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			_10bit_SP_buffer <= 10'b00_0000_0000;
		else if ((ps2_state == GETBIT) && f_ps2clk_fall)
			_10bit_SP_buffer <= {io_PS2DATA, _10bit_SP_buffer[9:1]};
	end
	//
	// flag when read data is ready
	//
	reg f_PS2_data_ready;
	//
	always @(posedge in_clk, posedge in_reset)
	begin
		if (in_reset)
			f_PS2_data_ready <= 1'b0;
		else if ((in_write == 1'b1) && (in_address == 1'b0))
			f_PS2_data_ready <= in_write_data[0];
		else if ((ps2_state == STOPBIT) && f_ps2clk_fall)
			f_PS2_data_ready <= 1'b1;
	end
	//
	// set read data
	//
	assign out_read_data = (in_read == 1'b0)? 8'h0:
		(in_address == 1'b0)? {7'h0, f_PS2_data_ready}: _10bit_SP_buffer[8:1];
	//
endmodule

このモジュールをQsysでNios IIに組み込む。
方法はこちらと同様。
今回は

  • Nios II/e
  • On-chip Memory (RAM or ROM) 8192bytes
  • System ID Peripheral
  • JTAG UART
  • (自作の)ps2reader

そして、キーボードの値を7セグLEDに表示するために、

  • PIO(16bit, output)

を組み込んだ。
QsysでNios IIと周辺機器IPを組み込んだ統合モジュールを作る方法は、こちらと同様。
トップモジュールはこんな感じだ。

module nios2ps2reader(	
	input wire in_clk, 
	input wire [9:0] in_switch, 
	input wire [2:0] in_button, 
	output wire [9:0] out_led, 
	output wire [7:0] seven_segment_0, 
	output wire [7:0] seven_segment_1, 
	output wire [7:0] seven_segment_2, 
	output wire [7:0] seven_segment_3,
	inout PS2CLK,
	inout PS2DATA);
	//
	assign reset_n = in_button[0];
	//
	// modules
	//
	nios2ps2reader_qsys nios2ps2reader_qsys(
		.clk_clk(in_clk),                                   //                                clk.clk
		.reset_reset_n(reset_n),                             //                              reset.reset_n
		.ps2reader_0_conduit_end_io_ps2clk_export(PS2CLK),  //  ps2reader_0_conduit_end_io_ps2clk.export
		.ps2reader_0_conduit_end_io_ps2data_export(PS2DATA),  // ps2reader_0_conduit_end_io_ps2data.export
		.pio_0_export({seven_segment_1, seven_segment_0})                               //                              pio_0.export
	);
	//
	//	terminate unused LEDs
	//
	assign out_led[0] = ~PS2CLK;
	assign out_led[1] = ~PS2DATA;
	assign out_led[9:2] = 8'b0000_0000;
	assign seven_segment_2 = 8'b1111_1111;
	assign seven_segment_3 = 8'b1111_1111;
	//
endmodule

PS/2クロック(PS2CLK)はピンP22に、PS/2データ(PS2DATA)はピンP21に接続する。
あとはいつもと同じだ。
最後に、Nios IIのソースコード
Nios IIでps2readerの状態レジスタをpollingして、PS/2からの読み出しデータが準備できたらその値を読み込み、7セグLED用のデータに変換して、PIOに出力する。

#include "system.h"
#include "io.h"
int main()
{ 
	int PS2State, PS2Data;
	unsigned short seven_seg_out;
	unsigned char out_MSB, out_LSB;
	IOWR_16DIRECT(PIO_0_BASE, 0, 0xffff);

  /* Event loop never exits. */
  while (1)
  {
	  PS2State = IORD_8DIRECT(PS2READER_0_BASE, 0);
	  if (PS2State == 1)
	  {
		  PS2Data = IORD_8DIRECT(PS2READER_0_BASE, 1);
		  IOWR_8DIRECT(PS2READER_0_BASE, 0, 0x00);
		  if (PS2Data != 0xf0)
		  {
			  alt_printf("%x ", PS2Data);
			  switch(PS2Data / 16)
			  {
				  case 0x0:
					  out_MSB = 0xc0;
					  break;
				  case 0x1:
					  out_MSB = 0xf9;
					  break;
				  case 0x2:
					  out_MSB = 0xa4;
					  break;
				  case 0x3:
					  out_MSB = 0xb0;
					  break;
				  case 0x4:
					  out_MSB = 0x99;
					  break;
				  case 0x5:
					  out_MSB = 0x92;
					  break;
				  case 0x6:
					  out_MSB = 0x82;
					  break;
				  case 0x7:
					  out_MSB = 0xd8;
					  break;
				  case 0x8:
					  out_MSB = 0x80;
					  break;
				  case 0x9:
					  out_MSB = 0x90;
					  break;
				  case 0xa:
					  out_MSB = 0x88;
					  break;
				  case 0xb:
					  out_MSB = 0x83;
					  break;
				  case 0xc:
					  out_MSB = 0xc6;
					  break;
				  case 0xd:
					  out_MSB = 0xa1;
					  break;
				  case 0xe:
					  out_MSB = 0x86;
					  break;
				  case 0xf:
					  out_MSB = 0x8e;
					  break;
				  default:
					  out_MSB = 0xff;
					  break;
			  }
			  switch(PS2Data % 16)
			  {
				  case 0x0:
					  out_LSB = 0xc0;
					  break;
				  case 0x1:
					  out_LSB = 0xf9;
					  break;
				  case 0x2:
					  out_LSB = 0xa4;
					  break;
				  case 0x3:
					  out_LSB = 0xb0;
					  break;
				  case 0x4:
					  out_LSB = 0x99;
					  break;
				  case 0x5:
					  out_LSB = 0x92;
					  break;
				  case 0x6:
					  out_LSB = 0x82;
					  break;
				  case 0x7:
					  out_LSB = 0xd8;
					  break;
				  case 0x8:
					  out_LSB = 0x80;
					  break;
				  case 0x9:
					  out_LSB = 0x90;
					  break;
				  case 0xa:
					  out_LSB = 0x88;
					  break;
				  case 0xb:
					  out_LSB = 0x83;
					  break;
				  case 0xc:
					  out_LSB = 0xc6;
					  break;
				  case 0xd:
					  out_LSB = 0xa1;
					  break;
				  case 0xe:
					  out_LSB = 0x86;
					  break;
				  case 0xf:
					  out_LSB = 0x8e;
					  break;
				  default:
					  out_LSB = 0xff;
					  break;
			  }
			  seven_seg_out = ((unsigned short) out_MSB) * 256 + ((unsigned short) out_LSB);
			  IOWR_16DIRECT(PIO_0_BASE, 0, seven_seg_out);
		  }
	  }
  }
  return 0;
}

今回大きくハマったのは、PIOへの出力。
Niosコンソールにはキーボードのコードがちゃんと出力されるのに、7セグLEDには出ない。

  • (int)を16bitだと思い込んでいた、16bitは(short)
  • signedであることを忘れていた、seven_seg_out、out_MSB、out_LSBともunsignedにする必要がある

などなど。
型定義を厳密に書かなくてはいけないのは、組み込みの基本だ。
まずいまずい。