V3s_ircut.c 9.7 KB
#include "ircut.h"

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "version_choose.h"

#include "JZsdkLib.h"

typedef struct
{
    unsigned int CFG[4];
    unsigned int DAT;
    unsigned int DRV0;
    unsigned int DRV1;
    unsigned int PUL0;
    unsigned int PUL1;
} PIO_Struct;

typedef struct
{
    PIO_Struct Pn[7];
} PIO_Map;

typedef enum {
    PA = 0,
    PB = 1,
    PC = 2,
    PD = 3,
    PE = 4,
    PF = 5,
    PG = 6,
} PORT;

typedef enum {
    IN = 0x00,
    OUT = 0x01,
    AUX = 0x02,
    INT = 0x06,
    DISABLE = 0x07,
} PIN_MODE;

unsigned int fd;
PIO_Map *PIO = NULL;
unsigned int addr_start, addr_offset;
unsigned int PageSize, PageMask;

static int PowerContorl;

#define PIO_BASE_ADDR 0x01C20000
#define PIO_ADDR_OFF 0x800
#define PIO_CFG_OFF 0x24    //配置
#define PIO_DAT_OFF 0x34    //数据
#define PWM_ADDR_OFF 0x1400
#define PWM_CH1_OFF 0x08    //pwm1
#define Page_Size (4096 * 2)
#define PIO_BASE_ADDRESS 0x01C20800

#if DEVICE_VERSION == JZ_H1E 
    #define AMPLIFIER_PIN PB
    #define AMPLIFIER_PIN_NUM 4
#elif DEVICE_VERSION == JZ_H1T
    #define AMPLIFIER_PIN PG
    #define AMPLIFIER_PIN_NUM 5
#elif DEVICE_VERSION == JZ_H10T
    #define AMPLIFIER_PIN PG
    #define AMPLIFIER_PIN_NUM 5
#elif DEVICE_VERSION == JZ_U3
    #define AMPLIFIER_PIN PB
    #define AMPLIFIER_PIN_NUM 4
#elif DEVICE_VERSION == TF_A1
    #define AMPLIFIER_PIN PG
    #define AMPLIFIER_PIN_NUM 5
#else
    #define AMPLIFIER_PIN PB
    #define AMPLIFIER_PIN_NUM 4
#endif



#define STATUS_LIGHT_PIN PG
#define STATUS_LIGHT_PIN_NUM 2

static uint32_t *base_map = NULL;
static uint32_t *gpio_map = NULL;
static uint32_t *gpio_cfg = NULL;
static uint32_t *gpio_dat = NULL;
static uint32_t *pwm_base_map = NULL;
static uint32_t *pwm1_period = NULL;

void GPIO_ConfigPin(PORT port, unsigned int pin, PIN_MODE mode)
{
    if (base_map == NULL)
        return;
    PIO->Pn[port].CFG[pin / 8] &= ~((unsigned int)0x07 << pin % 8 * 4);
    PIO->Pn[port].CFG[pin / 8] |= ((unsigned int)mode << pin % 8 * 4);
    printf("struct PIO_Struct size : %d\n",sizeof(PIO->Pn[port]));
}

void GPIO_SetPin(PORT port, unsigned int pin, unsigned int level)
{
    if (base_map == NULL)
        return;
    if (level)
        PIO->Pn[port].DAT |= (1 << pin);
    else
        PIO->Pn[port].DAT &= ~(1 << pin);
}

int GPIO_Free(void)
{
    if ((munmap(gpio_map, PageSize * 2)) == 0)//取消映射
    {
        printf("unmap success!");
    }
    else
    {
        printf("unmap failed!");
    }
    return 0;
}




void V3s_set_amplifier(int amplifier_mode)
{   //功放开关
    if(amplifier_mode==0)
    {//关闭功放
        printf("关闭功放\n");
        GPIO_SetPin(AMPLIFIER_PIN,AMPLIFIER_PIN_NUM,0);
    }
    else if(amplifier_mode==1)
    {//打开功放
        printf("打开功放\n");
        GPIO_SetPin(AMPLIFIER_PIN,AMPLIFIER_PIN_NUM,1);
    }
}


