midifun2.S

以下はアセンブラ部分のソースですが、プリプロセッサを通すためにファイル名のエクステンションは「.S」(英大文字の「エス」) にする必要があります。

;/*************************************************/
;/* midifun2.S : MIDI functions (asm part)        */
;/*              for ATtiny10                     */
;/*                                               */
;/* 2012/01/16 : Created by pcm1723               */
;/*************************************************/

#include <avr/io.h>
#include "m2c_tn10.h"
;
; void calc_pitch(int8_t gate_flag)
;
; arg1 -- int8_t gate_flag : 0 != GATE ON, 0 == GATE intact
;
        .global calc_pitch
        .func   calc_pitch

#define ROUND_CONST 0x20

calc_pitch:
        ldi     ZL,lo8(ch_prop+1) ; ch_prop[0].MD_bend[0]
        ldi     ZH,hi8(ch_prop+1) ; ch_prop[0].MD_bend[0]
        ld      r21,Z+
        ld      r22,Z+  ; R22:R21 = ch_prop[0].MD_bend
        lsl     r21
        rol     r22     ; R22:R21 <<= 1
        sbc     r23,r23 ; R23 <-- sign extension of R22:R21
        lds     r25,ch_prop+3 ; LIER (R25) = ch_prop[0].MD_bend_range
        clr     r31
        clr     r30
        clr     r19     ; clear SUM (R31:R30:R19)
; 
calc_p1:
        lsl     r21
        rol     r22
        rol     r23  ; CAND (R23:R22:R21) <<= 1
calc_p2:
        lsr     r25  ; b0 of LIER (R25) --> C
        brcc    calc_p3 ; don't add CAND
        add     r19,r21
        adc     r30,r22
        adc     r31,r23 ; SUM (R31:R30:R19) += CAND (R23:R22:R21)
calc_p3:
        tst     r25     ; LIER (R25) == 0 ?
        brne    calc_p1 ; loop again
;
        subi    r30,lo8(-ROUND_CONST) ; fraction part
        sbci    r31,hi8(-ROUND_CONST) ; rounding
        lds     r19,ch_prop ; R19 = ch_prop[0].MD_note
        add     r31,r19     ; add integer part
        clr     r23         ; upper byte (b15..b8)
        lsl     r30
        rol     r31
        rol     r23
        lsl     r30
        rol     r31
        rol     r23         ; R23:R31:R30 <<= 2
        out     _SFR_IO_ADDR(OCR0AH),r23 
        out     _SFR_IO_ADDR(OCR0AL),r31 ; OCR0A duty register
        tst     r24   ; test for GATE ON flag
        breq    calc_p_ret ; immediate return
        lds     r24,unit_prop+2 ; R24 = hi8(nit_prop[0].gate_que)
        ori     r24,0x80        ; GATE ON flag
        sts     unit_prop+2,r24 ; update GATE queue
calc_p_ret:
        ret
        .endfunc
;
; void pitch_bend( void )
;
        .global pitch_bend
        .func   pitch_bend
pitch_bend:
        clr     r24   ; no GATE manipulation
        rjmp    calc_pitch ; tail merge to 'calc_pitch()'       
        .endfunc
;
; void midi_note_on(uint8_t MD_2nd, uint8_t MD_3rd)
;
; arg1 -- int8_t MD_2nd : MIDI note number
;
; arg2 -- int8_t MD_3rd : MIDI velocity (unused)
;
        .func   midi_note_on
        .global midi_note_on
midi_note_on:
        sts     ch_prop,r24  ; ch_prop[0].MD_note = MD_2nd
        lds     r24,unit_prop  ; R24 = unit_prop[0].on_cnt
        subi    r24,-1  ; R24 += 1
        sts     unit_prop,r24 ; unit_prop[0].on_cnt = R24
        ldi     r24,-1       ; GATE ON flag
        rjmp    calc_pitch  ; tail merge to 'calc_pitch()'
        .endfunc