/*
 *  Copyright Droids Corporation, Microb Technology, Eirbot (2005)
 * 
 *  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
 *
 *  Revision : $Id$
 *
 */
#include <uart.h>
#include <wait.h>
#include <stdio.h>
#include <i2c_config.h>
#include <i2cm_genric.h>
#include <compat/twi.h>
#include <string.h>

#define SOH 0x01
#define NAK 0x15
#define ACK 0x06
#define EOT 0x04
#define CTRLZ 26

#define BASE_RAMV 0x00000000
#define BASE_RAMT 0x00100000
#define BASE_FLASHA 0x00200000
#define BASE_FLASHB 0x00300000

u08 xmodem_send(u32 memory_address, u32 taille);

void* mem2add(u32 memory_address)
{
    void *pointeur;
    unsigned char *pages = (unsigned char *) (0x1FFF);

    // memory_address 22 bits:
    // 31 downto 22: rien donc 0
    // 21 downto 20: pages (00=ramV, 01=ramT, 10=flashA, 11=flashB)
    // 19 downto 1: adresse physique
    // 0 : poids fort / faible (dans le cas des flash, poids forts et faibles accedent a la meme addresse)

    // "*pages":
    // 7 inutilisé
    // 6 downto 5: pages donc 21 downto 20
    // 4 downto 0: adresse haute donc 19 downto 15

    *pages = (memory_address & 0x003F8000) >> 15;
    pointeur = (memory_address & 0x00007FFF) + 0x00008000;
    return pointeur;
}

void mem_fill(u32 memory_address, u08 data, u32 taille)
{
    u08 *buffer;
    u32 cpt;

    for (cpt=0; cpt<taille; cpt++)
    {
        buffer = (unsigned char *)mem2add(memory_address+cpt);
        *buffer = data;
    }
}

void set_cross(u08 pos_x, u08 pos_y)
{
    u08 * cross_x = (u08 *) (0x1F00 + 24);
    u08 * cross_y = (u08 *) (0x1F00 + 25);

    *cross_x = pos_x;
    *cross_y = pos_y;
}

void set_seuilsB(u08 code, u08 hmin, u08 hmax, u08 smin, u08 smax, u08 lmin, u08 lmax)
{
    u08 * select = (u08 *) (0x1F00 +4); // B: +4, A: +1
    u08 * data = (u08 *) (0x1F00 +3); // B: +3, A: +0
    u08 * write = (u08 *) (0x1F00 +5); // B: +5, A: +2
    u08 selection;

    *write = 0;
    selection = (code << 3) & 0x38;

    *select = selection;
    *data = hmin;
    *write = 1;
    *write = 0;

    selection++;
    *select = selection;
    *data = hmax;
    *write = 1;
    *write = 0;

    selection++;
    *select = selection;
    *data = smin;
    *write = 1;
    *write = 0;

    selection++;
    *select = selection;
    *data = smax;
    *write = 1;
    *write = 0;

    selection++;
    *select = selection;
    *data = lmin;
    *write = 1;
    *write = 0;

    selection++;
    *select = selection;
    *data = lmax;
    *write = 1;
    *write = 0;

}

void start_acq(u08 *record, u08 whichram)
{
    volatile u08 * recorder = record;

    *recorder = 0;
    while( ((*recorder)&0x03) != 0 );

    if (whichram == 0)
        *recorder = 1;
    else
        *recorder = 3;

    while( ((*recorder)&0x03) != 0x01 );

    if (whichram == 0)
        *recorder = 0;
    else
        *recorder = 2;
}

u16 calcrc(unsigned char *ptr, int count)
{
    int crc;
    char i;

    crc = 0;
    while (--count >= 0)
    {
        crc = crc ^ (int) *ptr++ << 8;
        i = 8;
        do
        {
            if (crc & 0x8000)
                crc = crc << 1 ^ 0x1021;
            else
                crc = crc << 1;
        } while(--i);
    }
    return (crc);
}

void saa_write(u08 address, u08 subaddress, u08 data)
{
  i2cm_send_start();
  i2c_wait_for_ready();
  i2cm_send_address(address & 0xfe);
  i2c_wait_for_ready();
  i2cm_send_byte(subaddress);
  i2c_wait_for_ready();
  i2cm_send_byte(data);
  i2c_wait_for_ready();
  i2cm_send_stop();
}

