第二種電気工事士の資格に挑戦してみる その1

きっかけは以下の記事です。

https://qiita.com/rukihena/items/a30f07f93ca1718dff8e

 

2003年に新築した一戸建ても色々がたが来て、コンセントなど自分でできるものは取り換えたい!と思い立ちました。

 

まずは引き返せないように申し込みます。インターネット申し込みだと9300円かかりました。

https://uketsuke.shiken.or.jp/mohshi/FIC1010.do

 

工具は自分で用意する必要があるため以下を購入しました。11595円かかりました。

https://www.amazon.co.jp/dp/B079JFJHSM/

 

部材セットはDVDつきの第二種電気工事士技能試験「準備万端試験対策セット」をメルカリで5000円で購入。2019年の対策セットですが、2020年も試験範囲が同じなので問題ないと思っています。

 

筆記試験と技能試験があるのですが、まずは工具が届くまでは、技能試験の動画を見てイメージトレーニングをしています。HOZAN最高!

電工試験の虎_ホーザン - YouTube

 

動画を見て、合格クリップ(P-926 629円)、合格マルチツール(DK-200 667円)、プレートはずし器(WV-8400 420円)などを追加購入しました。足りない部材は都度ホームセンターなどで調達予定。

RETRONFREAK5でHello, World.

Android NDKをつかってRETRONFREAK5でHello, Worldしてみます。

circuit-board.de

まずはAndroid NDK(android-ndk-r10e-windows-x86_64.zip)をダウンロードします。

developer.android.com

サンプルプログラムを書き換えます。

>cd \android-ndk-r10e\samples\hello-jni
>..\..\ndk-build

RETRONFREAK5に転送して実行します。

>adb push \android-ndk-r10e\samples\hello-jni\libs\armeabi\hello-jni /hello-jni
>adb shell
#busybox chmod +x /hello-jni
#/hello-jni
Hello, World.

Application.mk

APP_ABI := armeabi

Android.mk

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

#include $(BUILD_SHARED_LIBRARY)
include $(BUILD_EXECUTABLE)

hello-jni.c

/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
#include <string.h>
#include <jni.h>

/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java
 */

jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
//#if defined(__arm__)
//  #if defined(__ARM_ARCH_7A__)
//    #if defined(__ARM_NEON__)
//      #if defined(__ARM_PCS_VFP)
//        #define ABI "armeabi-v7a/NEON (hard-float)"
//      #else
//        #define ABI "armeabi-v7a/NEON"
//      #endif
//    #else
//      #if defined(__ARM_PCS_VFP)
//        #define ABI "armeabi-v7a (hard-float)"
//      #else
//        #define ABI "armeabi-v7a"
//      #endif
//    #endifexit
//  #else
   #define ABI "armeabi"
//  #endif
//#elif defined(__i386__)
//   #define ABI "x86"
//#elif defined(__x86_64__)
//   #define ABI "x86_64"
//#elif defined(__mips64)  /* mips64el-* toolchain defines __mips__ too */
//   #define ABI "mips64"
//#elif defined(__mips__)
//   #define ABI "mips"
//#elif defined(__aarch64__)
//   #define ABI "arm64-v8a"
//#else
//   #define ABI "unknown"
//#endif

    return (*env)->NewStringUTF(env, "Hello from JNI !  Compiled with ABI " ABI ".");
}

int main(void)
{
    printf("Hello, World.\n");
    return 0;
}

RETRONFREAK5のSERIAL(DNA)を取得します。

/*
 * RETROFREAK GETDNA
 */

#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>

#define RKNAND_SYS_STORGAE_DATA_LEN 512
#define SN_SECTOR_OP_TAG            0x41444E53 // SNDA
#define RKNAND_GET_SN_SECTOR       _IOW('d', 3, unsigned int)

typedef struct tagRKNAND_SYS_STORGAE
{
    unsigned long tag;
    unsigned long len;
    unsigned char data[RKNAND_SYS_STORGAE_DATA_LEN];
}RKNAND_SYS_STORGAE;

int main(void)
{
    int i;
    RKNAND_SYS_STORGAE sysData;
    for (i=0; i<512; i++) sysData.data[i]=0xff;
    int sys_fd = open("/dev/rknand_sys_storage",O_RDWR,0);
    if(sys_fd < 0){
        printf("rknand_sys_storage open fail\n");
        return -1;
    }
    //sn
    sysData.tag = SN_SECTOR_OP_TAG;
    sysData.len = RKNAND_SYS_STORGAE_DATA_LEN;
    int ret = ioctl(sys_fd, RKNAND_GET_SN_SECTOR, &sysData);
    if(ret) {
        printf("get sn fail\n");
        return -1;
    }
    for (i=480; i<496; i++) printf("%02x", sysData.data[i]);
    printf("\n");

    return 0;
}