int V3s_PWM_contrl(int PWM_num)
{

    /*设置活跃周期  活跃周期要小于总周期1000*/
    (*pwm1_period) &= ~((uint32_t)65535 << 0); //将15~0位置零
    (*pwm1_period) |= (uint32_t)PWM_num << 0; //将15~0位置为2500 现在设置活跃周期为35535

    /*使能pwm,PWM_CH1_EN为enable*/
    (*pwm_base_map) &= ~((uint32_t)1 << 19); //先将第4位置0 ---> disable
    (*pwm_base_map) |= (uint32_t)1 << 19;    //将第4位置1 ---> enable pwm1  

    //printf("V3s_Pwm_control:%d\n",PWM_num);

    return 0;
}


static void GPIO_mmap_Init()
{
    if ((fd = open("/dev/mem", O_RDWR)) == -1)
    {
        printf("open error");
        return;
    }

    PageSize = sysconf(_SC_PAGESIZE); //使用sysconf查询系统页面大小
    PageMask = (~(PageSize - 1));     //页掩码
    printf("PageSize:%d,PageMask:0x%.8X", PageSize, PageMask);

    addr_start = PIO_BASE_ADDRESS & PageMask;   //0x01C20800 & 0xfffff000 =  0x1C20000
    addr_offset = PIO_BASE_ADDRESS & ~PageMask; //0x01C20800 & 0x00000100 = 0x800
    printf("addr_start:%.8X,addr_offset:0x%.8X\n", addr_start, addr_offset);
    //mmap(系统自动分配内存地址,映射区长度“内存页的整数倍”,选择可读可写,MAP_SHARED=与其他所有映射到这个对象的进程共享空间,文件句柄,被映射内容的起点)
    //offest 映射物理内存的话,必须页对其!!!   所以这个起始地址应该是0x1000的整数倍,那么明显0x01C20800需要减去0x800才是整数倍!
    if ((base_map = mmap(NULL, PageSize * 2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, addr_start)) == NULL)
    {
        printf("mmap error");
        close(fd);
        return;
    }
    printf("base_map:%.8X\n", base_map);
    close(fd); //映射好之后就可以关闭设备号

}


//状态灯初始化
static void Status_light_init() 
{
    //状态灯初始化
    //这里已经将0x1c20000的地址映射到了内存中,但是我们需要的地址是0x01C20800,所以要再加上地址偏移量~
    PIO = (PIO_Map *)((unsigned int)base_map + addr_offset);
    printf("PIO:0x%.8X\n", PIO);

    GPIO_ConfigPin(STATUS_LIGHT_PIN,STATUS_LIGHT_PIN_NUM,OUT);
}

static void Status_light()
{
    //低电平亮
    GPIO_SetPin(STATUS_LIGHT_PIN,STATUS_LIGHT_PIN_NUM,0);
}

static void PWM_init()     //pwm初始化
{
    //pwm引脚初始化
    //这里已经将0x1c20000的地址映射到了内存中,但是我们需要的地址是0x01C20800,所以要再加上地址偏移量~
    gpio_map = (uint32_t)base_map + PIO_ADDR_OFF; //加上偏移量必选先把他转化成unsigend int才可以相加
    //printf("gpio_map:0x%.8X\n", (uint32_t)gpio_map);

    gpio_cfg = (uint32_t)gpio_map + PIO_CFG_OFF; //gpioB控制寄存器地址

/**
 * PWM波配置顺序
 * 1.GPIO 配置PWM输出模式
 * 2.PWM 预分頻 
 * 3.PWM 总周期
 * 4.PWM 活跃周期
 * 5.PWM 使能
 */
    //PB5设定PWM输出
    (*gpio_cfg) &= ~((unsigned int)7 << 20);    //置20:22 000
    (*gpio_cfg) |= ((unsigned int)2 << 20); //PB5 2=010 设定20:22 010 pwm1模式
    //我们需要的地址是0x01C21400,所以要再加上地址偏移量

    //无法修改为 pwm_base_map = (uint32_t *)base_map + PWM_ADDR_OFF

    pwm_base_map = (uint32_t)base_map + PWM_ADDR_OFF; //pwm_base_map也是pwm控制寄存器 初始值是0x00000000
    //printf("pwm_base_map:0x%.8X\n", (uint32_t)pwm_base_map);

    /*首先设置pwm1 预分頻*/                  //PWM_CH1_PRESCAL
    (*pwm_base_map) &= ~((uint32_t)15 << 15); //先将15~18位置0
    (*pwm_base_map) |= (uint32_t)0 << 15;     //将15~18位设置为 0000 ---> 对应分頻120 24m/120=200k
    //(*pwm_base_map) |= (uint32_t)9 << 15;     //将15~18位设置为 1001 ---> 对应分頻120 24m/24k=1000

    /*可能要设置SCLK_CH1_GATING为mask*/
    (*pwm_base_map) &= ~((uint32_t)1 << 21); //先将第21位置0 
    (*pwm_base_map) |= (uint32_t)1 << 21; //将第21位置1 ---> 设置为自定义预分頻系数
/**
 * 具体的总周期时间的作用需要进一步测试
 * 注意:要活动周期设置好之后使能PWM通道WWW
 * 这样才会有正确输出,并且之后直接修改寄存器的值就可以修改占空比。
 * */
    /*再设置pwm1占空比*/
    //无法修改为 pwm1_period = (uint32_t *)pwm_base_map + PWM_CH1_OFF

    pwm1_period = (uint32_t)pwm_base_map + PWM_CH1_OFF; //pwm1_period设置pwm_CH1的占空比寄存器
    //printf("pwm1_period:0x%.8X\n", (uint32_t)pwm1_period);

    /*先设置总周期*/ //PWM周期的计算应该是这样 OSC 24MHz / Pre-scalar / (entire cycles + 1)
    (*pwm1_period) &= ~((uint32_t)65535 << 16); //将31~16位置零    
    (*pwm1_period) |= (uint32_t)1000 << 16; // 现在设置整个周期1000

    printf("v3spwm初始化完成\n");    
}