u08 saa_read(u08 address, u08 subaddress)
{
  u08 received_byte;
  i2cm_send_start();
  i2c_wait_for_ready();
  i2cm_send_address(address & 0xfe);
  i2c_wait_for_ready();
  i2cm_send_byte(subaddress);
  i2c_wait_for_ready();
  i2cm_send_start();
  i2c_wait_for_ready();
  i2cm_send_address(address | 0x01);
  i2c_wait_for_ready();
  i2cm_want_last_byte();
  i2c_wait_for_ready();
  i2cm_get_received_byte(&received_byte);
  i2c_wait_for_ready();
  i2cm_send_stop();
  return received_byte;
}

int main(void)
{
    u08 i=0;
    u08 k,t;
    u16 h,s,l;
    u32 hop;
    u16 hep;
    u32 j=0;
    u08 tab[0x20]={0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x6C, 0x6C, 0x88, 0x01, 0x80, 0x47, 0x40, 0x00, 0x01, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

    unsigned char *entree = (unsigned char *) (0x1F00 + 30);
    unsigned char *test = (unsigned char *) (0x1F00 + 10);
    unsigned char *sortie = (unsigned char *) (0x1F00 + 31);
    unsigned char *ram = (unsigned char *) (0x1F00);
    unsigned char *pages = (unsigned char *) (0x1FFF);
    unsigned char *access = (unsigned char *) (0x1FFE);
    u16 *ram16 = (u16 *) (0x1F00);
    volatile u08 * const recorder = (volatile u08 *) (0x1F1D);
    volatile u08 * const recorderC = (volatile u08 *) (0x1F1C);

    unsigned char *page = (unsigned char *) (0x8000);

    volatile u16 *rgb = (volatile u16*) (0x1F00 + 11);
    volatile u32 *hsl = (volatile u32*) (0x1F00 + 11);

    u08 * const test_val = (u08 *) (0x1F00 + 13);
    u08 * const sync_val = (u08 *) (0x1F00 + 14);
    u08 * const blank_val = (u08 *) (0x1F00 + 15);
    u08 * const sw_val = (u08 *) (0x1F00 + 16);

    volatile u16 * const donneeB1 = (volatile u16 *) (0x1F00 + 2);
    u08 * const fifoB_add = (u08 *) (0x1F00 + 23);
    u08 * const request_fifoB = (u08 *) (0x1F00 + 21);
    volatile u08 * const fifoB_granted = (volatile u08 *) (0x1F00 + 5);
    volatile u08 * const statusfifoB = (volatile u08 *) (0x1F00 + 7);
    volatile u08 * const statuschoixB = (volatile u08 *) (0x1F00 + 8);
    u08 * const codeB = (u08 *) (0x1F00 + 6);
    u08 * const tailleB = (u08 *) (0x1F00 + 7);
    u08 * const codeB_write = (u08 *) (0x1F00 + 10);
    u08 * const codeB_select = (u08 *) (0x1F00 + 27);

    sei();
    uart_init();  

    wait_ms(100);

    // pour faire marcher printf 
    fdevopen((int(*)(char))uart0_send,(int(*)(void))uart0_recv,0);

    printf("Cam-ass-ultra has Booted !\r\n"); 
 
    i2cm_init();
    printf(" i2c initialise\r\n");
    
    for (i=0; i<0x20; i++)
        saa_write(0x48,i,tab[i]);

    for (i=0; i<0x20; i++)
        saa_write(0x4A,i,tab[i]);

    for (i=0; i<0x20; i++)
        if (saa_read(0x49,i) != tab[i]) printf("E:%i\r\n", i);

    *access = 0;

    printf("test = %2x\r\n", *test);
    printf("entree = %2x\r\n", *entree);
    *sortie = 0xAA;
    printf("test = %2x\r\n", *test);
    printf("entree = %2x\r\n", *entree);
    *sortie = 0x55;
    printf("entree = %2x\r\n", *entree);
    *sortie = 0x00;
    printf("entree = %2x\r\n", *entree);
    *sortie = 0xFF;
    printf("entree = %2x\r\n", *entree);

    *access=1;
    *pages = 0;
    while(*access != 0xF1) { uart0_send('x'); wait_ms(10); }

    hep=0;
    do
    {
    //l = (j&0x0000003F) << 10;
    //s = (j&0x00007F00) << 1;
        *rgb = hep;
        j = *hsl;
        ram16 = (u16*)mem2add(BASE_RAMV+2*(u32)hep);
        h = (j&0x01FF0000) >> 16;
        *ram16 = (u16)h;
if ( (hep > 0x3fff) && (hep < 0x400f) )
  printf("%04x,%04x@%04x ", hep, *ram16, ram16);
        hep++;
    } while(hep!=0);

    *pages = 0;
    for (hop=0; hop<=0x000f; hop++)
    {
//        *rgb = hop;
//        j = *hsl;
        ram16 = (u16*)mem2add(BASE_RAMV+2*hop);
        printf("%04x.", *ram16);
//        h = ((j&0x01FF0000) >> 9)&0xFF80;
//        printf("%04x_", h);
    }
    printf("\r\n");

    *sync_val = 0;
    *blank_val = 77;
    *sw_val = 0x84|0x40;

    set_seuilsB(0, 0, 255, 0, 255, 2, 1);
    set_seuilsB(4, 0, 255, 0, 255, 2, 1);
    set_seuilsB(2, 0, 255, 0, 255, 2, 1);
    set_seuilsB(3, 0, 255, 0, 255, 2, 1);
    set_seuilsB(5, 0, 255, 0, 255, 2, 1);
    set_seuilsB(1, 143, 165, 0, 255, 20, 32);
    set_seuilsB(6, 29, 48, 0, 255, 100, 32);

    *tailleB = 0xF3;

for (i=0; i<64; i++)
{
    *codeB_write = 0;
    *codeB_select = i;
    *codeB = 0x16;
    *codeB_write = 1;
    *codeB_write = 0;
}

while(1)
{
    *fifoB_add = 0;
    printf("%i!\r\n", *fifoB_granted);
    *request_fifoB = 1;
    while(*fifoB_granted == 0)
    {
        printf("(%02x) ", *statusfifoB);
        wait_ms(100);
    }

    set_cross(125, 72);

    printf("%i (%02x)!\r\n", *fifoB_granted, *statusfifoB);
    uart0_send('=');
    for (k=0; k<20; k++)
    {
        printf("%02x: ",k);
        for (i=0; i<4; i++)
        {
            t = i+4*k;
            *fifoB_add = t;
            printf("%03i ", *donneeB1);
        }
        printf("\r\n");
    }
    *request_fifoB = 0;
for (i=0; i<20; )
{
k = *statusfifoB;
t = *statuschoixB;
if (k!=0)
{
i++;
//printf("%02x(%02x)_", k,t);
}
}
printf("\r\n");
    wait_ms(1000);
}


    *sync_val = 0;
    *blank_val = 77;
    *sw_val = 0x85;


while(1);
{
*sw_val = 0xFF;
    i=0;
    *sync_val = i;
    *blank_val = i;
    *test_val = i;
    wait_ms(2000);
uart0_send('-');
printf("%i ", i);
    i=0xFF;
    *sync_val = i;
    *blank_val = i;
    *test_val = i;
printf("%i ", i);
wait_ms(2000);
}

    set_seuilsB(0, 0, 255, 0, 255, 2, 1);
    set_seuilsB(1, 0, 255, 0, 255, 2, 1);
    set_seuilsB(2, 0, 255, 0, 255, 2, 1);
    set_seuilsB(3, 0, 255, 0, 255, 2, 1);
    set_seuilsB(5, 0, 255, 0, 255, 2, 1);
    set_seuilsB(4, 143, 165, 0, 255, 10, 22);
    set_seuilsB(6, 29, 48, 0, 255, 100, 32);

    i=0;
    while (1)
    {
        //*sync_val = i;
        //*blank_val = i;
        //*image_val = i;
        wait_ms(2000);
        i++;


    }

    printf("Sending hue table\r\n");
    xmodem_send(BASE_RAMV, 0x20000);

    *access = 0;

    start_acq(recorder, 0);
    start_acq(recorderC, 1);

    while(((*recorder)&0x03) != 0); // on attend qu'il ait fini
    while(((*recorderC)&0x03) != 0);

    printf("\r\n");

    hep = 0x0809;
    *rgb = hep;
    j = *hsl;
    printf("rgb = %04x ; hsl = %lx\r\n", hep, j);
    l = (j&0x0000003F);
    s = (j&0x00007F00) >> 8;
    h = (j&0x01FF0000) >> 16;
    printf("h = %04x, s = %04x, l = %04x\r\n", (u16)h, (u16)s, (u16)l);

    *access = 1;
    printf(":%i:\r\n", *access);

    xmodem_send(BASE_RAMV, (u32)210*1024*2); // une trame complete

    wait_ms(1000);

    xmodem_send(BASE_RAMT, (u32)210*1024*2); // une trame complete

    wait_ms(1000);

    for (j=0x1F00; j<=0x20FF; j++)
    {
        ram = j;
        printf("%02x.", *ram);
        if (!((j+1)%16)) printf("\r\n");
    }

    for (i=0; i<0x1F;i++)
    {
        ram = (unsigned char *)mem2add(BASE_RAMV+i);
        printf("%02x?%c!", *ram, *ram);
    }

    printf("\r\n");

    printf("hop !\r\n");
    //xmodem_send(BASE_RAMV, 32);

    i=0;
    for (j=0x8000; j<=0x801F; j++)
    {
        ram = j;
        *ram=0x44+i;
        i++;
    }

    for (j=0x8000; j<=0x801F; j++)
    {
        ram = j;
        printf("%02x.", *ram);
    }
    printf("\r\n");

    for (j=0x8100; j<=0x810F; j++)
    {
        ram = j;
        printf("%02x.", *ram);
    }
    printf("\r\n");

    for (j=0x8000; j<=0x82FF; j++)
    {
        ram = j;
        printf("%02x.", *ram);
        if (!((j+1)%16)) printf("\r\n");
    }

    *access = 0;
    *recorder = 1;
    *recorder = 0;
    do
    {
        j = *recorder;
        printf("%02x.", j);
        wait_ms(1000);
    } while(j!=0);

printf("\r\nok!\r\n");
    do
    {
        j = *recorder;
        printf("%02x.", j);
        wait_ms(1000);
    } while(1);
    *pages = 0;
    printf("cypress = %2x\r\n", *page);
    *page = 0x77;
    printf("cypress = %2x\r\n", *page);
    *page = 0x44;
    printf("cypress = %2x\r\n", *page);

    *pages = 2;
    *page = 0x33;
    printf("cypress = %2x\r\n", *page);
    *page = 0x66;
    printf("cypress = %2x\r\n", *page);

    *pages = 0;
    printf("cypress = %2x\r\n", *page);


    while (1)
        uart0_send(uart0_recv());

    return 0;
}

u08 xmodem_send(u32 memory_address, u32 taille)
{
    unsigned char *buffer;
    u08 i;
    u08 bloc_num;
    unsigned char octet;
    u16 crc;
    u32 nombre;
    unsigned char buf2[128];

    printf("Waiting to send %lu bytes\r\n", taille);

    if (uart0_recv() != 'C') return 1;

    bloc_num = 1;
    nombre = 0;

    do
    {
       uart0_send(SOH);
       uart0_send(bloc_num);
       uart0_send(255-bloc_num);
       for (i=0; i<128; i++)
       {
           if (nombre <= taille)
           {
               buffer = (unsigned char *)mem2add(memory_address);
               octet = *buffer;
           } else {
               octet = CTRLZ;
           }
           memory_address++;
           uart0_send(octet);
           buf2[i] = octet;
           nombre++;
       }
       crc = calcrc(buf2,128);
       uart0_send((u08)(crc>>8));
       uart0_send((u08)(crc & 0x00FF));

       octet = uart0_recv();
       if (octet == ACK)
       {
           bloc_num++;
           //if (bloc_num == 255) bloc_num=1;
       } else {
           memory_address -= 128;
           nombre -= 128;
       }
    } while (nombre <= taille);
    uart0_send(EOT);
    uart0_recv();
    return 0;
}