RETRON5をRETROFREAKにする

RETRON5をCFWでRETROFREAKにしてみます。

circuit-board.de

上記CFW(RETRONFREAK5)で本体をアップデートします。コントローラケーブルをPCにつなぐとADB接続でrootが有効になります。

カートリッジを読み込むと/mnt/ramに元のバイナリデータが生成されます。

>adb pull /mnt/ram
>cd ram
>dir
dump.NES

 

カセットビジョンで遊ぼう会(ヨコハマ)

エポック社の電子ゲーム、ゲームポケコンカセットビジョンスーパーカセットビジョンなどで遊ぶイベントです。

MC6800でHello, World

Absolute assembler for MC6800/MC6801を使ってMC-10で、MC6847を表示するプログラムを開発して行きます。

f:id:tanam:20191125123044p:plain

VRAM($4000-$57FF)、ROM($E000-$FFFF)の想定で書いていきます。

	ORG	$E000
STACK	EQU	$5000
VRAM	EQU	$4000
START	LDS	#STACK
	LDX	#VRAM
	STX	$82
	LDX	#HELLO
LOOP	LDAA	0,X
	BEQ	QUIT
	INX
	STX	$80
	LDX	$82
	STAA	0,X
	INX
	STX	$82
	LDX	$80
	BRA	LOOP
QUIT	BRA	QUIT
HELLO	FCC	'HELLO,WORLD'
	FCB	$00
	ORG	$FFFE
	FDB	START
	END

TVボーイで動かす場合は、VRAM($1000-$17FF)、ROM($F000-$FFFF)とします。

カワサキ新年会(Z80)

ファミコン以外のマイナーゲーム機、SG-1000、PV-1000、PV-2000、RX-78、M5、MSXPC-6001、ZXスペクトラムなどのZ80機種で遊ぶイベントです。

ハッシュタグ(2020/1/19)

NimotsuKun for .NET Core 3.0

C#で書いてみます。

>dotnet run
########
# .. p #
# oo   #
#      #
########
a:left s:right w:up z:down. command?

Program.cs

using System;

class Program
{
    //#壁 _空間 .ゴール oブロック p人
    const string gStageData =
        "########\n" +
        "# .. p #\n" +
        "# oo   #\n" +
        "#      #\n" +
        "########\0";

    const int gStageWidth = 8;
    const int gStageHeight = 5;

    enum OBJ
    {
        OBJ_SPACE,
        OBJ_WALL,
        OBJ_GOAL,
        OBJ_BLOCK,
        OBJ_BLOCK_ON_GOAL,
        OBJ_MAN,
        OBJ_MAN_ON_GOAL,

        OBJ_UNKNOWN,
    };

    static void Main(string[] args)
    {
        string input;
        OBJ[] state = new OBJ[gStageWidth * gStageHeight]; /* 状態配列確保 */

        initialize(state, gStageWidth, gStageData); /* ステージ初期化 */
        /* メインループ */
        while (true)
        {
            /* まず描画 */
            draw(state, gStageWidth, gStageHeight);
            /* クリアチェック */
            if (checkClear(state, gStageWidth, gStageHeight))
            {
                break; /* クリアチェック */
            }
            /* 入力取得 */
            Console.Write("a:left s:right w:up z:down. command?"); /* 操作説明 */
            input=Console.ReadLine();
            Console.Write("\n");
            /* 更新 */
            update(state, input[0], gStageWidth, gStageHeight);
        }
        /* 祝いのメッセージ */
        Console.WriteLine("Congratulation's! you won.");

        return;
    }

    /* ---------------------以下関数定義------------------------------------------ */

    static void initialize(OBJ[] state, int width, string stageData)
    {
        int d = 0; /* 読み込みポインタ */
        int x = 0;
        int y = 0;
        while (stageData[d] != '\0')
        { /* NULL文字でない間 */
            OBJ t; /* 特に意味はないが使う回数が多い変数に私は良くtを使う。temporaryの略。たぶんよくない習慣だが、無駄に長い名前にして読みにくいのも困り物だろう。 */
            switch (stageData[d])
            {
                case '#': t = OBJ.OBJ_WALL; break;
                case ' ': t = OBJ.OBJ_SPACE; break;
                case 'o': t = OBJ.OBJ_BLOCK; break;
                case 'O': t = OBJ.OBJ_BLOCK_ON_GOAL; break;
                case '.': t = OBJ.OBJ_GOAL; break;
                case 'p': t = OBJ.OBJ_MAN; break;
                case 'P': t = OBJ.OBJ_MAN_ON_GOAL; break;
                case '\n': x = 0; ++y; t = OBJ.OBJ_UNKNOWN; break; /* 改行処理 */
                default: t = OBJ.OBJ_UNKNOWN; break;
            }
            ++d;
            if (t != OBJ.OBJ_UNKNOWN)
            { /* 知らない文字なら無視するのでこのif文がある */
                state[y * width + x] = t; /* 書き込み */
                ++x;
            }
        }
    }

