ルーレットKA2

MC9RS08KA2マイコンを使って、ルーレットゲームを作ります。 目標は、できるだけ半田付け箇所を減らすことです。

RouletteKA2の写真

アジェンダ

ハードウェア

回路図

以下にこのアプリケーションの回路図を示します。 押しボタンの操作で8個のLEDと1個の圧電スピーカを駆動します。

R2(470Ω)は、 FLASH ROMのプログラム用12V電源がつながっている時に押しボタンを押しても、 悲惨な事故が起こらないように入れてあります。

ルーレットKA2の部品表
品名規格メーカ個数調達先
マイコンMC9RS08KA2CPCFreescale1Freescale
カーボン抵抗470Ω 1/6W-1秋月電子
カーボン抵抗1kΩ 1/6W-1秋月電子
電解コンデンサ47µF 16VSANYO1手持在庫
積層セラミック・コンデンサ0.1µF 50V-2秋月電子
赤色発光ダイオードOSDR5113AOptoSupply1秋月電子
黄色発光ダイオードOSNG5113AOptoSupply3秋月電子
緑色発光ダイオードOSYL5113AOptoSupply4秋月電子
タクト・スイッチ--1梅澤無線
ICソケット8P DIP-1秋月電子
ボタン電池ホルダCH25-2032SHOGYO1秋月電子
ボタン電池CR2032東芝1千石電商
圧電スピーカ--1梅澤無線
ピンヘッダ2×3-1秋月電子
片面ユニバーサル基板95mm×72mm-1秋月電子
丸ビス2mm×10mm-2手持在庫
6角ナット2mm-2手持在庫
スペーサ3mm×20mmマック84手持在庫
6角ナット3mm-4手持在庫

LEDには、電流制限抵抗を入れていません。 これは、MC9RS08KA2の出力電流が多くないという事実を利用しています。 下のグラフは、流れる電流に対する"H"出力ポートと"L"出力ポートの 電位差(VOH-VOL)とLEDの順方向電圧(VF)をモデル化したものです。 これら二つのグラフの交点でLEDが点灯します。

LEDに流れる電流の推定

設計では、電源電圧3Vのときに、 "H"出力ポートと"L"出力ポートで0.5Vづつ電圧降下が起き、 それによって出力電流は約5mAに制限されます。 これは、3V電源の時に限る計算です。 したがって、この回路に5V電源を与えると マイコンとLEDに大電流が流れて破壊する可能性がありますのでご注意ください。

アートワーク

このアプリケーションのプロトタイプは、 ユニバーサル基板に作ったため、 一箇所だけジャンパ線があります。 プリント基板にするときには、 ジャンパ線の配線を迂回させて片面基板に収めることができます。

BDMポートを評価ボードに取り付ける

DEMO9RS08KA2評価ボードを開発ツールとして使用するためには、 BDMピンヘッダをつけます。

BDMポートの写真

これで、ソフトウェア開発の準備は完了です。

BDMによる接続の写真

ソフトウェア

ここでは、ソフトウェアの概要を説明します。

動作

このプログラムは、 押しボタンスイッチを押すとLEDの光が走り出し、 押しボタンスイッチを放すとLEDの速度が徐々に遅くなり、 最後には停止します。 停止した位置によって、「あたり」と「はずれ」の音を出します。

このプログラムでは、押しボタンスイッチを押さずに 一定期間放置すると、LEDを消灯し、低消費電力モードに入ります。 低消費電力状態からは、押しボタンスイッチを押すと復帰します。

状態遷移

このプログラムは、状態遷移によって動作しています。

電源ONによるリセット直後、MC9RS08KA2は PROLOGUEという状態に入ります。 PROLOGUEでは、 押しボタンスイッチが押されていない状態であることを確認します。 つまり、押しボタンスイッチを押したまま電源を投入しても ルーレットは走り出しません。

押しボタンスイッチが押されていないことを確認したら、 MC9RS08KA2は、WAITという状態に入ります。 この状態では、キーボード割り込みを待ち、 押しボタンが押されたらRUNという状態に遷移します。 同時に、押しボタンが押されなかった時間を計測しており、 約5分間、押しボタンが押されない場合には、STOPという 状態に遷移します。

