⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iopic18.c

📁 HID汽车大灯安定器,应用现在的安定器上,有多种保护功能
💻 C
字号:
/********************************************************************/
/********************************************************************/
/*****                                                          *****/
/*****        L A B C E N T E R    E L E C T R O N I C S        *****/
/*****                                                          *****/
/*****              PROTEUS VSM TINY CHESS SAMPLE               *****/
/*****                                                          *****/
/*****                     PIC18 I/O Module                     *****/
/*****                                                          *****/
/********************************************************************/
/********************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include "pic18.h"
#include "chess.h"

// LCD Driver Routines
VOID lcd_cls ();
VOID lcd_blit (WORD addr, const BYTE *data, BYTE numbytes);
VOID lcd_wrcmd (BYTE cmd);
VOID lcd_wrcmd1 (BYTE cmd, BYTE arg);
VOID lcd_wrcmd2 (BYTE cmd, WORD arg);

// Keypad Scanner
BYTE scankeypad ();
VOID sleep (INT msecs);
VOID tone (WORD period, WORD cycles);

// LCD Command Codes
#define LCD_CURSOR	0x21
#define LCD_OFFSET   	0x22
#define LCD_ADDRESS	0x24
#define LCD_TEXTHOME	0x40
#define LCD_TEXTAREA    0x41
#define LCD_GFXHOME	0x42
#define LCD_GFXAREA	0x43
#define LCD_ORMODE	0x80
#define LCD_XORMODE	0x81
#define LCD_ANDMODE	0x83
#define LCD_ATTRMODE	0x84
#define LCD_DISPLAY	0x90
#define LCD_CLINES	0xA0
#define LCD_AUTOWRITE	0xB0
#define LCD_AUTOREAD	0xB1
#define LCD_AUTORESET   0xB2
#define LCD_WRITEINC	0xC0
#define LCD_READINC	0xC1
#define LCD_WRITEDEC	0xC2
#define LCD_READDEC	0xC3
#define LCD_SCREENPEEK	0xE0
#define LCD_SCREENCOPY  0xE8
#define LCD_BITSET	0xF0

// Location of LCD Hardware (PORT A values)
#define LCD_STATUS      0x09
#define LCD_COMMAND     0x0A
#define LCD_DATA        0x02
#define LCD_DONE        0x0F

// Location of Chess Piece Bitmaps (in pieces.c)
extern const BYTE LCD_BITMAPS[];

// Number of timer ticks for flashing piece
#define FLASHTICKS 30

/*********************************************************************
**** Panel Interface Fuctions ****
*********************************/

VOID panel_init ()
 { // Initialize the I/O Ports and other stuff:
   PORTA = PORTB = PORTC = PORTD = 0xFF;
   TRISA = TRISC = TRISE = 0;
   RBPU = 0;
   
   // Initialize the debug console:
   SPEN = 1;
   CREN = 1;
   SPBRG = 0x19;   // 19200 Baud @ 8MHz
   TXSTA = 0xA4;   // CSRC/TXEN (Internal clock, 8 bit mode, Async operation, High Speed)
   

   // Initialize the main timer - prescaler = 8
   // TMSK2 = 2;
   
   printf("\nProteus VSM Tiny Chess\n");
 
   // Graphics screen has 32 bytes per row, and resides at address 0
   lcd_wrcmd2(LCD_GFXHOME,  0x0000);
   lcd_wrcmd2(LCD_GFXAREA, 32);
   lcd_wrcmd2(LCD_TEXTHOME, 0x2000);
   lcd_wrcmd2(LCD_TEXTAREA, 32);
   lcd_wrcmd2(LCD_OFFSET,   0x3000>>11);

   // Load custom graphic for a black square
   lcd_wrcmd2(LCD_ADDRESS,  0x3400);
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);   
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);
   lcd_wrcmd1(LCD_WRITEINC, 0xFF);


   // Enable text and graphics modes, with XOR mode
   lcd_wrcmd(LCD_DISPLAY+0x0C); 
   lcd_wrcmd(LCD_XORMODE);   

 }

VOID panel_cls (VOID)
// Draw an empty board
 { COORD row, col;

   lcd_cls();

   for (row=0; row<32; row += 1)
      for (col=0; col<32; col += 4)
         if ((row & 4) ^ (col & 4))         
          { WORD addr = 0x2000 + row*32 + col;
            lcd_wrcmd2(LCD_ADDRESS, addr);
            lcd_wrcmd1(LCD_WRITEINC, 128);
            lcd_wrcmd1(LCD_WRITEINC, 128);
            lcd_wrcmd1(LCD_WRITEINC, 128);
            lcd_wrcmd1(LCD_WRITEINC, 128);
          }

 }
        
