#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <stdint.h>
#include <wiringPi.h>
#include <string.h>
#include "LocalDimmingLedData.h"
#include "interface.h"

#define SPI_DEVICE "/dev/spidev0.0"  // SPI设备文件路径

#define   AW20144_PAGE0                     (0xA0U)
#define   AW20144_PAGE1                     (0xA2U)
#define   AW20144_PAGE2                     (0xA4U)
#define   AW20144_PAGE3                     (0xA6U)
#define   AW20144_PAGE4                     (0xA8U)

#define  ENABLE                             25
#define  AW20144_CHIP1                      26
#define  AW20144_CHIP2                      11
#define  AW20144_CHIP3                      27
#define  AW20144_CHIP4                      0

char ret[12] = {0xA5, 0x01, 0xff, 0x03, 0x04, 0x05, 0x06, 0xA5, 0x00, 0x00, 0x00, 0x00};
char totalbuf[1024];
int count = 1;

int fileusb;
int fileuart;



int spi_fd;


static audio_event_cb_t g_callback = NULL;
static void *g_callback_ctx = NULL;

void audio_set_callback(audio_event_cb_t cb, void *user_ctx)
{
    g_callback = cb;
    g_callback_ctx = user_ctx;
}

//xfm
int xfm_Init()
{
    //sleep(60);
   	// ttyUSB0 ttyAMA0gi
	if ((fileusb = serialOpen("/dev/ttyUSB0", 115200)) < 0)
	{
		printf("/dev/ttyUSB0 Open Faild\r\n");
		return 0;
	}
	printf("/dev/ttyUSB0 Open success\r\n");

	if ((fileuart = serialOpen("/dev/ttyAMA0", 115200)) < 0)
	{
		printf("/dev/ttyAMA0 Open Faild\r\n");
		return 0;
	}
	printf("/dev/ttyAMA0 Open success\r\n");
    memset(totalbuf, 0, 1024);
    
    
    return 1;
}

void protocalAck(int fileusb)
{
     printf("protocalAck..\n");
	char retExmaple[12] = {0};
	strcpy(retExmaple, ret);
	retExmaple[3] = 0x04;
	retExmaple[4] = 0x00;
	retExmaple[5] = 0x00;
	retExmaple[6] = 0x00;

	for (int i = 0; i < 11; i++)
	{
		retExmaple[11] += retExmaple[i];
	}
	retExmaple[11] = ~retExmaple[11] + 1;
	retExmaple[11] = 0xb2;
	write(fileusb, retExmaple, 12);
}

// get angle and change into 16bits, return;
uint16_t getAngle(char *rece)
{
	uint16_t angle;
	int result = 0;

	int i = 0;
	char *p = rece;
	while (*(p + i) != 'a' || *(p + i + 1) != 'n')
	{
		i++;
	}
	i += 8;
	while (*(p + i) != ',')
	{
		if (*(p + i) == '.')
		{
			i++;
			continue;
		}
		int num = *(p + i) - '0';
		result = result * 10 + num;
		i++;
	}
	// printf("result = %d\n", result);
	angle = result;
	return angle;
}

// crc
uint16_t CrcValueCalc(const uint8_t *cpucData, uint16_t usLength)
{
	uint16_t crcValue = 0xffff;
	int i;
	while (usLength--)
	{
		crcValue ^= *cpucData++;
		for (i = 8 - 1; i >= 0; i--)
		{
			if (crcValue & 0x0001)
			{
				crcValue = (crcValue >> 1) ^ 0xa001;
			}
			else
			{
				crcValue = crcValue >> 1;
			}
		}
	}
	return crcValue;
}

extern int get_audio_device_id();

void sentUart(char *buf, int fileuart)
{
	if (count == 9)
	{
		strcat(totalbuf, buf);
		uint16_t angle;
		angle = getAngle(totalbuf);
		printf("angle = %x\n", angle);
		char angleret[2];
		angleret[1] = angle & 0xff;
		angleret[0] = (angle >> 8) & 0xff;
		write(fileuart, angleret, 2);
		count = 1;
		memset(totalbuf, 0, 1024);
        if (g_callback != NULL){
	    char buf[256] = {0};
	    snprintf(buf, 256, "cvlc --play-and-exit --aout alsa --alsa-audio-device hw:%d,0 /usr/local/bin/Videos/aaaa.mp3 &", get_audio_device_id());
	    //system("mpg321 /usr/local/bin/Videos/aaaa.mp3 &");
	    //system("cvlc --play-and-exit --aout alsa --alsa-audio-device hw:2,0 /usr/local/bin/Videos/aaaa.mp3 &");
	    system(buf);
            g_callback(g_callback_ctx, 2);
	    
        }
	}
	else
	{
		count++;
		strcat(totalbuf, buf);
	}

}