    static void draw(OBJ[] state, int width, int height)
    {
        int x, y, t;
        string font = " #.oOpP"; /* Object列挙の順 */
        for (y = 0; y < height; ++y)
        {
            for (x = 0; x < width; ++x)
            {
                OBJ o = state[y * width + x];
                switch (o)
                {
                    case OBJ.OBJ_SPACE: t = 0; break;
                    case OBJ.OBJ_WALL: t = 1; break;
                    case OBJ.OBJ_GOAL: t = 2; break;
                    case OBJ.OBJ_BLOCK: t = 3; break;
                    case OBJ.OBJ_BLOCK_ON_GOAL: t = 4; break;
                    case OBJ.OBJ_MAN_ON_GOAL: t = 5; break;
                    case OBJ.OBJ_MAN: t = 6; break;
                    default: t = 0; break;
                }
                Console.Write(font[t]);
            }
            Console.Write("\n");
        }
    }

    /* 第一引数はほかの関数ではstateとしているが、あまりに頻繁に使うので
    短いsで済ませている。w,hもそれぞれwidth,heightである。 */
    static void update(OBJ[] s, char input, int w, int h)
    {
        /* 移動差分に変換(dはdifferenceでもdeltaでもお好きな方の略だと思って欲しい) */
        int dx = 0;
        int dy = 0;
        int i = -1;
        int x, y, tx, ty, p, tp, tx2, ty2, tp2;
        switch (input)
        {
            case 'a': dx = -1; break;
            case 's': dx = 1; break;
            case 'w': dy = -1; break;
            case 'z': dy = 1; break;
        }
        /* 人座標を検索 */
        for (i = 0; i < w * h; ++i)
        {
            if (s[i] == OBJ.OBJ_MAN || s[i] == OBJ.OBJ_MAN_ON_GOAL)
            {
                break;
            }
        }
        x = i % w; /* xは幅で割ったあまり */
        y = i / w; /* yは幅で割った商 */

        /* 移動後座標(tに意味はない。ごめんなさい) */
        tx = x + dx;
        ty = y + dy;
        /* 座標の最大最小チェック。外れていれば不許可 */
        if (tx < 0 || ty < 0 || tx >= w || ty >= h)
        {
            return;
        }
        /* A.その方向が空白またはゴール。人が移動。 */
        p = y * w + x; /* 人位置 */
        tp = ty * w + tx; /* ターゲット位置(TargetPosition) */
        if (s[tp] == OBJ.OBJ_SPACE || s[tp] == OBJ.OBJ_GOAL)
        {
            s[tp] = (s[tp] == OBJ.OBJ_GOAL) ? OBJ.OBJ_MAN_ON_GOAL : OBJ.OBJ_MAN; /* ゴールならゴール上の人に */
            s[p] = (s[p] == OBJ.OBJ_MAN_ON_GOAL) ? OBJ.OBJ_GOAL : OBJ.OBJ_SPACE; /* もともとゴール上ならゴールに */
                                                                                 /* B.その方向が箱。その方向の次のマスが空白またはゴールであれば移動。 */
        }
        else if (s[tp] == OBJ.OBJ_BLOCK || s[tp] == OBJ.OBJ_BLOCK_ON_GOAL)
        {
            /* 2マス先が範囲内かチェック */
            tx2 = tx + dx;
            ty2 = ty + dy;
            if (tx2 < 0 || ty2 < 0 || tx2 >= w || ty2 >= h)
            { /* 押せない */
                return;
            }

            tp2 = (ty + dy) * w + (tx + dx); /* 2マス先 */
            if (s[tp2] == OBJ.OBJ_SPACE || s[tp2] == OBJ.OBJ_GOAL)
            {
                /* 順次入れ替え */
                s[tp2] = (s[tp2] == OBJ.OBJ_GOAL) ? OBJ.OBJ_BLOCK_ON_GOAL : OBJ.OBJ_BLOCK;
                s[tp] = (s[tp] == OBJ.OBJ_BLOCK_ON_GOAL) ? OBJ.OBJ_MAN_ON_GOAL : OBJ.OBJ_MAN;
                s[p] = (s[p] == OBJ.OBJ_MAN_ON_GOAL) ? OBJ.OBJ_GOAL : OBJ.OBJ_SPACE;
            }
        }
    }

    /* ブロックのみがなければクリアしている。 */
    static bool checkClear(OBJ[] s, int width, int height)
    {
        int i;
        for (i = 0; i < width * height; ++i)
        {
            if (s[i] == OBJ.OBJ_BLOCK)
            {
                return false;
            }
        }
        return true;
    }
}