VOID panel_draw (COORD row, COORD col, PIECE p)
// Draw  piece p at location loc.
 { const BYTE *sprite = LCD_BITMAPS;
   row = (CHAR)7-row;                               // Adjust row to board matrix.  
   if ((row & 1) ^ (col & 1))
    { if ((p & 8) == WHITE)
         sprite += (p & 7) * 4 + 0x0400;            // White piece on black square
      else
         sprite += (p & 7) * 4 + 0x0000;            // Black piece on black square
    }
   else
    { if ((p & 8) == WHITE)
         sprite += (p & 7) * 4 + 0x0000;            // White piece on white square
      else
         sprite += (p & 7) * 4 + 0x0400;            // Black piece on white square
    }
   panel_blit(row, col, sprite);
 }
 
VOID panel_blit (COORD row, COORD col, const BYTE *sprite)
// Low level function to draw specified sprite onto the board.
 { WORD addr = row * 1024 + col * 4;
   INT i;
   for (i=0; i<32; ++i)
    { lcd_blit(addr, sprite, 4);
      addr += 32;
      sprite += 32;
    }         
 }

BOOL panel_getmove (LOC from, LOC to)
// Polls for chess move, returns TRUE when move entered.
 { BYTE key, fdelay, fstate=0;
   PIECE p;
   
   // seed a random number generator after first user move.
   if (movecount == 1) srand (TMR1);

   if (key=scankeypad(), key == 0xFF)
      return FALSE;

   // Store the 'from' position
   from[0] = (key / 8);
   from[1] = key % 8;
 
   // Check moving correct piece.
   p = board[7-from[0]][from[1]];
   if (p == EMPTY || p & BLACK)
      return FALSE;
   

   // Wait for key release
   fdelay = 0;
   while (scankeypad() != 0xFF)
    { if (fdelay-- == 0)
       { panel_invert(from, fstate ^= 1);
         fdelay = FLASHTICKS;
       }
    }
     
   // Wait for key press
   while ((key=scankeypad()) == 0xFF)
    { if (fdelay-- == 0)
       { panel_invert(from, fstate ^= 1);
         fdelay = FLASHTICKS;
       }
    }

   // Clear any left over inversion       
   if (fstate)
      panel_invert(from, FALSE);

   to[0] = key / 8;
   to[1] = key % 8;    

   // Convert rows from Physical Layout coords to internal
   // board matrix. 
   from[0] = 7 - from[0];
   to[0]   = 7 - to[0];

   // Wait for key release
   while (scankeypad() != 0xFF)
      ;

   return from[0] != to[0] || from[1] != to[1];
 }

VOID panel_invert (LOC loc, BYTE flag)
// Set the graphical inversion state of the specified square.
 { WORD addr = 0x2000 + loc[0]*128 + loc[1]*4;
   BYTE i, data;
   
   if ((loc[0] & 1) ^ (loc[1] & 1))         
      data = flag ? 0 : 128;  // Invert/normal for black square
   else
      data = flag ? 128 : 0;  // Invert/normal for white square 
   
   for (i=0; i<4; ++i)
    { lcd_wrcmd2(LCD_ADDRESS, addr);
      lcd_wrcmd1(LCD_WRITEINC, data);
      lcd_wrcmd1(LCD_WRITEINC, data);
      lcd_wrcmd1(LCD_WRITEINC, data);
      lcd_wrcmd1(LCD_WRITEINC, data);
      addr += 32;
    }
 }

/*********************************************************************
**** Low Level LCD Driver ****
*****************************/

VOID lcd_cls ()
// Clear graphics and text areas.
 { INT i;
   lcd_wrcmd(LCD_DISPLAY+0x00);
   lcd_wrcmd2(LCD_ADDRESS, 0);
   lcd_wrcmd(LCD_AUTOWRITE);
   for (i=0; i<0x2400; ++i)
    { BYTE status;
      TRISD = 0xFF;
      do
       { PORTA = LCD_STATUS;
         asm("nop");
         status = PORTD;
         PORTA = LCD_DONE;
       } while ((status & 8) == 0);
      PORTD = 0;
      TRISD = 0;
      PORTA = LCD_DATA;
      PORTA = LCD_DONE;
    }    
   lcd_wrcmd(LCD_AUTORESET); 
   lcd_wrcmd(LCD_DISPLAY+0x0C);
 }
   
VOID lcd_blit (WORD addr, const BYTE *data, BYTE numbytes)
// Copy a sprite bitmap to the display
 { lcd_wrcmd2(LCD_ADDRESS, addr);
   lcd_wrcmd(LCD_AUTOWRITE);
   while (numbytes--)
    { BYTE status;
      TRISD = 0xFF;
      do
       { PORTA = LCD_STATUS;
         asm("nop");
         status = PORTD;
         PORTA = LCD_DONE;
       } while ((status & 8) == 0);
      PORTD = *data++;
      TRISD = 0;
      PORTA = LCD_DATA;
      PORTA = LCD_DONE;
    }
   lcd_wrcmd(LCD_AUTORESET);
 }