void circleReading()
{
    printf("cicleReading..\n");
    serialFlush(fileusb);
    while (1)
    {
        int recbytenum = serialDataAvail(fileusb);
		char buf[1024] = {0};
        if (recbytenum > 1)
		{
			int temp = 0;
			int totalbytes = recbytenum;
			while (totalbytes--)
			{
				buf[temp++] = serialGetchar(fileusb);
			}

			if (buf[0] == 0xa5 && buf[2] == 0x01)
			{
				protocalAck(fileusb);        printf("                          %d\n", __LINE__);
			}
			else
			{
				sentUart(buf, fileuart);     printf("                          %d\n", __LINE__);
			}
		}
    }
    return;
}


//localdimming
void LocalDimming_Init()
{
    spi_fd = open(SPI_DEVICE, O_RDWR);
    if (spi_fd < 0) {
        perror("Unable to open SPI device");
        exit(1);
    }
    // 配置SPI模式、位数、速度等参数
    uint8_t spi_mode = SPI_MODE_0;
    uint8_t spi_bits = 8;
    uint32_t spi_speed = 600000;  // SPI速度;

    usleep(2000);
    if (ioctl(spi_fd, SPI_IOC_WR_MODE, &spi_mode) == -1) {
        perror("Unable to set SPI mode");
        exit(1);
    }
    if (ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &spi_bits) == -1) {
        perror("Unable to set SPI bits per word");
        exit(1);
    }
    // provided 
    if (ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed) == -1) {
        perror("Unable to set SPI speed");
        exit(1);
    }
    
    //raspi
    if (wiringPiSetup() == -1)
    {
        //printf("");
        //return -1;
    }

    usleep(2000);
    pinMode(25, OUTPUT);
    pinMode(26, OUTPUT);
    pinMode(11, OUTPUT);
    pinMode(27, OUTPUT);
    pinMode(0, OUTPUT);

     // enable set to 0;
    setGpioLevel(25, 0); 
    // cs set to high;
    setGpioLevel(26, 1);
    setGpioLevel(11, 1);
    setGpioLevel(27, 1);
    setGpioLevel(0, 1);
    setGpioLevel(25, 1);
    
    usleep(2000);
    AW20144_Byte_Write(AW20144_CHIP1, AW20144_PAGE0, 0x2FU, 0xAEU);
    AW20144_Byte_Write(AW20144_CHIP2, AW20144_PAGE0, 0x2FU, 0xAEU);
    AW20144_Byte_Write(AW20144_CHIP3, AW20144_PAGE0, 0x2FU, 0xAEU);
    AW20144_Byte_Write(AW20144_CHIP4, AW20144_PAGE0, 0x2FU, 0xAEU);
    
    usleep(2000);
    AW20144_Byte_Write(AW20144_CHIP1, AW20144_PAGE0, 0x00U, 0x71U);
    AW20144_Byte_Write(AW20144_CHIP2, AW20144_PAGE0, 0x00U, 0x71U);
    AW20144_Byte_Write(AW20144_CHIP3, AW20144_PAGE0, 0x00U, 0x71U);
    AW20144_Byte_Write(AW20144_CHIP4, AW20144_PAGE0, 0x00U, 0x71U);

    AW20144_Byte_Write(AW20144_CHIP1, AW20144_PAGE0, 0x01U, 0xFFU);
    AW20144_Byte_Write(AW20144_CHIP2, AW20144_PAGE0, 0x01U, 0xFFU);
    AW20144_Byte_Write(AW20144_CHIP3, AW20144_PAGE0, 0x01U, 0xFFU);
    AW20144_Byte_Write(AW20144_CHIP4, AW20144_PAGE0, 0x01U, 0xFFU);
   
    AW20144_Byte_Write(AW20144_CHIP1, AW20144_PAGE0, 0x4DU, 0x07U);
    AW20144_Byte_Write(AW20144_CHIP2, AW20144_PAGE0, 0x4DU, 0x07U);
    AW20144_Byte_Write(AW20144_CHIP3, AW20144_PAGE0, 0x4DU, 0x07U);
    AW20144_Byte_Write(AW20144_CHIP4, AW20144_PAGE0, 0x4DU, 0x07U);
    //sl for max
    for (unsigned int i = 0U; i < 144U; i++)
    {
         AW20144_Byte_Write(AW20144_CHIP1, AW20144_PAGE2, i, 0xFFU);
         AW20144_Byte_Write(AW20144_CHIP2, AW20144_PAGE2, i, 0xFFU);
         AW20144_Byte_Write(AW20144_CHIP3, AW20144_PAGE2, i, 0xFFU);
         AW20144_Byte_Write(AW20144_CHIP4, AW20144_PAGE2, i, 0xFFU);
    }
}

 void setGpioLevel(int num, int level)
{
    digitalWrite(num, level);  
    return;
}

 int SPI_Transfer(const char *pu8TxBuf, char *pu8RxBuf, int i32len)
{

    int i32Rtn;

    if (spi_fd < 0)
    {
        return -1;
    }
    
    struct spi_ioc_transfer stTrans =
    {
        .tx_buf      = (unsigned long)pu8TxBuf,
        .rx_buf      = (unsigned long)pu8RxBuf,
        .len         = i32len,
        .delay_usecs = 0,
    };
    
    if (ioctl(spi_fd, SPI_IOC_MESSAGE(1), &stTrans) < 0)
    {
        printf("failed to transfer data through SPI0 \n");
        return -1;
    }

    return 0;
}

 int AW20144_Byte_Write(int i32ChipSelect, char u8Page, char u8Addr, char u8Val)
{
    char u8DataBuffer[3];

    //GPIO_Set_Level(i32ChipSelect, GPIO_LEVEL_LOW);
    setGpioLevel(i32ChipSelect, 0); 
    u8DataBuffer[0] = u8Page & 0xFEU;
    u8DataBuffer[1] = u8Addr;
    u8DataBuffer[2] = u8Val;
    SPI_Transfer(u8DataBuffer, NULL, 3);
    setGpioLevel(i32ChipSelect, 1); 
    //GPIO_Set_Level(i32ChipSelect, GPIO_LEVEL_HIGH);

    return 0;
}