STOP状態では、 STOP命令により低消費電力モードに入ります。 この状態では、押しボタンスイッチが押されるのを待ちます。 押しボタンが押されたら、再び、PROLOGUE状態に 遷移します。

一方、RUN状態では、 徐々に移動速度を落としながら、LEDを移動させます。 移動速度が、ある決められた移動速度にまで低下したら、 EPILOGUE状態に遷移します。

EPILOGUE状態では、停止したLEDの位置によって、 「あたり」と「はずれ」の効果音を圧電スピーカから出します。 効果音を出し終わったら、PROLOGUE状態に遷移します。

ソースコード

MC9RS08KA2には、Cなどの高級言語が準備されていません。 このため、このアプリケーションの開発も アセンブラで行いました。 アセンブラには、アブソリュート・アセンブラを使い、 一つのファイルにすべての記述を行っています。

このプログラムの全ソースコードは、以下のようになっています。

;*******************************************************************
;*
;* RouletteKA2.asm : 
;*
;* Copyright 2006 (C) noritan.org
;* 
;*******************************************************************

; Include derivative-specific definitions
        include         'derivative.inc'
;
; export symbols
;
        xdef            _Startup
        absentry        _Startup

;**************************************************************
;*  Debug and Release Configurations.
;**************************************************************

  IFNE    MODE
;==============================================================
;=  Release Configuration.
;==============================================================
;==============================================================
;=  Initialization value for SPMSC1 register.
;=
;=  In RELEASE case, LVD cause RESET in RUN and STOP.
;==============================================================
SPMSC1_init     equ     %01010000
;                        |||||||+-- BGBE=0   (no bandgap)
;                        ||||||+--- Reserved
;                        |||||+---- LVDE=0   (LVD enabled)
;                        ||||+----- LVDSE=0  (LVD enable in STOP)
;                        |||+------ LVDRE=1  (Reset by LVD enabled)
;                        ||+------- LVDIE=0  (INT by LVD disabled)
;                        |+-------- LVDACK=1 (Clear LVDF)
;                        +--------- LVDF=0   (N/A)
;==============================================================
;=  Initialization value for SOPT register.
;=
;=  In RELEASE case, STOP instruction is enabled.
;==============================================================
SOPT_init       equ     %00100000
;                        |||||||+-- RSTPE=0  (no RESET*)
;                        ||||||+--- BKGDPE=0 (no BKGD)
;                        |||+++---- Reserved
;                        ||+------- STOPE=1  (STOP available)
;                        |+-------- COPT=0   (COP rate)
;                        +--------- COPE=0   (no COP)

stop_nop:       macro
        stop
        endm

wait_nop:       macro
        wait
        endm
  ELSE                
;==============================================================
;=  Debug Configuration.
;==============================================================
;==============================================================
;=  Initialization value for SPMSC1 register.
;=
;=  In DEBUG case, LVD cause RESET in RUN and STOP.
;==============================================================
SPMSC1_init     equ     %01011100
;                        |||||||+-- BGBE=0   (no bandgap)
;                        ||||||+--- Reserved
;                        |||||+---- LVDE=1   (LVD enabled)
;                        ||||+----- LVDSE=1  (LVD enable in STOP)
;                        |||+------ LVDRE=1  (Reset by LVD enabled)
;                        ||+------- LVDIE=0  (INT by LVD disabled)
;                        |+-------- LVDACK=1 (Clear LVDF)
;                        +--------- LVDF=0   (N/A)
;==============================================================
;  Initialization value for SOPT register.
;
;  In DEBUG case, STOP instruction and BKGD pin are enabled.
;==============================================================
SOPT_init       equ     %00100010
;                        |||||||+-- RSTPE=0  (no RESET*)
;                        ||||||+--- BKGDPE=1 (no BKGD)
;                        |||+++---- Reserved
;                        ||+------- STOPE=1  (STOP available)
;                        |+-------- COPT=0   (COP rate)
;                        +--------- COPE=0   (no COP)

stop_nop:       macro
        nop
        endm

wait_nop:       macro
        nop
        endm
  ENDIF

