/**************************************************************************//**
 * @item     CosyOS-III 例程（系统构建）
 * @file     demo_debug.c
 * @brief    例程-DEBUG for STC8H
 * @author   迟凯峰
 * @version  V1.0.3
 * @date     2026.07.31
 ******************************************************************************/

#if 1 /* 编译开关 */ \
 && defined ( __C51__ )

#include "CosyOS.H"
#if (SYSCFG_DEBUGGING == __ENABLED__)

/*
 * 用户定义
 */

/*-------------------------------------------------------------*
 | DEBUG_MODE | 输出（UART SEND）| 输入（UART RECV）| 推荐等级 |
 |------------+------------------+------------------+----------|
 | 0          | printf（查询）   | 无               | *        |
 |------------+------------------+------------------+----------|
 | 1          | 串口发送中断     | 串口接收中断     | ***      |
 |------------+------------------+------------------+----------|
 | 2          | DMA串口发送中断  | DMA串口接收中断  | *****    |
 *-------------------------------------------------------------*/
#define DEBUG_MODE          0

/* DEBUG RECV 缓存SIZE */// 当 DEBUG_MODE 非0时，需定义此项
#define DEBUG_RECV_BUFF     32

////////////////////////////////////////////////////////////////////////////////

// 1、例程中使用了UART1做为DEBUG专用串口，用户如需更换其它串口请自行调整。
// 2、下方的DEBUG配置函数 Debug_Config()，不能够取代基本的串口初始化工作，
//    用户在main函数中，在调用该函数之前，需先行初始化串口。

////////////////////////////////////////////////////////////////////////////////

#if   (DEBUG_MODE == 0)
#include <stdio.h>
#else
static char xdata  u_debug_recv_buff[DEBUG_RECV_BUFF];
static char xdata *u_debug_recv_p = u_debug_recv_buff;
#if   (DEBUG_MODE == 1)
static char xdata *u_debug_send_p;
#elif (DEBUG_MODE == 2)
#ifdef  DMA_UR1R_RXA
#undef  DMA_UR1R_RXA
#endif
#ifdef  DMA_UR1T_TXA
#undef  DMA_UR1T_TXA
#endif
#define DMA_UR1R_RXA (*(char xdata * volatile xdata *)0xfa3d)
#define DMA_UR1T_TXA (*(char xdata * volatile xdata *)0xfa35)
static unsigned char DMA_UR1T_cishu;
static unsigned char DMA_UR1T_bytes;
static char xdata    DMA_UR1R_SBUF;
#endif
#endif

void Debug_Config(void)
{
    #if   (DEBUG_MODE == 0)
    REN = 0;
    ES  = 0;
    TI  = 1;
    
    #elif (DEBUG_MODE == 1)
    if(~PSH && ~PS){
        PS = 1;
    }
    REN = 1;
    ES  = 1;
    
    #elif (DEBUG_MODE == 2)
    REN = 1;
    ES  = 0;
    DMA_UR1T_CFG |= 0x80 | 0x04 | 0x01;
    DMA_UR1T_CR  |= 0x80;
    DMA_UR1R_RXA  = &DMA_UR1R_SBUF;
    DMA_UR1R_AMT  = 0;
    DMA_UR1R_CFG |= 0x80 | 0x04 | 0x01;
    DMA_UR1R_CR  |= 0x80 | 0x20 | 0x01;
    #endif
}

#if (SYSCFG_DEBUG_SENDLEN == __DISABLED__)
void debug_hook(char _XDATA_MEM_ *p)
#else
void debug_hook(char _XDATA_MEM_ *p, s_u16_t len)
#endif
{
    #if   (DEBUG_MODE == 0)
    printf("%s", p);
    xDebugSend_Complete();
    
    #elif (DEBUG_MODE == 1)
    u_debug_send_p = p;
    TI = 1;
    
    #elif (DEBUG_MODE == 2)
    DMA_UR1T_cishu = (len / 256) + !!(len % 256);
    DMA_UR1T_bytes = (len % 256) ? (len % 256 - 1) : (256 - 1);
    DMA_UR1T_TXA = p;
    DMA_UR1T_AMT = (DMA_UR1T_cishu > 1) ? (256 - 1) : DMA_UR1T_bytes;
    DMA_UR1T_CR |= 0x40;
    #endif
}

#if (DEBUG_MODE == 1)
void UART1_Isr(void) interrupt 4
{
    if(TI){
        TI = 0;
        if(*u_debug_send_p){
            SBUF = *u_debug_send_p++;
        }
        else{
            xDebugSend_Complete();
        }
    }
    if(RI){
        RI = 0;
        if(u_debug_recv_p - u_debug_recv_buff < DEBUG_RECV_BUFF - 1){
            *u_debug_recv_p++ = SBUF;
            if(SBUF == '\n'){
                xDebugRecv_Handler(u_debug_recv_buff, u_debug_recv_p - u_debug_recv_buff);
                u_debug_recv_p = u_debug_recv_buff;
            }
        }
        else{
            u_debug_recv_p = u_debug_recv_buff;
        }
    }
}

#elif (DEBUG_MODE == 2)
void DMA_UR1T_Isr(void) interrupt 50
{
    DMA_UR1T_STA &=~0x01;
    DMA_UR1T_cishu--;
    if(DMA_UR1T_cishu){
        DMA_UR1T_TXA += 256;
        DMA_UR1T_AMT  = (DMA_UR1T_cishu > 1) ? (256 - 1) : DMA_UR1T_bytes;
        DMA_UR1T_CR  |= 0x40;
    }
    else{
        xDebugSend_Complete();
    }
}

void DMA_UR1R_Isr(void) interrupt 51
{
    DMA_UR1R_STA &=~0x01;
    if(u_debug_recv_p - u_debug_recv_buff < DEBUG_RECV_BUFF - 1){
        *u_debug_recv_p++ = DMA_UR1R_SBUF;
        if(DMA_UR1R_SBUF == '\n'){
            xDebugRecv_Handler(u_debug_recv_buff, u_debug_recv_p - u_debug_recv_buff);
            u_debug_recv_p = u_debug_recv_buff;
        }
    }
    else{
        u_debug_recv_p = u_debug_recv_buff;
    }
    DMA_UR1R_CR |= 0x20 | 0x01;
}
#endif

#endif

#endif