static int V3S_Power_Pin_init()
{
    //这里已经将0x1c20000的地址映射到了内存中,但是我们需要的地址是0x01C20800,所以要再加上地址偏移量~
    PIO = (PIO_Map *)((unsigned int)base_map + addr_offset);
    printf("PIO:0x%.8X", PIO);

    if (DEVICE_VERSION == JZ_H10T)
    {
        GPIO_ConfigPin(PB,6,OUT);

    }
    
}




void V3s_Ircut_Init()//引脚初始化
{
    GPIO_mmap_Init();    //GPIO 内存映射初始化

    //这里已经将0x1c20000的地址映射到了内存中,但是我们需要的地址是0x01C20800,所以要再加上地址偏移量~
    PIO = (PIO_Map *)((unsigned int)base_map + addr_offset);
    printf("PIO:0x%.8X", PIO);

    //静音引脚初始化
    GPIO_ConfigPin(AMPLIFIER_PIN,AMPLIFIER_PIN_NUM,OUT);

    //10T要初始化电机引脚
    if (DEVICE_VERSION == JZ_H10T)
    {
        PWM_init() ;    //pwm初始化
        GPIO_ConfigPin(PB,6,OUT); //对外供电初始化
    }

    //激光引脚初始化
    if (DEVICE_VERSION == JZ_U3S)
    {
        GPIO_ConfigPin(PB,6,OUT);
        GPIO_ConfigPin(PB,7,OUT);   
    }
    
    //状态灯初始化
    //Status_light_init(); 
    //打开状态灯
    //Status_light(); 
}


int V3s_Ircut_uInit()  
{
    //GPIO 内存映射移除
    munmap(base_map, Page_Size);
    printf("munmap success!\n");
}

void Ircut_V3S_Set_OutPutPowerControl(int power_control)
{
    if (DEVICE_VERSION == JZ_H10T)
    {
        if (power_control == 1)
        {
            GPIO_ConfigPin(PB,6,OUT);  //电源脚初始化
            GPIO_SetPin(PB,6,1);       //打开开关
        }
        else if(power_control ==0)
        {
            GPIO_SetPin(PB,6,0);       //关闭开关
            GPIO_ConfigPin(PB,6,DISABLE);    //释放引脚    
        }

    }

}

/***********************
 * 
 *  引脚控制
 * 
 * 
 * ********************/
T_JZsdkReturnCode V3s_PinControl(int port, int num, int status)
{
    int value = 0;
    if (status == JZ_FLAGCODE_ON)
    {
        value = 1;
    }
    else if (status == JZ_FLAGCODE_OFF)
    {
        value = 0;
    }
    
    GPIO_SetPin(port,num,value);       //关闭开关
}