友人に頼まれて作ったのですが、一昔前の4号機と呼ばれる「北斗の拳」の物です。
実際ホールなどで使用すると違法らしいのですが、今となっては家庭で持っている好きな方なら使えるんじゃないか
と思い経過はかなりはしょって公開します。
元々スロットに関して知識がなかったので友人に台を提供していただき、まずは構造などデータ取りをしてみました。
いろいろ調べてみると左図のような構造であることはだいたい
わかってきましたので赤丸の部分に注目しメイン基板からサブ
基板に出力される信号は8bitである事も判明したので、それを
ロジアナで計り信号変化をエクセル上で表にしてみました。
結果はこちら
表にしてみると単純な物で、スタート時に役は決定されてサブ
基板に送られ、続いて停止ボタンに応じたドラムの停止信号と
全てストップ後に現在のモードなどが送信される仕組みです。
サブ基板では信号ヘッダに従い音声などの処理をして表示など
を抽選決定している様子です。
ここで設計するにあたり追加機能で画面表示にバグが出た時に
リセットできるサブ基板初期化機能(これは単純にRAMクリアと
呼ばれる台を設定状態にした時の信号を出力)と画面表示変更
機能(これは断線チェックの為にコイン投入→スタート→ドラム
停止→モード決定の信号を出力し2台以上の本機を並列接続す
れば断線や機能チェックできるように)を付けました。
まぁオマケですけどねw
さぁいよいよ設計開始です。
入力が8bitにコントロール端子が1本と表示には7セグLEDを使うのでBCDデコードICを使っても出力4本にスイッチ
入力に2本などで合計入出力端子に15本は確保したいのでPIC16F627Aを使うことにしました。
回路図はこちらに↓
パターン図はこちらに↓
さて次はソースコードですが・・・作ったのはかなり昔で今となっては何を考えて書いたのか全く覚えていないので、
そのまま載せようと思います。(あの頃の自分はどこへやら?w)
;****************************************************
; Filename: mode.asm *
; Programname: モードチェッカー *
; Version: Ver1.0.0 *
; Assembler: MPLAB Ver7.50.00 *
;****************************************************
INCLUDE"p16F627a.inc"
list p=16F627A
__CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _LVP_OFF
;******************************プログラム初期設定***************************
;ファイルレジスタの定義
COUNT EQU 0x20 ;ウェイトカウント用
COUNT1 EQU 0x21 ;ウェイトカウント用
E_ADRS EQU 0x22 ;
;RAポート割り当て
CHANG SET 4 ;チェンジモード
CLERE SET 5 ;クリアモード
CTRL SET 6 ;コントロールビット
;--------EEPROM---------
ORG H'2100'
DE H'7F',H'F6',0
DE H'7E',H'F7',H'71',H'EF',H'6B',H'F0',H'6A',H'B1',0
DE 0
DE 0
ORG H'2130'
DE H'70',H'FC',0
DE H'7A',H'FC',H'72',H'FD',H'73',H'F6',H'7A',H'FF',0
DE H'79',H'FE',H'78',H'FA',H'79',H'FD',H'77',H'F7',H'79',H'FC',H'76',H'F0',0
DE H'74',H'FE',H'71',H'E7',H'6B',H'F0',H'6A',H'B1',0
;
ORG 0 ;リセットベクタ
;
START
;ポートの初期設定
MOVLW B'00000111' ;コンパレータ不使用
MOVWF CMCON ;コンパレータI/O設定
CALL PORT_IN ;ポート入力モード
INIT MOVLW H'0F' ;7SEG初期値
MOVWF PORTA ;7SEG出力
;******************************プログラム本文***************************
;入力の読み取り
L_CHANG BTFSC PORTA,CHANG ;RA = (L)?
GOTO L_CLERE ;L_CLEREへ
CALL WAIT100 ;ノイズカットウェイト
BTFSC PORTA,CHANG ;RA = (L)?
GOTO L_CLERE ;L_CLEREへ
CALL PORT_OT ;ポート出力モード
GOTO TASK_2 ;チェンジモードへ
L_CLERE BTFSC PORTA,CLERE ;RA = (L)?
GOTO L_CTRL ;L_CTRLへ
CALL WAIT100 ;ノイズカットウェイト
BTFSC PORTA,CLERE ;RA = (L)?
GOTO L_CTRL ;L_CTRLへ
CALL PORT_OT ;ポート出力モード
GOTO TASK_1 ;クリアモードへ
L_CTRL BTFSC PORTA,CTRL ;CTRL = (L)?
GOTO L_CHANG ;L_CHANGへ
MOVF PORTB,W ;RB<7:0>データ読み込み
SUBLW H'71' ;データ照合
BTFSS STATUS,Z ;RB = (&H71)?
GOTO H_CTRL ;H_CTRLへ
GOTO TASK1 ;TASK1へ
H_CTRL BTFSS PORTA,CTRL ;CTRL = (H)?
GOTO H_CTRL ;H_CTRLへ
GOTO L_CHANG ;L_CHANGへ
;メインタスク
TASK1 BTFSS PORTA,CTRL ;CTRL = (H)?
GOTO TASK1 ;TASK1へ
TASK2 BTFSC PORTA,CTRL ;CTRL = (L)?
GOTO TASK2 ;TASK2へ
MOVF PORTB,W ;RB<7:0>データ読み込み
SUBLW H'FF' ;W - &HFF
CALL TABLE ;データテーブル読み込み
MOVWF PORTA ;7SEG出力
GOTO H_CTRL ;H_CTRLへ
;クリアモード
TASK_1 MOVLW H'00' ;EEPROMアドレスセット
MOVWF E_ADRS ;データエリアのアドレス指定
CALL DATAOUT ;データ出力へ
H_CLERE BTFSS PORTA,CLERE ;RA → (H)?
GOTO H_CLERE ;H_CLEREへ
CALL PORT_IN ;ポート入力モード
GOTO L_CHANG ;L_CHANGへ
;チェンジモード
TASK_2 CALL WAIT40
MOVLW H'30' ;EEPROMアドレスセット
MOVWF E_ADRS ;データエリアのアドレス指定
CALL DATAOUT ;データ出力へ
H_CHANG BTFSS PORTA,CHANG ;RA → (H)?
GOTO TASK_2 ;
CALL PORT_IN ;ポート入力モード
GOTO L_CHANG ;L_CHANGへ
;ポートイニシャライズ
PORT_IN BSF STATUS,RP0 ;バンク1に切り替え
MOVLW B'11110000' ;RA<0-3>出力
MOVWF TRISA ;ポートA方向(入出力)設定
MOVLW B'11111111' ;RB<0:7>入力
MOVWF TRISB ;ポートB方向(入出力)設定
MOVLW B'10000000' ;オプションレジスタの設定
MOVWF OPTION_REG ;タイマ不使用
BCF STATUS,RP0 ;バンク0に切り替え
RETURN
PORT_OT BSF STATUS,RP0 ;バンク1に切り替え
MOVLW B'10110000' ;RA<0-3><6>出力
MOVWF TRISA ;ポートA方向(入出力)設定
MOVLW B'00000000' ;RB<0:7>出力
MOVWF TRISB ;ポートB方向(入出力)設定
MOVLW B'10000000' ;オプションレジスタの設定
MOVWF OPTION_REG ;タイマ不使用
BCF STATUS,RP0 ;バンク0に切り替え
CALL INI_D ;
CALL INI_T ;
RETURN
;データポートイニシャライズ
INI_D MOVLW H'FF'
MOVWF PORTB ;(H)→RB<7:0>
RETURN
;コントロールビットイニシャライズ
INI_T BSF PORTA,CTRL ;(H)→RA
RETURN
;ウェイトシーケンス
WAIT CALL WAIT_07 ;ウェイト70us
CALL INI_T ;
CALL WAIT1_0 ;ウェイト1ms
CALL WAIT1_0 ;ウェイト1ms
CALL INI_D ;
RETURN
;データ出力シーケンス
DATAOUT CALL D_LIST ;
CALL WAIT
CALL WAIT
CALL WAIT
CALL WAIT
INCF E_ADRS,F ;
CALL D_LIST ;
CALL WAIT
CALL WAIT
CALL WAIT
CALL WAIT
INCF E_ADRS,F ;
CALL D_LIST ;
CALL WAIT
CALL WAIT
CALL WAIT
CALL WAIT
INCF E_ADRS,F ;
CALL D_LIST ;
RETURN
;データリスト出力
D_LIST CALL EE_READ ;
BTFSC STATUS,Z ;EEDATA = (00H)?
RETURN ;
MOVWF PORTB ;W → PORTB
CALL WAIT_01 ;ウェイト10us
BCF PORTA,CTRL ;CTRLクリア
CALL WAIT ;
INCF E_ADRS,F ;データアドレスのインクリメント
GOTO D_LIST ;
;EEPROM読み出し
EE_READ MOVF E_ADRS,W ;アドレスをWレジスタに
BSF STATUS,RP0 ;PAGE1へ切替え
MOVWF EEADR ;アドレスをEEADRへセット
BSF EECON1,RD ;読み出し
MOVF EEDATA,W ;Wレジスタにデータ取り出し
BCF STATUS,RP0 ;PAGE0に戻る
RETURN
;100msノイズカットウェイトサブルーチン
WAIT100 MOVLW D'50'
MOVWF COUNT1 ;1.0ms×100=100ms
LOOP100 CALL WAIT1_0
DECFSZ COUNT1, F
GOTO LOOP100
RETURN
;40msウェイトサブルーチン
WAIT40 MOVLW D'40'
MOVWF COUNT1 ;1.0ms×40=40ms
LOOP40 CALL WAIT1_0
DECFSZ COUNT1, F
GOTO LOOP40
RETURN
;1msウェイトサブルーチン
WAIT1_0 MOVLW D'249'
MOVWF COUNT ;1.0ms基準
LOOP1_0 NOP
DECFSZ COUNT, F
GOTO LOOP1_0
RETURN
;70uSウェイトサブルーチン
WAIT_07 MOVLW D'5'
MOVWF COUNT1 ;
LOOP_07 CALL WAIT_01
DECFSZ COUNT1, F
GOTO LOOP_07
RETURN
;10uSウェイトサブルーチン
WAIT_01 MOVLW D'1'
MOVWF COUNT ;
LOOP_01 NOP
NOP
DECFSZ COUNT, F
GOTO LOOP_01
RETURN
;データテーブル
TABLE ADDWF PCL,1
RETLW H'00' ;FF=[0]ストック無
RETLW H'00' ;FE=[0]ストック無
RETLW H'0F' ;FD=[F]
RETLW H'0F' ;FC=[F]
RETLW H'0F' ;FB=[F]
RETLW H'0F' ;FA=[F]
RETLW H'0F' ;F9=[F]
RETLW H'0F' ;F8=[F]
RETLW H'01' ;F7=[1]低確率
RETLW H'01' ;F6=[1]低確率
RETLW H'0F' ;F5=[F]
RETLW H'0F' ;F4=[F]
RETLW H'0F' ;F3=[F]
RETLW H'0F' ;F2=[F]
RETLW H'0F' ;F1=[F]
RETLW H'0F' ;F0=[F]
RETLW H'02' ;EF=[2]通常
RETLW H'02' ;EE=[2]通常
RETLW H'0F' ;ED=[F]
RETLW H'0F' ;EC=[F]
RETLW H'0F' ;CB=[F]
RETLW H'0F' ;EA=[F]
RETLW H'0F' ;E9=[F]
RETLW H'0F' ;E8=[F]
RETLW H'03' ;E7=[3]高確率
RETLW H'03' ;E6=[3]高確率
RETLW H'0F' ;E5=[F]
RETLW H'0F' ;E4=[F]
RETLW H'0F' ;E3=[F]
RETLW H'0F' ;E2=[F]
RETLW H'0F' ;E1=[F]
RETLW H'0F' ;E0=[F]
RETLW H'04' ;DF=[4]前兆
RETLW H'04' ;DE=[4]前兆
RETLW H'0F' ;DD=[F]
RETLW H'0F' ;DC=[F]
RETLW H'0F' ;DB=[F]
RETLW H'0F' ;DA=[F]
RETLW H'0F' ;D9=[F]
RETLW H'0F' ;D8=[F]
RETLW H'05' ;D7=[5]ボーナス(7)
RETLW H'05' ;D6=[5]ボーナス(7)
RETLW H'0F' ;D5=[F]
RETLW H'0F' ;D4=[F]
RETLW H'0F' ;D3=[F]
RETLW H'0F' ;D2=[F]
RETLW H'0F' ;D1=[F]
RETLW H'0F' ;D0=[F]
RETLW H'06' ;CF=[6]ボーナス(北斗)
RETLW H'06' ;CE=[6]ボーナス(北斗)
RETLW H'0F' ;CD=[F]
RETLW H'0F' ;CC=[F]
RETLW H'0F' ;CB=[F]
RETLW H'0F' ;CA=[F]
RETLW H'0F' ;C9=[F]
RETLW H'0F' ;C8=[F]
RETLW H'0F' ;C7=[F]ボーナス66%継続
RETLW H'0F' ;C6=[F]ボーナス66%継続
RETLW H'0F' ;C5=[F]
RETLW H'0F' ;C4=[F]
RETLW H'0F' ;C3=[F]
RETLW H'0F' ;C2=[F]
RETLW H'0F' ;C1=[F]
RETLW H'0F' ;C0=[F]
RETLW H'09' ;BF=[9]ボーナス79%継続
RETLW H'09' ;BE=[9]ボーナス79%継続
RETLW H'0F' ;BD=[F]
RETLW H'0F' ;BC=[F]
RETLW H'0F' ;BB=[F]
RETLW H'0F' ;BA=[F]
RETLW H'0F' ;B9=[F]
RETLW H'0F' ;B8=[F]
RETLW H'08' ;B7=[8]ボーナス84%継続
RETLW H'08' ;B6=[8]ボーナス84%継続
RETLW H'0F' ;B5=[F]
RETLW H'0F' ;B4=[F]
RETLW H'0F' ;B3=[F]
RETLW H'0F' ;B2=[F]
RETLW H'0F' ;B1=[F]
RETLW H'0F' ;B0=[F]
RETLW H'07' ;AF=[7]ボーナス88%継続
RETLW H'07' ;AE=[7]ボーナス88%継続
;
END
一応注釈が入っているのでわかるとは思いますが、原理は簡単です。
ポートBの入力が0x71になるのを待ちコントロールビットの立ち上がりを待ちます。
次のデータを読み取り0xFFで減算した結果をテーブルから読み出して7セグに出力するだけ
画面クリアや変更信号は予めEEPROMに書き込んであるものを読み出してタイミングに従い出力している
だけなので、かなり単純な作りです。
完成品画像↑(写真のハーネスは長さ50cmのストレートケーブルです。これも作らないと接続できません)
ここで紹介した物の全てはこちらから圧縮ファイルでダウンロードできて以下の物が含まれます。
回路図(CADLUS Circuit)
パターン図(CADLUS X)
ソースコード(テキスト)
バイナリデータ(MPLAB)
部品表(エクセル)
説明書(エクセル)
ケース加工図面(図脳RAPID14 Pro)
部品代をざっと計算すると制作費は3,000円ほどになると思いますが、一番高いのは基板です。
現在基板が30枚ほど余っておりますので1枚600円でお分けいたします。
自分で製作できない方には完成品の販売も考えておりますので、メールください。
おわりに:
「吉宗」用の物も作ったのですが、回路図等を紛失したので見つけたら掲載いたします。
|