C言語のポインタとメモリ空間2

### メモリの節約
long型は8つのアドレス空間を取るが、ポインタは4つ分のアドレス空間しか取らないため、アドレス空間の節約になる
アドレス(&a)を渡すことを参照渡しという

void f(long *pa){
	*pa += 100;
	printf("%ld\n", *pa);
}


int main(void){

	long a = 1000;
	f(&a);
	return 0;
}

配列でアドレス空間が巨大な場合などは有効

void swap(int *pa, int *pb){
	int tmp;
	tmp = *pa;
	*pa = *pb;
	*pb = tmp; 
}

int main(void){

	int a = 5;
	int b = 10;
	swap(&a, &b);
	printf("a:%d, b:%d\n", a, b);
	return 0;
}

C言語のポインタとメモリ空間1

ポインタとはメモリのアドレスを使って操作をすること
&: アドレス演算子
*: アドレスを示す(間接演算子)
宣言時も*を使う

int main(void){
	int a;
	a = 10;

	int *pa; // *でポインタの宣言
	pa = &a; // &aでaのアドレスを入れる
	printf("%d\n", *pa); //paに入っているアドレスの値を呼び出す

	return 0;
}

$ ./dev
10

なんだこれは? 要は「*」でポインタを宣言した後に、「&」でアドレスを入れて、「*」でアドレスを呼び出してるってことか。
char型でも同じようchar型のポインタを割り当ててできるが、どう活用するかようわからん。

int main(void){
	char s[] = "hello";

	char *ps;
	ps = &s[3];
	printf("%c\n", *ps);

	return 0;
}

C言語基礎2

### 関数
関数: 複数の処理
返り値の型 関数名(引数){
処理;
return
}
C言語は、最初にmain()関数を実行する
main内で使用する関数は、mainよりも上部に書く
プロトタイプ宣言を最上部に記述する

float getMax(float a, float b){
	if(a >= b){
		return a;
	} else {
		return b;
	}
}
void sayHi(void){
	printf("Hi\n");
}
int main(void){
	float result;
	result = getMax(2.3, 5.2);
	printf("%f\n", result);

	sayHi();
	return 0;
}

引数がない場合はvoidをつける

### 三項演算子
返り値 = (条件) ? A : B;

float getMax(float a, float b){
	return (a >= b) ? a : b;
}

### ローカル変数とグローバル変数
※グローバル変数は非推奨

int a = 0;

void f(void){
	a++;
	printf("a:%d\n", a);
}


int main(void){
	f();
	printf("[main]a:%d\n", a);
	return 0;
}

### static
型指定の前に、staticとすると、静的変数となり、値を保持する

void f(void){
	static int a = 0;
	a++;
	printf("a:%d\n", a);
}


int main(void){
	f();
	f();
	f();
	return 0;
}

$ ./dev
a:1
a:2
a:3

### 変数
領域を確保する
なお、variables[]={a,b,c} と書くことができる

int main(void){
        // int sales[] = {200, 405, 302};
	int sales[3];
	sales[0] = 200;
	sales[1] = 400;
	sales[2] = 300;

	printf("%d\n", sales[1]);

	return 0;
}

### 文字列
char型の配列、終端は「\0」
char s[] = {‘a’,’b’,’c’,’\0′};
char s[] = “abc”;

int main(void){
	char s[] = "abc";

	printf("%c\n", s[1]);

	return 0;
}

配列の書き方が原始的というか、他の言語でも仕組み上は同じと考えると、面白いです。

C言語基礎1 

### 変数
変数の指定は、intは%d, floatは%f, charは%cと決まっている。

#include <stdio.h>

/*
int -> %d, 
float -> %f, 
char -> %c
*/

int main(void){

	int x = 10;
	float y = 5.2;
	char c = 'A';

	printf("x = %d, y = %f, c = %c\n", x, y, c);
	return 0;
}

$ ./dev
x = 10, y = 5.200000, c = A

### 演算
x++ は+1、x–は-1のこと