VOID lcd_wrcmd (BYTE cmd)
// Send a simple command
 { BYTE status; 
   TRISD = 0xFF;
   do
    { PORTA = LCD_STATUS;
      asm("nop");
      status = PORTD;
      PORTA = LCD_DONE;
    } while ((status & 1) == 0);
   PORTD = cmd;
   TRISD = 0;
   PORTA = LCD_COMMAND;
   PORTA = LCD_DONE;
 }

VOID lcd_wrcmd1 (BYTE cmd, BYTE data)
// Send a command with a byte argument
 { BYTE status;
   TRISD = 0xFF;
   do
    { PORTA = LCD_STATUS;
      asm("nop");
      status = PORTD;
      PORTA = LCD_DONE;
    } while ((status & 2) == 0);
   PORTA = LCD_DATA;
   PORTD = data;
   TRISD = 0;
   PORTA = LCD_DONE;

   TRISD = 0xFF;
   do
    { PORTA = LCD_STATUS;
      asm("nop");
      status = PORTD;
      PORTA = LCD_DONE;
    } while ((status & 1) == 0);
   PORTA = LCD_COMMAND;
   PORTD = cmd;
   TRISD = 0;
   PORTA = LCD_DONE;
 }

VOID lcd_wrcmd2 (BYTE cmd, WORD arg)
// Send a command with a word argument
 { BYTE status;
   TRISD = 0xFF;
   do
    { PORTA = LCD_STATUS;
      asm("nop");
      status = PORTD;
      PORTA = LCD_DONE;
    } while ((status & 2) == 0);
   PORTA = LCD_DATA;
   PORTD = arg & 0xFF;
   TRISD = 0;
   PORTA = LCD_DONE;

   TRISD = 0xFF;
   do
    { PORTA = LCD_STATUS;
      asm("nop");
      status = PORTD;
      PORTA = LCD_DONE;
    } while ((status & 2) == 0);
   PORTA = LCD_DATA;
   PORTD = arg >> 8;
   TRISD = 0;
   PORTA = LCD_DONE;

   TRISD = 0xFF;
   do
    { PORTA = LCD_STATUS;
      asm("nop");
      status = PORTD;
      PORTA = LCD_DONE;
    } while ((status & 1) == 0);
   PORTA = LCD_COMMAND;
   PORTD = cmd;
   TRISD = 0;
   PORTA = LCD_DONE;
 }


/*********************************************************************
**** Sound Effects ****
**********************/

// The Tone Generator operates using the OC1 control mechanisms on
// pins PA3 and PA7.

VOID sound_yourmove ()
 { tone(100, 100);
//   tone(500, 200);
 }   

VOID sound_capture ()
 { tone(50, 100);
   tone(75, 75);
   tone(100, 50);
   sleep(200);
 }
     

VOID sound_illegal ()
 { tone(400, 100);
 }
 
VOID tone (WORD period, WORD cycles)
// Play a simple tone.
// Use Timer 0 (16 bit mode) for this purpose
 { LATC = 0x03;
   T0CON = 0x04;
   while (cycles--)
    { TMR0H = -period >> 8;
      TMR0L = -period & 0xFF;
      TMR0IF = 0;
      TMR0ON = 1;
      while (TMR0IF == 0)
         ;
      TMR0ON = 0;
      LATC ^= 0x03;
   }
 }

/*********************************************************************
**** Keyboard Scanner ****
*************************/

BYTE scankeypad ()
// Scan the keypad for a keypress.
// Return 0xFF for no press or the char pressed.
 { BYTE row,col,tmp;
   BYTE key=0xFF;

   for (col=0; col < 8; col++)
    { // Drive appropriate column low and read off the rows:
      PORTE = col;
      sleep(1); // allow settling time
      tmp = PORTB;
    
      // See if any row is active (low):
      for (row=0; row<8; ++row)
         if ((tmp & (1<<row)) == 0)
          { key = ((row)*8) + col;
            goto done;
          }
    }

   done: return key;
 }

VOID sleep (INT msecs)
// Sleep for specified number of milliseconds.
// We use Timer 0 on a 1/64 prescaler, assuming and its output compare latch for this purpose.
 { while (msecs--)
    { TMR0L = -32;
      TMR0IF = 0;
      T0CON = 0xC6;
      while (TMR0IF == 0)
          ;
      TMR0ON = 0;
    }
 }


/*********************************************************************
**** Stdio Output ****
*********************/

void putch(char value)
 { if (value == '\n')
      value = '\r';
   TXREG = value;
   while (TRMT == 0)
     ;
 }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -