URL
https://opencores.org/ocsvn/Aquarius/Aquarius/trunk
Subversion Repositories Aquarius
[/] [Aquarius/] [trunk/] [application/] [shc_pi/] [main.c] - Rev 12
Compare with Previous | Blame | View Log
//=============================== // Calculate Circular Constant Pi // (1024 figures) //------------------------------- // for VirtexE Evaluation Board // July.20 2003 Ver.1 //=============================== //====================================================== // Address Map //====================================================== // address sz wt wd device // 00000000-00001FFF 8K 0 32 ROM (code) // 00002000-00003DFF 6K 0 32 RAM (data) // 00003E00-00003FFF 512 0 32 RAM (stack) // // 00000000-0000FFFF 64K 0 32 RAM (shadow every 16KB) // 00010000-0001FFFF 64K 3 32 RAM (shadow every 16KB) // 00020000-0002FFFF 64K 0 16 RAM (shadow every 16KB) // 00030000-0003FFFF 64K 3 16 RAM (shadow every 16KB) // 00040000-ABCCFFFF (shadow RAM) // ABCD0000-ABCD00FF 256 3 32 PIO (shadow every 4B) // ABCD0100-ABCD01FF 256 3 32 UART(shadow every 4B) // ABCD0200-ABCD02FF 256 3 32 SYS (shadow every 8B) // ABCD0300-FFFBFFFF (shadow RAM) // FFFC0000-FFFCFFFF 64K 0 32 RAM (shadow every 16KB) // FFFD0000-FFFDFFFF 64K 3 32 RAM (shadow every 16KB) // FFFE0000-FFFEFFFF 64K 0 16 RAM (shadow every 16KB) // FFFF0000-FFFFFFFF 64K 3 16 RAM (shadow every 16KB) // //====================================================== // PORT OUTPUT //====================================================== // ABCD0000 : reserved // 31 30 29 28 27 26 25 24 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | | | | | | | | | // -----------------------------------------------; // // ABCD0001 : KEYYO (Key SCAN Y-axis out) // 23 22 21 20 19 18 17 16 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | | | | KY4 | KY3 | KY2 | KY1 | KY0 | // ----------------------------------------------- // // ABCD0002 : LCDCON (LCD Control Signal) // 15 14 13 12 11 10 9 8 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | | | | | | E | R/W | RS | // ----------------------------------------------- // // ABCD0003 : LCDOUT (Write Data to LCD) // 7 6 5 4 3 2 1 0 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | DW7 | DW6 | DW5 | DW4 | DW3 | DW2 | DW1 | DW0 | // ----------------------------------------------- // //====================================================== // PORT INPUT //====================================================== // ABCD0000 : reserved // 31 30 29 28 27 26 25 24 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | | | | | | | | | // -----------------------------------------------; // // ABCD0001 : KEYXI (Key SCAN X-axis in) // 23 22 21 20 19 18 17 16 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | | | | KX4 | KX3 | KX2 | KX1 | KX0 | // ----------------------------------------------- // // ABCD0002 : reserved // 15 14 13 12 11 10 9 8 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | | | | | | | | | // ----------------------------------------------- // // ABCD0003 : LCDIN (Read Data from LCD) // 7 6 5 4 3 2 1 0 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | DR7 | DR6 | DR5 | DR4 | DR3 | DR2 | DR1 | DR0 | // ----------------------------------------------- // //====================================================== // UART: SASC (www.opencores.com) // Simple Asynchronous Serial Communication Device //====================================================== // ABCD0100 : UARTBG0 Baud Rate Generator Div0 (R/W) // 31 30 29 28 27 26 25 24 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | B07 | B06 | B05 | B04 | B03 | B02 | B01 | B00 | // ----------------------------------------------- // // ABCD0101 : UARTBG1 Baud Rate Generator Div1 (R/W) // 23 22 21 20 19 18 17 16 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | B17 | B16 | B15 | B14 | B13 | B12 | B11 | B10 | // ----------------------------------------------- // // ABCD0102 : UARTCON (TXF=full_o, RXE=empty_o) (R only) // 15 14 13 12 11 10 9 8 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | | | | | | | TXF | RXE | // ----------------------------------------------- // // ABCD0103 : UARTTXD(W only)/UARTRXD(R only) // 7 6 5 4 3 2 1 0 // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // | TR7 | TR6 | TR5 | TR4 | TR3 | TR2 | TR1 | TR0 | // ----------------------------------------------- // //====================================================== // System Controller // Interrupt and Exception Controller //====================================================== // ABCD0200 : INTCTL Interrupt Control (32bit R/W only) // 31 30 29 28 27 26 25 24 // ----------------------------------------------- // |E_NMI|E_IRQ|E_CER|E_DER|E_MRS| |TMRON|BRKON| // ----------------------------------------------- // 23 22 21 20 19 18 17 16 // ----------------------------------------------- // |ILVL3|ILVL2|ILVL1|ILVL0|IVEC7|IVEC6|IVEC5|IVEC4| // ----------------------------------------------- // 15 14 13 12 11 10 9 8 // ----------------------------------------------- // |IVEC3|IVEC2|IVEC1|IVEC0|TMR11|TMR10|TMR09|TMR08| // ----------------------------------------------- // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // |TMR07|TMR06|TMR05|TMR04|TMR03|TMR02|TMR01|TMR00| // ----------------------------------------------- // bit31: E_NMI Emulate NMI Interrupt (W only) // bit30: E_IRQ Emulate IRQ Interrupt (W only) // bit29: E_CER Emulate CPU Address Error (W only) // bit28: E_DER Emulate DMA Address Error (W only) // bit27: E_MRS Emulate Manual Reset (W only) // bit26: reserved // bit25: TMRON INTTMR OFF/ON (0:OFF, 1:ON) // bit24: BRKON Address Break(NMI) OFF/ON (0:OFF, 1:ON) // bit23: ILVL3 IRQ ILevel 3 // bit22: ILVL2 IRQ ILevel 2 // bit21: ILVL1 IRQ ILevel 1 // bit20: ILVL0 IRQ ILevel 0 // bit19: IVEC7 IRQ Vector 7 // bit18: IVEC6 IRQ Vector 6 // bit17: IVEC5 IRQ Vector 5 // bit16: IVEC4 IRQ Vector 4 // bit15: IVEC3 IRQ Vector 3 // bit14: IVEC2 IRQ Vector 2 // bit13: IVEC1 IRQ Vector 1 // bit12: IVEC0 IRQ Vector 0 // bit11: TMR11 (12 bit interval timer to generate IRQ) // ... // bit 0: TMR00 (12 bit interval timer to generate IRQ) // // ABCD0204 : BRKADR Break Address (16bit R/W only) // 15 14 13 12 11 10 9 8 // ----------------------------------------------- // |ADR15|ADR14|ADR13|ADR12|ADR11|ADR10|ADR09|ADR08| // ----------------------------------------------- // 7 6 5 4 3 2 1 0 // ----------------------------------------------- // |ADR07|ADR06|ADR05|ADR04|ADR03|ADR02|ADR01|ADR00| // ----------------------------------------------- // bit15: ADR15 Break Address15 // ... // bit00: ADR00 Break Address00 // #include "common.h" #define MAXFIGURE ((1024/4)+2) // should be (N*8)+2 to display correctly //================= // Define Functions //================= void lcd_message(unsigned char pos, unsigned char *pstr); void lcd_disp(unsigned char chr); void lcd_pos(unsigned char pos); void lcd_ready(void); unsigned char lcd_rd(int); void lcd_wr(int, unsigned char); void lcd_init(void); void waitNms(unsigned char n); unsigned char key_scan(); unsigned char key_wait_on(void); void key_wait_off(void); void longadd(unsigned short *a, unsigned short *b, unsigned short *c); void longsub(unsigned short *a, unsigned short *b, unsigned short *c); int longdiv(unsigned short *a, unsigned short b, unsigned short *c); void calc_pi(void); void disp_oct4(unsigned short x); void disp_pi(void); //----------------------------------- // Work data for Circular Constant Pi //----------------------------------- unsigned short PI[MAXFIGURE]; unsigned short T1[MAXFIGURE]; unsigned short T2[MAXFIGURE]; unsigned short T3[MAXFIGURE]; //============= // Main Routine //============= void main_sh(void) { unsigned char mes[] = "Calculating....."; lcd_init(); lcd_message(0, mes); calc_pi(); disp_pi(); } //------------------------------------------------- // Calculate the Circular Constant Pi //------------------------------------------------- // (1) Matin's formula // PI/4 = 4*arctan(1/5) - arctan(1/239) // PI = 16*arctan(1/5) - 4*arctan(1/239) // Here, arctan(1/p) = 1/p - 1/(3*p^3) + 1/(5*p^5) - 1/(7*p^7) + ... // Then, // PI = (16*1/5 - 4*1/239) // - (16*1/3*5^3 - 4*1/3*239^3) // + (16*1/5*5^5 - 4*1/5*239^5) // - (16*1/7*5^7 - 4*1/7*239^7) // +... // = (1/1)*(16*5/(5*5)^1 - 4*239/(239*239)^1) // - (1/3)*(16*5/(5*5)^2 - 4*239/(239*239)^2) // + (1/5)*(16*5/(5*5)^3 - 4*239/(239*239)^3) // - (1/7)*(16*5/(5*5)^4 - 4*239/(239*239)^4) // +... //------------------------------------------------- // (2) Define Arrays for Long Figure Number // Each element has Octal 4 figures. // PI[] : Value to be converged to Pi // T1[] : (16* 5)/( 5* 5)^n (n=1...) // T2[] : ( 4*239)/(239*239)^n (n=1...) // T3[] : (-1)*(n+1)*(1/(2n-1))*(T1[]-T2[]) //------------------------------------------------- // (3) Example // n TI[0] TI[1] T2[0] T2[1] T3[0] T3[1] PI[0] PI[1] // 0 0080 0000 0956 0000 0000 0000 0000 0000 // 1 0003 2000 0000 0167 0003 1833 0003 1833 (+) // 2 0000 1280 0000 0000 0000 0426 0003 1407 (-) // 3 0000 0051 0000 0000 0000 0010 0003 1417 (+) // 4 0000 0002 0000 0000 0000 0000 0003 1417 (-) //------------------------------------------------- void calc_pi(void) { int i; int converged; //----------- // Initialize //----------- converged = 0; for (i=0; i<=MAXFIGURE-1; i++) { PI[i] = 0; T1[i] = 0; T2[i] = 0; T3[i] = 0; } T1[0] = 16*5; T2[0] = 4*239; //----------------------------- // repeat until being converged //----------------------------- i = 1; while (converged == 0) { //------------- // Make T1 & T2 //------------- longdiv(T1, 25, T1); longdiv(T2, 239, T2); longdiv(T2, 239, T2); //-------- // Make T3 //-------- longsub(T1, T2, T3); converged = longdiv(T3, (unsigned short)(2*i-1), T3); //if (converged) break; //----------------- // Accumulate to PI //----------------- if (i%2 != 0) longadd(PI, T3, PI); else longsub(PI, T3, PI); //------------ // Increment i //------------ i++; } } //--------- // Long Add //--------- void longadd(unsigned short *a, unsigned short *b, unsigned short *c) { int i; unsigned short carry; carry = 0; for (i = MAXFIGURE-1; i >= 0; i--) { *(c+i) = *(a+i) + *(b+i) + carry; if (*(c+i) < 10000) carry = 0; else { carry = 1; *(c+i) = *(c+i) - 10000; } } } //--------- // Long Sub //--------- void longsub(unsigned short *a, unsigned short *b, unsigned short *c) { int i; unsigned short borrow; unsigned short temp; borrow = 0; for (i = MAXFIGURE-1; i >= 0; i--) { temp = *(b+i) + borrow; if (*(a+i) >= temp) { *(c+i) = *(a+i) - temp; borrow = 0; } else { *(c+i) = 10000 + *(a+i) - temp; borrow = 1; } } } //--------- // Long Div //--------- int longdiv(unsigned short *a, unsigned short b, unsigned short *c) { int i; int conv; unsigned long al, bl, cl, dvd, rem; conv = 1; rem = 0; for (i = 0; i <= MAXFIGURE-1; i++) { al = (unsigned long) *(a+i); bl = (unsigned long) b; cl = (unsigned long) *(c+i); dvd = al + rem; cl = dvd / b; rem = (dvd - cl * bl) * 10000; if (cl > 0) conv = 0; *(c+i) = (unsigned short) cl; } return conv; } //----------- // Display Pi //----------- void disp_pi(void) { unsigned char mes1[] = "Calculating DONE"; unsigned char mes2[] = "Constant Pi = 3."; int i, j; while(1) { lcd_message( 0, mes1); lcd_message(16, mes2); key_wait_off(); key_wait_on(); // PI[MAXFIGURE-1] has error, so do not display. for (i = 0; i < (MAXFIGURE - 2) / 8; i++) { for (j = 0; j < 8; j++) { if (j == 0) lcd_pos(0); if (j == 4) lcd_pos(16); disp_oct4(*(PI + i*8 + j + 1)); } key_wait_off(); key_wait_on(); } } } //------------------- // Display Oct 4 digit //------------------- void disp_oct4(unsigned short x) { unsigned short d; d = x / 1000; x = x - d * 1000; lcd_disp((char)(d+0x30)); d = x / 100; x = x - d * 100; lcd_disp((char)(d+0x30)); d = x / 10; x = x - d * 10; lcd_disp((char)(d+0x30)); lcd_disp((char)(x+0x30)); } //**************************************************** //* * //* LCD Utilities * //* * //**************************************************** //======================================== // Print a Message from Current Position //---------------------------------------- // Input : pstr = message top address // Outpur : none //======================================== void lcd_message(unsigned char pos, unsigned char *pstr) { unsigned char *pmessage; lcd_pos(pos); pmessage = pstr; while (*pmessage) lcd_disp(*pmessage++); } //========================================== // Display One Character on Current Position //------------------------------------------ // Input : chr = display charcter // Output : none //========================================== void lcd_disp(unsigned char chr) { lcd_ready(); lcd_wr(DATA, chr); } //================================ // Set LCD Display Position //-------------------------------- // Input : pos = position // 1st line = 00-15 // 2nd line = 16-31 // Ouput : none //================================ void lcd_pos(unsigned char pos) { unsigned char phypos; phypos = pos % 32; if (phypos >= 16) phypos = (phypos - 16) + 64; phypos = phypos | 0x80; lcd_ready(); lcd_wr(INST, phypos); } //===================== // Wait until LCD ready //--------------------- // Input : none // Output : none //===================== void lcd_ready(void) { while ((lcd_rd(INST) & 0x80) == 0x80); } //================================= // LCD Read //--------------------------------- // Input : rs (0=Instr,1=Data) // Output : lcd_rd (Read Data) //================================= unsigned char lcd_rd(int rs) { int i; unsigned char dummy; unsigned char data; PORTO.LCDCON.BYTE = 0x02 | (rs & 0x01); // wait 60ns = 2cyc@20MHz dummy = PORTI.RESERVED_0; dummy = PORTI.RESERVED_0; PORTO.LCDCON.BYTE = 0x06 | (rs & 0x01); // wait 500ns = 10cyc@20MHz for (i = 0 ; i <= 10 ; i++) dummy = PORTI.RESERVED_0; data = PORTI.LCDIN; PORTO.LCDCON.BYTE = 0x02 | (rs & 0x01); // wait 500ns = 10cyc@20MHz for (i = 0 ; i <= 10 ; i++) dummy = PORTI.RESERVED_0; return(data); } //================================= // LCD Write //--------------------------------- // Input : rs (0=Instr,1=Data) // wd (Write Data) // Output : none //================================= void lcd_wr(int rs, unsigned char wd) { int i; unsigned char dummy; PORTO.LCDOUT = wd; PORTO.LCDCON.BYTE = 0x00 | (rs & 0x01); // wait 60ns = 2cyc@20MHz dummy = PORTI.RESERVED_0; dummy = PORTI.RESERVED_0; PORTO.LCDCON.BYTE = 0x04 | (rs & 0x01); // wait 500ns = 10cyc@20MHz for (i = 0 ; i <= 10 ; i++) dummy = PORTI.RESERVED_0; PORTO.LCDCON.BYTE = 0x00 | (rs & 0x01); // wait 500ns = 10cyc@20MHz for (i = 0 ; i <= 10 ; i++) dummy = PORTI.RESERVED_0; } //================== // LCD Initialize //------------------ // Input : none // Output : none //================== void lcd_init(void) { int i; unsigned char dummy; lcd_wr(INST, 0x30); // wait 4100us=82000cyc@20MHz for (i = 0 ; i < 82000 ; i++) dummy = PORTI.RESERVED_0; lcd_wr(INST, 0x30); // wait 100us=2000cyc@20MHz for (i = 0 ; i < 2000 ; i++) dummy = PORTI.RESERVED_0; lcd_wr(INST, 0x30); // set function (8bit, 2lines) lcd_ready(); lcd_wr(INST, 0x38); // display (disp on, cursor off, blink off) lcd_ready(); lcd_wr(INST, 0x0c); // clear lcd_ready(); lcd_wr(INST, 0x01); // entry mode (increment, no-shift) lcd_ready(); lcd_wr(INST, 0x06); } //**************************************************** //* * //* Key Utilities * //* * //**************************************************** //=================================== // Wait until Key On //----------------------------------- // Input : none // Output : key = pushed key code //=================================== unsigned char key_wait_on(void) { unsigned char key; while((key = key_scan()) == KEYNONE) waitNms(8); return(key); } //=================== // Wait until Key Off //------------------- // Input : none // Output : none //=================== void key_wait_off(void) { while(key_scan() != KEYNONE) waitNms(8); } //=================================== // Key Scan //----------------------------------- // Input : none // Output : key = pushed key code //=================================== unsigned char key_scan() { unsigned char keyx4; unsigned char keyx3; unsigned char keyx2; unsigned char keyx1; unsigned char keyx0; PORTO.KEYYO.BYTE = 0xef; // KEYY4 waitNms(1); keyx4 = PORTI.KEYXI.BYTE & 0x1f; PORTO.KEYYO.BYTE = 0xf7; // KEYY3 waitNms(1); keyx3 = PORTI.KEYXI.BYTE & 0x1f; PORTO.KEYYO.BYTE = 0xfb; // KEYY2 waitNms(1); keyx2 = PORTI.KEYXI.BYTE & 0x1f; PORTO.KEYYO.BYTE = 0xfd; // KEYY1 waitNms(1); keyx1 = PORTI.KEYXI.BYTE & 0x1f; PORTO.KEYYO.BYTE = 0xfe; // KEYY0 waitNms(1); keyx0 = PORTI.KEYXI.BYTE & 0x1f; switch(keyx4) { case 0x17 : return(KEYPUT); case 0x1b : return(KEYGET); case 0x1d : return(KEYRUN); case 0x1e : return(KEYUTL); } switch(keyx3) { case 0x0f : return(KEYADR); case 0x17 : return(KEYF); case 0x1b : return(KEYE); case 0x1d : return(KEYD); case 0x1e : return(KEYC); } switch(keyx2) { case 0x0f : return(KEYINC); case 0x17 : return(KEYB); case 0x1b : return(KEYA); case 0x1d : return(KEY9); case 0x1e : return(KEY8); } switch(keyx1) { case 0x0f : return(KEYDEC); case 0x17 : return(KEY7); case 0x1b : return(KEY6); case 0x1d : return(KEY5); case 0x1e : return(KEY4); } switch(keyx0) { case 0x0f : return(KEYDAT); case 0x17 : return(KEY3); case 0x1b : return(KEY2); case 0x1d : return(KEY1); case 0x1e : return(KEY0); } return(KEYNONE); } //================== // Wait n ms //------------------ // Input : n ms // Output : none //================== void waitNms(unsigned char n) { int i, j; unsigned char dummy; for (i = 0 ; i < n ; i++) { // 1ms = 20000 * 50ns (20MHz) for (j = 0 ; i <= 10000 ; i++) dummy = PORTI.RESERVED_0; } } //=============== // End of Program //===============