int main(void){

	int x = 10 % 3;
	x += 5;
	x++;

	printf("x = %d\n", x);
	return 0;
}

$ ./dev
x = 7

### if
一致の場合は”==”、不一致は”!=”

int main(void){

	int score = 50;
	if(score >= 60){
		printf("nice score\n");
	} else {
		printf("come on\n");
	}
	return 0;
}

$ ./dev
come on

### switch

int main(void){

	int rank = 2;

	switch(rank){
		case 1:
			printf("Gold!\n");
			break;
		case 2:
			printf("Silver!\n");
			break;
		case 3:
			printf("Bronze!\n");
			break;
		default:
			printf("no medal!\n");
			break;
	}
	return 0;
}

### while

int main(void){

	int m = 0;
	while(m < 10){
		printf("m: %d\n", m);
		m++;
	}
	
	return 0;
}

### for

int main(void){

	int m;
	for(m = 0; m < 10; m++){
		if (m == 3){
			continue;
		}
		if (m == 8){
			break;
		}
		printf("m: %d\n", m);
	}

	return 0;
}

$ ./dev
m: 0
m: 1
m: 2
m: 4
m: 5
m: 6
m: 7

改めてC言語を勉強するとなると、C言語が偉大なので、慣れるまで構えてしまいます。

ubuntuでcを実行する

$ cat /etc/os-release
NAME=”Ubuntu”
VERSION=”18.04.4 LTS (Bionic Beaver)”

gccはc言語用のコンパイラ
GNU Compiler Collectionの略

$ gcc –version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ sudo apt-get install build-essential

#include <stdio.h>

int main(void){
	printf("hello world!\n");
	return 0;
}

// コンパイル時に-oオプションを使うことで、実行形式ファイルの名前を指定
$ gcc -o hello hello.c
$ ls
hello hello.c
// ./実行形式ファイルパスで実行
$ ./hello
hello world!

ArduinoとRaspberry Piの違い

### Arduinoとは
AVRマイコン、入出力ポートを備えた基板
C言語風のArduino言語によってコンパイル、デバック等を行う
Arduinoを動かすプログラムをSketch(拡張子は.ino)といい、統合環境はArduino IDE
OSがインストールされていないので、プログラムを送信する必要がある
基本はArduino Uno

Github: Arduino
機能: 温度センサー、気圧センサー、赤外線センサーなどの様々なセンサーをArduinoに接続することで、その値を使って処理可

### Raspberry Piとは
OSが搭載されている
SDカードから、Raspberry Pi専用のLinuxを起動でき、そこからプログラミングができる
Raspberry Pi用のカメラも発売されている
主にPythonやbashでプログラムを書く
無線通信が出来る

### ArduinoとRaspberry Piの違い
Arduinoは、組み込みや電子回路を学びたい人向け
Raspberry Piはソフトウェアを組み合わせたい人向け

両方とも実際にやってみないとわからなそうやな。

RAMの仕組み

### SRAM
フリップフロップを使ったメモリで、SRAMと言われる。消費電力が少なく、動作速度が早い
DRAMと比べて1セルあたりの部品点数が多いため集積度を上げにくい
CPU間近にSRAMに記憶する

### DRAM
大量データの記憶にはDRAMが使用される
コンデンサに蓄えた電荷量によって1ビットを記憶する
1個のコンデンサと1個のMOSFET AD=HにしてQをオンにすると、コンデンサ電圧がデータ線Dに現れるので、電圧H、Lで判定できる
構造、動作原理がSRAMに比較して単純でセル面積も小さいため、大容量メモリに適している

EPROMとflip-flopの構造的な違いは理解しておく必要がありそうだ。

### 半導体の設計
半導体の機能目的を決定する「システム設計」、これを電子回路で実現するための「ロジック設計」、さらに実際にパーツを並べて詳細な回路を検討・設計する「回路設計」、ICチップの中で回路の配置を決定する「レイアウト設計」

集積回路設計