;==============================================================
;  Port Declaration
;==============================================================
BEEP:           equ     PTAD_PTAD3      ; Beeper is assigned to PTA5.
START:          equ     PTAD_PTAD2      ; Start is assigned to PTA2.
mBEEP:          equ     (1<<BEEP)       ; Beeper MASK.

;==============================================================
;  Flag Declaration
;==============================================================
PRESSED:        equ     0               ; PRESSED flag position.

;==============================================================
;  RTI initialization.
;  RTI period:  8msec
;
SRTISC_init:    equ     %01000001
;                        |||||+++-- RTIS=001  (8msec period)
;                        ||||+----- Reserved
;                        |||+------ RTIE=0    (no interrupt)
;                        ||+------- RTICLKS=0 (internal 1kHz)
;                        |+-------- RTIACK=1  (clear RTIF)
;                        +--------- RTIF=0    (no effect)
;
;==============================================================

;==============================================================
;  MTIM initialization
;
MTIMCLK_init:   equ     %00000101
;                        ||||++++-- PS=0101   (x32 prescale)
;                        ||++------ CLKS=00   (BUSCLK)
;                        ++-------- Reserved
;
;  MTIM clock: Freq=250kHz, Period=4usec
;
;  MTIMMOD in play:  334usec (1 / 2 * 1.497kHz)
MTIMMOD_1500:   equ     42-1     ; 1488Hz*2=2976Hz
;  MTIMMOD in epilogue: based on 250kHz
MTIMMOD_do3:    equ     239-1    ;  523Hz*2=1046Hz
MTIMMOD_so3:    equ     159-1    ;  786Hz*2=1572Hz
MTIMMOD_ra3:    equ     142-1    ;  880Hz*2=1761Hz
MTIMMOD_si3:    equ     127-1    ;  984Hz*2=1969Hz
MTIMMOD_do4:    equ     119-1    ; 1050Hz*2=2101Hz
;
;==============================================================

;==============================================================
;  Constant parameters
;==============================================================
ACCEL_PERIOD:   equ     20              ; Period of accel events.
DEBOUNCE_PERIOD:equ     80              ; Period of debounce.
BEEP_PERIOD:    equ     20              ; Period of beep.
MOVE_PERIOD:    equ     40              ; Period for max speed.
WAIT_PERIOD:    equ     146             ; Period of max waiting.
RELEASE_PERIOD: equ     6               ; Period of button release.
MAX_SPEED:      equ     255             ; Maximum speed of LED.
MIN_SPEED:      equ     13              ; Minimum speed of LED.
LED_AMOUNT:     equ     8               ; Number of LEDs.

;**************************************************************
;
; variable/data section
;
;**************************************************************
                org     TINY_RAMStart   ; TINY RAM is mainly used.
speed:          rmb     1               ; speed of LED.
speedf:         rmb     1               ; fractional part of speed.
position:       rmb     1               ; position between LEDs.
positionf:      rmb     1               ; fractional part of position.
led_index:      rmb     1               ; index for LED.
accel_count:    rmb     1               ; periodic timer for accel.
beep_count:     rmb     1               ; periodic timer for beep.
debounce_count: rmb     1               ; periodic timer for debounce.
flag:           rmb     1               ; user defined flag.
rti_count_h:    equ     speed           ; RTI event counter H.
rti_count_l:    equ     speedf          ; RTI event counter L.
sound_page:     rmb     1               ; Page for sounder.

;**************************************************************
;  Constant table section
;**************************************************************
                org     ROMStart
;==============================================================
;  fanfare
;==============================================================
                align   64
FANFARE:
                fcb     MTIMMOD_so3,60
                fcb     MTIMMOD_so3,30
                fcb     MTIMMOD_so3,30
                fcb     MTIMMOD_ra3,30
                fcb     MTIMMOD_si3,30
                fcb     MTIMMOD_do4,240
                fcb     0

;==============================================================
;  missed
;==============================================================
                align   64
MISSED:
                fcb     MTIMMOD_so3,30
                fcb     MTIMMOD_so3,30
                fcb     MTIMMOD_do3,60
                fcb     0
                
;==============================================================
;  PORTA drive pattern.
;  Tables must be in a same page.
;==============================================================
                align   64
PTAD_PATTERN:   ;       PTAD      PTADD
                fcb     %00100000,%00100001   ; 0 5-0
                fcb     %00000010,%00000011   ; 1 1-0
                fcb     %00000001,%00000011   ; 2 0-1
                fcb     %00010000,%00010010   ; 3 4-1
                fcb     %00000010,%00010010   ; 4 1-4
                fcb     %00100000,%00110000   ; 5 5-4
                fcb     %00010000,%00110000   ; 6 4-5
                fcb     %00000001,%00100001   ; 7 0-5
                
;**************************************************************
;*  Macro code definition.
;**************************************************************
;==============================================================
;=  enable_rti : 
;=    Enable the RTI interrupt.
;=    SRTISC is initialized to start RTI counter.
;=
;=  accept_rti : 
;=    Accept an RTI event.
;=    RTIACK is set to clear the RTIF
;=
;=  disable_rti
;=    Disable the RTI interrupt.
;=    Counter is stopped to reduce power.
;=
;==============================================================
enable_rti:     macro
        mov     #HIGH_6_13(SRTISC),PAGESEL
        mov     #SRTISC_init,MAP_ADDR_6(SRTISC)
        bset    SRTISC_RTIE,MAP_ADDR_6(SRTISC)
        endm

accept_rti:     macro
        mov     #HIGH_6_13(SRTISC),PAGESEL
        bset    SRTISC_RTIACK,MAP_ADDR_6(SRTISC)
        endm

disable_rti:    macro
        mov     #HIGH_6_13(SRTISC),PAGESEL
        bclr    SRTISC_RTIE,MAP_ADDR_6(SRTISC)
        endm

;==============================================================
;=  enable_kbi : 
;=    Enable the KBI interrupt.
;=    KBACK is set to clear the KBF
;=
;=  accept_kbi : 
;=    Accept an KBI event.
;=    KBACK is set to clear the KBF
;=
;=  disable_kbi
;=    Disable the KBI interrupt.
;=
;==============================================================
enable_kbi:     macro
        bset    KBISC_KBACK,KBISC
        bset    KBISC_KBIE,KBISC
        endm

accept_kbi:     macro
        bset    KBISC_KBACK,KBISC
        endm

disable_kbi:    macro
        bclr    KBISC_KBIE,KBISC
        endm

;==============================================================
;=  enable_mtim : 
;=    Enable the TOF interrupt.
;=    TRST is set to clear the TOF and MTIMCNT.
;=    TSTP is controlled for safety enabling.
;=
;=  accept_mtim : 
;=    Accept an TOF event.
;=    TOF is reset to clear the TOF.
;=
;=  disable_mtim
;=    Disable the TOF interrupt.
;=    TRST is set to reset the timer counter.
;=    TSTP is set to stop the timer counter.
;=
;==============================================================
enable_mtim:    macro
        mov     #mMTIMSC_TOIE+mMTIMSC_TRST+mMTIMSC_TSTP,MTIMSC
        bclr    MTIMSC_TSTP,MTIMSC
        endm

accept_mtim:    macro
        bclr    MTIMSC_TOF,MTIMSC
        endm

disable_mtim:   macro
        mov     #mMTIMSC_TRST+mMTIMSC_TSTP,MTIMSC
        endm

;**************************************************************
; code section
;**************************************************************
;==============================================================
;=  Genral initialization.
;=
;=  Modules KBI, RTI and MTIM are initialized and ready to be
;=  used.  
;=
;=  led_index = 0;
;=  PTAPE2 = 1;
;=  KBIPE2 = 1;
;=  MTIMCLK = MTIMCLK_init;
;==============================================================
_Startup:
        mov     #HIGH_6_13(SOPT),PAGESEL
        mov     #SOPT_init,MAP_ADDR_6(SOPT)
        mov     #SPMSC1_init,MAP_ADDR_6(SPMSC1)
        clr     led_index
        bset    KBIPE_KBIPE2,KBIPE
        mov     #HIGH_6_13(PTAPE),PAGESEL
        bset    PTAPE_PTAPE2,MAP_ADDR_6(PTAPE)
        bset    KBISC_KBIMOD,KBISC
        mov     #MTIMCLK_init,MTIMCLK

;==============================================================
;=  Initialization for PROLOGUE state
;=    KBI  -- disabled not to capture KBI.
;=    RTI  -- enabled to wait TIMEOUT event.
;=    MTIM -- disabled to reduce power.
;=
;=  put_led();
;=  disable_kbi();
;=  enable_rti();
;=  disable_mtim();
;=  rti_count = 0;
;==============================================================
prologue_init:
        jsr     put_led
        disable_kbi
        enable_rti
        disable_mtim
        clr     rti_count_h
        clr     rti_count_l
        
;==============================================================
;  PROLOGUE state
;  Confirm START button released and go to WAIT state.
;
;  for (;;) {
;    $WAIT;
;    if (RTI) {
;      if (!PTAD[START]) {
;        rtc_count = 0;
;      } else {
;        if (++rti_count >= RELEASE_PERIOD) goto wait_init;
;      }
;    }
;  }
;==============================================================
prologue_loop:
        mov     #HIGH_6_13(SIP1),PAGESEL
        wait_nop
        brclr   SIP1_RTI,MAP_ADDR_6(SIP1),prologue_loop
        accept_rti
        brset   START,PTAD,prologue_release
        clr     rti_count_l
prologue_release:
        inc     rti_count_l
        lda     rti_count_l
        cmp     #RELEASE_PERIOD
        bcs     prologue_loop

        
;==============================================================
;=  Initialization for WAIT state
;=    KBI  -- enabled to wait START button.
;=    RTI  -- enabled to wait TIMEOUT event.
;=    MTIM -- disabled to reduce power.
;=
;=  put_led();
;=  enable_kbi();
;=  enable_rti();
;=  disable_mtim();
;=  rti_count = 0;
;==============================================================
wait_init:
        jsr     put_led
        enable_kbi
        enable_rti
        disable_mtim
        clr     rti_count_h
        clr     rti_count_l
        
;==============================================================
;  WAIT state
;  Wait for a START trigger and go to RUN state.
;
;  for (;;) {
;    $WAIT;
;    if (KBI) goto run_init;
;    if (RTI) goto wait_rti;
;  }
;==============================================================
wait_loop:
        mov     #HIGH_6_13(SIP1),PAGESEL
        wait_nop
        brset   SIP1_KBI,MAP_ADDR_6(SIP1),run_init
        brclr   SIP1_RTI,MAP_ADDR_6(SIP1),wait_loop

;==============================================================
;=  Software count for RTI evnets.
;=
;=  accept_rti();
;=  if (++rti_count >= WAIT_PERIOD) goto stop_init;
;=  else goto wait_loop;
;==============================================================
        accept_rti
        inc     rti_count_l
        bne     wait_loop
        inc     rti_count_h
        lda     rti_count_h
        cmp     #WAIT_PERIOD
        bcs     wait_loop
        
;==============================================================
;=  Initialization for STOP state
;=    KBI  -- enabled to wait START button.
;=    RTI  -- disabled to reduce power.
;=    MTIM -- disabled to reduce power.
;=
;=  PTAD  = %00000000;
;=  PTADD = %00110011;
;=  enable_kbi();
;=  disable_rti();
;=  disable_mtim();
;==============================================================
stop_init:
        mov     #%00000000,PTAD
        mov     #%00110011,PTADD
        enable_kbi
        disable_rti
        disable_mtim

;==============================================================
;  STOP state
;
;  for (;;) {
;    $STOP;
;    if (KBF) goto wait_init;
;  }
;==============================================================
stop_loop:
        stop_nop
        brset   KBISC_KBF,KBISC,prologue_init
        bra     stop_loop
        
;==============================================================
;=  Initialization for RUN state.
;=    KBI  -- disabled.
;=    RTI  -- disabled.
;=    MTIM -- enabled to control all timings.
;=
;=  disable_kbi();
;=  disable_rti();
;=  enable_mtim();
;=  MTIMMOD = MTIMMOD_1500;
;=  flag.PRESSED = 1;
;=  speed = MAX_SPEED;
;==============================================================
run_init:
        disable_kbi
        disable_rti
        enable_mtim
        mov     #MTIMMOD_1500,MTIMMOD
        bset    PRESSED,flag
        mov     #MAX_SPEED,speed

