;/***************************************************************************
; *   Copyright (C) 2009, Crawlerz                                          *
; *                                                                         *
; *   Description:                                                          *
; *        - enCoRe II Bit-bang Async Transmit for Debug                    *
; *   Version:                                                              *
; *     2009.44.7                                                           *
; *                                                                         *
; *   This program is free software; you can redistribute it and/or modify  *
; *   it under the terms of the GNU General Public License as published by  *
; *   the Free Software Foundation; either version 2 of the License, or     *
; *   (at your option) any later version.                                   *
; *                                                                         *
; *   This program is distributed in the hope that it will be useful,       *
; *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
; *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
; *   GNU General Public License for more details.                          *
; *                                                                         *
; *   You should have received a copy of the GNU General Public License     *
; *   along with this program; if not, write to the                         *
; *   Free Software Foundation, Inc.,                                       *
; *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
; ***************************************************************************/
include "m8c.inc"
include "psocgpioint.inc"
include "memory.inc"
include "async.inc"

export _AsyncStart
export  AsyncStart
export _AsyncWrite
export  AsyncWrite

area InterruptRAM(ram)                                                          ; variables on ram page 0
AsyncData::   blk  1

area UserModules (ROM, REL)

.section
;-----------------------------------------------------------------------------
;  FUNCTION NAME: _AsyncStart
;
;  DESCRIPTION:
;-----------------------------------------------------------------------------
;  ARGUMENTS:
;
;  RETURNS: none
;-----------------------------------------------------------------------------
 AsyncStart:
_AsyncStart:
    or  reg[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1 / Stop:Idle [9 cycles]
    ret                                                                         ;                               [8 cycles]
.endsection

.section
;-----------------------------------------------------------------------------
;  FUNCTION NAME: _AsyncWrite
;
;  DESCRIPTION:
;   Writes async data (LSB first) to output pin "ASYNC" as fast as CPUCLK will allow.
;   ...Assumes "ASYNC" pin is already configured for output / default high.
;   ...Warning: Global interrupts are enabled upon exit.
;   CPUCLK/24MHz is 888,888bps/~12usec per byte
;   CPUCLK/12MHz is 444,444bps/~24usec per byte
;   ROM=139B, RAM=1B
;-----------------------------------------------------------------------------
;  ARGUMENTS: Data: 8-bit data that is written to the pin
;
;  RETURNS: none
;
;       Data to be written is in A
;-----------------------------------------------------------------------------
 AsyncWrite:
_AsyncWrite:
    and F,0xFE                                                                  ;M8C_DisableGInt[4 cycles]
    mov [AsyncData], A                                                          ;                               [5 cycles]

startbit:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0 / Start                     [9 cycles]
    jmp b0                                                                      ;                               [5 cycles]
b0:
    tst [AsyncData], 1                                                          ;                               [8 cycles]
    jz  b0low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp b1                                                                      ;                               [5 cycles]
b0low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp b1                                                                      ;                               [5 cycles]

b1:
    tst [AsyncData], 2                                                          ;                               [8 cycles]
    jz  b1low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp b2                                                                      ;                               [5 cycles]
b1low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp b2                                                                      ;                               [5 cycles]

b2:
    tst [AsyncData], 4                                                          ;                               [8 cycles]
    jz  b2low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp b3                                                                      ;                               [5 cycles]
b2low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp b3                                                                      ;                               [5 cycles]

b3:
    tst [AsyncData], 8                                                          ;                               [8 cycles]
    jz  b3low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp b4                                                                      ;                               [5 cycles]
b3low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp b4                                                                      ;                               [5 cycles]

b4:
    tst [AsyncData], 16                                                         ;                               [8 cycles]
    jz  b4low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp b5                                                                      ;                               [5 cycles]
b4low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp b5                                                                      ;                               [5 cycles]

b5:
    tst [AsyncData], 32                                                         ;                               [8 cycles]
    jz  b5low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp b6                                                                      ;                               [5 cycles]
b5low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp b6                                                                      ;                               [5 cycles

b6:
    tst [AsyncData], 64                                                         ;                               [8 cycles]
    jz  b6low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp b7                                                                      ;                               [5 cycles]
b6low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp b7                                                                      ;                               [5 cycles]

b7:
    tst [AsyncData], 128                                                        ;                               [8 cycles]
    jz  b7low                                                                   ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1                             [9 cycles]
    jmp stopbit                                                                 ;                               [5 cycles]
b7low:
    and REG[ASYNC_Data_ADDR], ~ASYNC_MASK                                       ;=0                             [9 cycles]
    jmp stopbit                                                                 ;                               [5 cycles]

stopbit:
    nop                                                                         ;                               [4 cycles]
    nop                                                                         ;                               [4 cycles]
    mov A, [AsyncData]                                                          ;                               [5 cycles]
    or  REG[ASYNC_Data_ADDR], ASYNC_MASK                                        ;=1 / Stop:Idle [9 cycles]
    or  F,0x1                                                                   ;M8C_EnableGInt [4 cycles]
    ret                                                                         ;                               [8 cycles]
.endsection