集積回路設計は、主にシリコンを使った半導体上に、トランジスタ、抵抗器、キャパシタといった部品を配置し、それらを金属の配線で接続する。シリコン基板は電導性があるため、個々の部品の絶縁を確保する方法(いわゆる素子分離)が必要とされる。集積回路の素子は一般の部品より非常に小さいため、トランジスタの電力消費、配線抵抗、配線における電流密度といったことに注意を払う必要がある。金属配線におけるエレクトロマイグレーションや極小素子の放電による破損なども考慮される。回路の物理配置も重要であり、性能やノイズの影響、発熱分布、ピン配置といったことと密接に関連する。
半導体製造工程の「前工程」と呼ばれる半導体ウェーハ処理工程では、シリコンウェーハ表面上にトランジスタなどを含む電子回路を高集積で形成
成膜、 パターン転写、エッチング
半導体製造工程の「後工程」と呼ばれる組立工程では、ウェーハから半導体を切り出し、所定の位置に固定・封入して検査

RAMの製造メーカー
Micron

こりゃ凄い世界や。

ROMの電子回路の仕組み

### マスクROM
メモリセルの内部回路の開放と短絡によって1, 0を記憶する
半導体製造工程には写真の感光技術が利用されるが、基板を覆うマスクパターンによってデータが記録される
データ線ADとデータ線Dが短絡しており、AD=HとなるとD=Hとなる
アドレス線を開放状態にすると、AD=HとしてもD=Lのままである H, Lに0と1を割り当てて、1ビットを記憶することができる
バイポーラトランジスタを使ったマスクROMはこの原理で動作させてることができる
実用的には消費電力の少ないMOSFETを半導体スイッチとして用いている
マスクROMはIC製造段階で情報を書き込むのでデータを変更することができない

### PROM
一度だけ書き込み可能なROMをPROMという
ヒーズをトランジスタのエミッタ端子とデータ線の間に設けて、これを溶断するかどうかによってH、Lを記憶する
PROM出荷時には全ヒューズが繋がっている
セルにLを記憶するには、電源電圧Vccを高く設定し、ヒューズが溶断されるとLが記憶される
ヒューズ以外にもダイオードを挿入し、pn接合を破壊・短絡してH, Lを表す方法もある

### EPROM
データの正気と再書き込み可能なROMをEPROMという
データの消去に紫外線を使うUV-EPROMと電圧を使うEEPROMがある
装置固有の設定データや利用者情報などの記憶、書き換え頻度の少ない用途に適している

– 書き込み方法
p型半導体基板上にn型半導体を二つ設け、これに電極ドレイン(D)とソース(S)をつける
更にドレイン・ソース間に絶縁層を設け、その上にゲート電極(G)をつける
n型半導体は自由電子が含まれた物質で自由電子の流れが電流
p型半導体は自由電子を含んでいない
ゲートに電圧を加えない状態では電流は流れない(nMOSがオフ)
ゲートに電圧を加えるとゲート、ソース間はコンデンサとして働き、正の電荷がゲート電極に蓄えられる
-> nチャンネルを作り、半導体スイッチとなる Vgs > Vthでオン、Vgs < Vthでオフ FGの帯電量によってMOSFETのオンオフを決定でき、ROMとして1ビットを記憶させることができる 一度入り込んだ負電荷は電源を切っても消えないので、半永久的にこの状態を保持できる - データ消去 UV-FPROMは紫外線をFGゲートに照射させることで内部電子のエネルギーを増大させ、FGゲートから放出させる このため、IC上部には紫外線照射窓がある EEPROMは電圧によってFGゲートの電子を放出させる FGゲートの帯電動作と逆 ゲート電圧を0とし、ドレイン電圧を高く設定するとFGゲートの電子がドレイン側に逃げ出して0となる EEPROMは電圧制御によって1ビット単位で行うことができるが、セルにMOSFETが追加されるため面積が大きくなり大容量化が難しくなる ### フラッシュメモリ メモリセルを幾つかの集合に分割し、消去をブロック単位で行うようにした セルの消去用トランジスタをなくすことでセル面積を抑え、大容量化を図っている 電源を切ってもデータが保持できるので応用は急速に広がっている マザーボードのBIOS、スマホのストレージはフラッシュメモリー UBS, SSDなどもNAND型のフラッシュメモリー フラッシュメモリはTranscend(台湾)、Silicon-Power(ドイツ)、ELECOM、I-O DATA、SanDisk、BUFFALO、GREEN HOUSEなどが生産 EPROMの仕組みは、p型半導体と、s,dのn型半導体に挟まれた絶縁体のゲートでできてるのね。 1ビットでこの仕組みが必要なのに、500GBのSSDって、どれだけpnとデータ線、アドレス線をどうやって少量化して詰め込んでるんやろうか、全く想像が付かない。CPUもそうだけど。 ICメモリの仕組みがわかったところで、アプリケーションの品質には直接は影響はないけど、興味深いところではある。