void resetPwm()
{
    for (unsigned int i = 0U; i < 144U; i++)
    {
         AW20144_Byte_Write(AW20144_CHIP1, AW20144_PAGE1, i, 0x00U);
         AW20144_Byte_Write(AW20144_CHIP2, AW20144_PAGE1, i, 0x00U);
         AW20144_Byte_Write(AW20144_CHIP3, AW20144_PAGE1, i, 0x00U);
         AW20144_Byte_Write(AW20144_CHIP4, AW20144_PAGE1, i, 0x00U);
    }
    return;
}
void setPwmtomax()
{
    for (unsigned int i = 0U; i < 144U; i++)
    {
         AW20144_Byte_Write(AW20144_CHIP1, AW20144_PAGE1, i, 0x0FU);
         AW20144_Byte_Write(AW20144_CHIP2, AW20144_PAGE1, i, 0x0FU);
         AW20144_Byte_Write(AW20144_CHIP3, AW20144_PAGE1, i, 0x0FU);
         AW20144_Byte_Write(AW20144_CHIP4, AW20144_PAGE1, i, 0x0FU);
    }
    return;
}
//*(*(ptr + k) + temp)
void eachPicWrite(int num, int pic)
{
    const char (*LocalDimmingLedData)[198];
    
    switch (num)
    {
        case 2:
            LocalDimmingLedData = LocalDimmingLedData_Ack;
            pic = 271 - pic;
            break;
        case 3:
            LocalDimmingLedData = LocalDimmingLedData_Right;
            pic = 91 - pic;
            break;
        case 4:
            LocalDimmingLedData = LocalDimmingLedData_Left;
            pic = 91 - pic;
            break;
        default:
            LocalDimmingLedData = LocalDimmingLedData_Standby;
            pic = 161 - pic;
            break;
    }

    int temp = 0;
    int count = 198;
    int chip[11] = {26, 26, 26, 11, 11, 11, 27, 27, 27, 0, 0}; 
    int addr[11] = {0, 72, 36, 0, 72, 36, 0, 72, 36, 0, 36};
    int op[11] = {18, 90, 54, 18, 90, 54, 18, 90, 54, 18, 54};
        for (int i = 0; i < 11; i++)
        {
            //int num = 9;
            int num = 9;
            int offset = addr[i];
            int chips = chip[i];
            int ops = op[i];
            for (int j = 0; j < 18; j++)
            {
                AW20144_Byte_Write(chips, AW20144_PAGE1, num+offset, LocalDimmingLedData[pic][i*18 + j]);
                //AW20144_Byte_Write(chips, AW20144_PAGE1, num+offset, *(a + temp));
                //printf("%d\n", num+offset);
                //printf("%x\n", *(a + temp));
                //printf("");
                num = (num+1) % 18;
            }
        
        }
}