;==============================================================
;=  RUN state
;==============================================================
run_loop:
;-----------------------------------------------------
;-  Wait for MTIM interrupt
;-
;-  do {
;-    $WAIT;
;-  } while (!TOF);
;-  accept_mtim();
;-----------------------------------------------------
run_wait_2:
        wait_nop
        brclr   MTIMSC_TOF,MTIMSC,run_wait_2
        accept_mtim

;-----------------------------------------------------
;-  Beep enabler
;-
;-  if (beep_count != 0) {
;-    PTAD.BEEP = 1;
;-    beep_count--;
;-  }
;-----------------------------------------------------
        lda     beep_count
        beq     beep_enabler_done
        bset    BEEP,PTAD
        dec     beep_count
beep_enabler_done:

;-----------------------------------------------------
;-  Speed updater
;-
;-  if (--accel_count == 0) {
;-    if (!flag.PRESSED) {
;-      speed -= speed >> 8;
;-    }
;-    accel_count = ACCEL_PERIOD;
;-  }
;-----------------------------------------------------
        dec     accel_count
        bne     speed_updater_done
        brset   PRESSED,flag,speed_updater_reschedule
        lda     speedf
        sub     speed
        sta     speedf
        bcc     speed_updater_reschedule
        dec     speed
speed_updater_reschedule:
        mov     #ACCEL_PERIOD,accel_count
speed_updater_done:

;-----------------------------------------------------
;-  Key handler
;-
;-  if (flag.PRESSED) {
;-    if (!PTAD[START]) {  // PUSH detected.
;-      debounce_count = DEBOUNCE_PERIOD;
;-    } else if (--debounce_count == 0) {
;-      flag.PRESSED = 0;
;-    }
;-  }
;-----------------------------------------------------
        brclr   PRESSED,flag,key_handler_done
        brset   START,PTAD,key_handler_release
key_handler_push:
        mov     #DEBOUNCE_PERIOD,debounce_count
        bra     key_handler_done
key_handler_release:
        dec     debounce_count
        bne     key_handler_done
        bclr    PRESSED,flag                
key_handler_done:        

;-----------------------------------------------------
;-  Wait for MTIM interrupt
;-
;-  do {
;-    $WAIT;
;-  } while (!TOF);
;-  accept_mtim();
;-----------------------------------------------------
run_wait_1:
        wait_nop
        brclr   MTIMSC_TOF,MTIMSC,run_wait_1
        accept_mtim
        
;-----------------------------------------------------
;-  Beep disabler
;-
;-  PTAD.BEEP = 0;
;-----------------------------------------------------
        bclr    BEEP,PTAD
        
;-----------------------------------------------------
;-  Position updater
;-
;-  position += speed;
;-  if (position >= MOVE_PERIOD) {
;-    position -= MOVE_PERIOD;
;-    beep_count = BEEP_PERIOD;
;-    led_index = (led_index + 1) % LED_AMOUNT;
;-    put_led();
;-  }
;-----------------------------------------------------
        lda     positionf
        add     speed;
        sta     positionf
        bcc     position_updater_done
        inc     position
        lda     position
        sub     #MOVE_PERIOD
        bcs     position_updater_done
        sta     position
        mov     #BEEP_PERIOD,beep_count
        inc     led_index
        lda     led_index
        sub     #LED_AMOUNT
        bcs     position_updater_putled
        sta     led_index
position_updater_putled:
        bsr     put_led
position_updater_done:

;-----------------------------------------------------
;-  Quit loop control
;-
;-  if (speed < min_speed) {
;-    $QUIT_LOOP;
;-  }
;-----------------------------------------------------
        lda     speed
        cmp     #MIN_SPEED
        bcs     epilogue_init
        bra     run_loop
        
;==============================================================            
;=  Initialization for EPILOGUE state
;=    KBI  -- disabled.
;=    RTI  -- enabled to show epilogue.
;=    MTIM -- enabled to control beep.
;=
;==============================================================            
epilogue_init:
        disable_kbi
        enable_mtim
        enable_rti
        mov     #HIGH_6_13(FANFARE),sound_page
        lda     led_index
        beq     set_sound
        mov     #HIGH_6_13(MISSED),sound_page
        lsra
        bcc     set_sound
        mov     #HIGH_6_13(MISSED),sound_page        