ICメモリ

記憶装置には大きく分けて外部記憶装置と内部記憶装置がある

### 外部記憶装置
外部記憶装置にはハードディスク、CD、DVDなど
-> 機械的な駆動部分が存在するため読み書き速度が遅い

### 内部記憶装置
ICメモリは小型の回路部品であり、基板内部に組み込まれる為、内部記憶装置と言われる
記憶容量では劣るが、機械駆動部が少ない為高速
CPU周りの高速処理にICメモリが使われている

### ICメモリの内部構造
大量の2値情報を記憶する
IC内部の最小記憶単位をセルと良い、通常は1ビットを記憶する 
セルは平面上に配列されており、アクセスするためにアドレス(固有の識別番号)が使われている
行アドレスと列アドレスがあり、アドレス線の電圧がH(アクティブ)になり、列アドレスが入力されると、特定のデータ線が選ばれ、セルが読み書きの対象となる
読み書きの制御信号R/WがHになると、記憶データが出力され、Lになると記憶される

### ICメモリの分類
ROM: 読み込み専用、電源を切っても内容保持 R/W制御信号は取り除かれ、出力のみ
RAM: 読み込み書き込み自由、電源を切ると内容も消える R/W信号に応じて双方向通信に対応

メモリっていうと、文字データ、画像データなどを記憶しているように思っていたが、実際には0、1の2値データを持ってるだけなのね。えらい勘違いをしていたみたいだ。

A/D, D/A変換

アナログからデジタルに変換するのをanalog to digital conversionでA/D変換という
逆に、2値信号をアナログ信号に変換する作業をdigital to analog conversion, D/A変換という

#### D/A変換の原理
ほとんどの電子回路は電圧を情報として扱うので、アナログ電圧量に変換すると捉える
-> 2進数を10進数に変換し、この10進数に比例した電圧量を得ること
e.g. X=1011(2)の時、Y=11 11に比例した電圧が現れる仕掛けを用意すればD/A変換したと言える
ビット重みに比例した電流を流す仕掛けと、得られた電流から電圧変換する作業を行えば良い
-> 複数の抵抗網と演算増幅器を用いることが多い

– 演算増幅器
マイナス端子とプラス端子電位差を増幅する
重み付け抵抗あるいはラダー抵抗で1/8R, 1/4R, 1/2R, Rとすれば、ビットの大きさに比例した電流を得られる

### A/D変換器の原理
A/D変換の原理は積分型と比較型に分けられる

– 二重積分型A/D変換器
積分器、コンパレータ、クロックパルス発生器、ゲート、カウンタ、制御回路が含まれている
電圧の大きさ -> 時間の長さ -> パルスのカウント数 という変換作業によって電圧信号をデジタル化する
クロック周波数、積分期間が長いほど大きくなる
– 逐次比較型A/D変換
二分法と言われる探索手法
あらかじめ想定される電圧範囲を二分し、この閾値電圧と入力電圧を比較してデジタル変換する

nビットの2進変換をしたい場合は、nビット対応のD/A変換器を用意してn回繰り返し動作によって求めることができる

A/D, D/Aも2進数の変換をどう扱うかってことやな
世の中の複雑なアルゴリズムが全て2進数で処理されているってのは未だに信じられない