set_sound:
        ldx     #$C0
        mov     #1,rti_count_l

;==============================================================            
;=  EPILOGUE state
;==============================================================            
epilogue_loop:
        mov     #HIGH_6_13(SIP1),PAGESEL
        wait_nop
        brclr   SIP1_MTIM,MAP_ADDR_6(SIP1),epilogue_checkrti
        accept_mtim
        lda     rti_count_l
        cmp     #2
        bcs     epilogue_checkrti
        lda     PTAD
        eor     #mBEEP
        sta     PTAD
epilogue_checkrti:        
        brclr   SIP1_RTI,MAP_ADDR_6(SIP1),epilogue_loop
        accept_rti
        dec     rti_count_l
        bne     epilogue_loop
        mov     sound_page,PAGESEL
        lda     D[X]
        beq     epilogue_done
        sta     MTIMMOD
        incx
        mov     D[X],rti_count_l
        incx
        bra     epilogue_loop

epilogue_done:        
        jmp     prologue_loop

;-----------------------------------------------------
;-  SUB: Put on an LED at led_index.
;-
;-  PTADD = $00;
;-  PTAD = PTAD_PATTERN[led_index][0];
;-  PTADD = PTAD_PATTERN[led_index][1];
;-----------------------------------------------------
put_led:
        clr     PTADD
        lda     led_index
        asla
        mov     #HIGH_6_13(PTAD_PATTERN),PAGESEL
        add     #MAP_ADDR_6(PTAD_PATTERN)
        tax
        mov     D[X],PTAD
        incx
        mov     D[X],PTADD
        rts


;**************************************************************
;*                 Startup Vector                             *
;**************************************************************
        org     $3FFD

        jmp     _Startup          ; Reset

光の点滅が減速する(ちょっと難しい)仕組み

このアプリケーションでは、 光の移動速度を積分することによって光るLEDの位置を計算しています。 さらに、移動速度も積分によって計算しているのですが、 この時に加速度を移動速度の-1/256倍にしています。 つまり、以下の微分方程式に従うことになります。

dv / dt = -(v / 256) / (ACCEL_SPEED / 1500Hz)

これを解くと

v = v0 * exp(-t / 3.41)

という一般式が得られます。 v0は、時刻0の時の移動速度です。 この式は、3.41秒かけて光の移動速度が1/2.7倍になることを示しています。

デバッグ

ここでは、プログラムのデバッグの際に問題になった事柄を取り上げます。

圧電スピーカの接続

圧電スピーカは、PTA3端子に接続されています。 この端子は、デバッグ時には、BKGD端子として使用されていますので、 デバッグ中は、圧電スピーカから雑音が出ます。 もし、雑音が気になる場合には、抵抗R1(1kΩ)をソケットで実装し、 デバッグ時には取り外すと雑音は出なくなります。

また、同じ理由で、 圧電スピーカから出す音のデバッグをデバッガを使って行うことができません。 端子数の少ないマイコンだから、仕方が無いですね。

WAIT命令とSTOP命令

このプログラムは、複数の割り込み待ちループによって構成されています。 それぞれの割り込み待ちには、 反応時間の短縮と低消費電力化を狙って WAITSTOPという命令が使用されています。

STOP命令は、内部クロックを停止させる命令ですが、 デバッグ中、内部クロックが無いとBDMはうまく接続できません。 データシートでは、STOP状態でもBDMがイネーブルされていれば クロックが動き続けるとされているのですが、 実際には、STOP命令を実行するとデバッガが接続されなくなってしまいました。

そこで、wait_nopstop_nopというアセンブラのマクロを宣言して、 デバッグ中はNOPに置き換えてやることにしました。 こうすると、デバッグ中もクロックが停止せず、 消費電力の削減はできませんが、快適にデバッグを行うことができます。

遊ぶ

リチウム型ボタン電池を入れて完成です。

ルーレットKA2の写真

消費電力を測定するため、 STOP状態の消費電流を手持ちのテスタで測定しましたが、 測定不能という結果になってしまいました。 おそらく、1µA以下になったのだろうと推測しています。

2006-06-25 発行。

Copyright (C) 2006 noritan.org ■