/* * sample.cpp --- Sample File for Handling IOSCMctl.cpp. * * This sample is for WindowsNT/2000/XP. * * Copyright (C) 2003 by mag44(M.Watanabe), all rights reserved. */ #include "stdafx.h" #include "ioscm.h" #include #include #include #include int data_port = 0x0378; /* typical output printer port */ int status_port = 0x0379; /* typical input printer port */ unsigned char mask = 0xFC; /* default bits X X X X X CS SI SCK */ // Change this address first, depending on your PC. //#define PRN_PORT (0x3bc) #define PRN_PORT (0x378) //---------------------------- // Wrapper Functions by kaoaru //---------------------------- int inportb(int dataport) { int ret; ret = _inp(dataport); return ret; } void outportb(int dataport,int mask) { _outp(dataport,mask); } //----------- // WP Control //----------- void WP_HIGH() { mask = mask | 0x08; // D3 HIGH outportb(data_port,mask); } void WP_LOW() { mask = mask & 0xF7; // D3 LOW outportb(data_port,mask); } /* AN75 Application Note www.xicor.com June, 2000 */ /*********************************************************************/ /* Turbo C code for interfacing Xicor second generation SPI serial */ /* EEPROMs to the Centronics parallel printer port. These devices */ /* include the X25160, X25320, X25640, X25642, and X25128. */ /* SCK is connected to D0, SI to D1, SO to BUSY, /CS to D2, and both */ /* /HOLD and /WP are assumed HIGH. */ /* */ /*********************************************************************/ void SCK_HIGH() { mask = mask | 0x01; /* forces SCK pin HIGH */ outportb(data_port,mask); } void SCK_LOW() { mask = mask & 0xFE; /* forces SCK pin LOW */ outportb(data_port,mask); } void SI_HIGH() { mask = mask | 0x02; /* forces SI pin HIGH */ outportb(data_port,mask); } void SI_LOW() { mask = mask & 0xFD; /* forces SI pin LOW */ outportb(data_port,mask); } unsigned char SO_SAMPLE() { unsigned char SO_value; SO_value = inportb(status_port) & 0x80; /* get value on SO pin */ /* and isolate */ SO_value = SO_value >> 7; /* shift to LSB */ SCK_HIGH(); /* provide clock */ SCK_LOW(); return(SO_value); } void CS_HIGH() { mask = mask | 0x04; /* forces CS pin HIGH */ outportb(data_port,mask); } void CS_LOW() { mask = mask & 0xFB; /* forces CS pin LOW */ outportb(data_port,mask); } /******************************************************************/ /* */ /* Routine transmits a databyte to the SPI memory. The databyte */ /* is passed to this routine directly when called. */ /* */ /******************************************************************/ void SEND_BYTE(unsigned char byte) { char count; for (count = 0; count <= 7; count++) { /* loop to pass each bit */ if ((byte & 0x80) == 0) /* is the bit LOW? */ SI_LOW(); else SI_HIGH(); byte = byte << 1; /* rotate to get next bit */ SCK_HIGH(); /* provide clock */ SCK_LOW(); } } /******************************************************************/ /* */ /* Routine receives a databyte from the SPI memory and passes it */ /* back to the calling routine as an unsigned char. */ /* */ /******************************************************************/ unsigned char GET_BYTE() { int count; unsigned char byte,temp; byte = 0; /* reset byte holder */ for (count = 0; count <= 7; count++) { /* loop to get each bit */ byte = byte << 1; /* rotate for next bit */ temp = SO_SAMPLE(); /* read SO pin */ if (temp == 0) byte = byte | 0x01; /* reconstruct current bit */ } return(byte); } /******************************************************************/ /* */ /* Set the WEL bit in the status register. */ /* */ /******************************************************************/ void WREN() { CS_LOW(); SEND_BYTE(0x06); /* WREN instruction */ CS_HIGH(); } /******************************************************************/ /* */ /* Reset the WEL bit in the status register. */ /* */ /******************************************************************/ void WRDI(){ CS_LOW(); SEND_BYTE(0x04); /* WRDI instruction */ CS_HIGH(); } /******************************************************************/ /* */ /* Read the status register. */ /* */ /******************************************************************/ unsigned char RDSR() { unsigned char byte; CS_LOW(); SEND_BYTE(0x05); /* RDSR instruction */ byte = GET_BYTE(); /* retrieve SR databyte */ CS_HIGH(); return(byte); } /******************************************************************/ /* */ /* Poll the status of the WIP bit to determine the early */ /* completion of a nonvolatile write cycle. */ /* */ /******************************************************************/ void WIP_POLL() { unsigned char byte; byte = 0; /* reset byte holder */ do { byte = RDSR(); /* read the SR */ byte = byte & 0x01; /* isolate WIP bit */ } while (byte != 0); /* repeat until WIP bit is LOW */ } /******************************************************************/ /* */ /* Write the status register with the value passed to the routine */ /* in the following format: WPEN|x|x|x|BP1|BP0|x|x */ /* */ /******************************************************************/ void WRSR(unsigned char byte) { WREN(); /* set WEL bit */ byte = byte & 0x8C; /* force other bits to 0 */ CS_LOW(); SEND_BYTE(0x01); /* WRSR instruction */ SEND_BYTE(byte); /* send SR data byte */ CS_HIGH(); WIP_POLL(); /* poll for completion of write cycle */ } /*******************************************************************/ /* */ /* Routine to read multiple consecutive bytes from the SPI memory. */ /* The specified number of bytes (no_bytes) are read starting from */ /* location (addr) and are stored to the array pointed to by */ /* (*bytes). */ /* */ /*******************************************************************/ void READ_SPI(int no_bytes,int addr,unsigned char *bytes) { unsigned char addrhi,addrlo; int n; CS_LOW(); SEND_BYTE(0x03); /* READ instruction */ addrhi = ((addr & 0x0FF00) >> 8); /* decompose addr into 2 bytes */ addrlo = addr & 0x0FF; SEND_BYTE(addrhi); /* send 2 address bytes */ SEND_BYTE(addrlo); for (n = 0; n < no_bytes; n++) { /* loop to read bytes */ bytes[n]=GET_BYTE(); /* read next byte into the array */ } CS_HIGH(); } /*******************************************************************/ /* */ /* Routine to write multiple consecutive bytes to the SPI memory. */ /* The specified number of bytes (no_bytes) are written starting */ /* at location (addr) and are taken from the array pointed to by */ /* (*bytes). */ /* */ /*******************************************************************/ //------------------------------------------------------------------ // 連続して書き込めるのは32バイトまでである。 // 次の書き込みまでは充分な時間(500ms位)をとらないといけない。 // これは、このEEPROMの仕様なのでしかたがない! // 一般的に、EEPROMはそういう傾向の仕様である。 //------------------------------------------------------------------ void WRITE_SPI(int no_bytes,int addr,unsigned char *bytes) { unsigned char addrhi,addrlo,byte; int n; WREN(); /* set WEL bit */ CS_LOW(); SEND_BYTE(0x02); /* WRITE instruction */ addrhi = ((addr & 0x0FF00) >> 8); /* decompose addr into 2 bytes */ addrlo = addr & 0x0FF; SEND_BYTE(addrhi); /* send 2 address bytes */ SEND_BYTE(addrlo); for (n = 0; n < no_bytes; n++) { /* loop to write bytes */ byte = bytes[n]; /* retrieve next byte to write */ SEND_BYTE(byte); /* write it to the SPI memory */ } CS_HIGH(); WIP_POLL(); /* poll for completion of write cycle */ } //------ // main //------ int main(int argc, char* argv[]) { int ret; unsigned int addr; unsigned char val; addr = PRN_PORT; printf("\nRead/Write Access to I/O Port '0x%x', hit any key (ESC to Cancel):", addr); if (getch() == 0x1b) { printf("\n"); return(-1); } printf("\n"); // Start I/O Access (IOSCM) ret = IOSCM_Start(); // Call this first(Windows95/98/Me/NT/2000/XP) if (ret & IOSCM_ERROR) // Check Bit0 if error occurred or not. { if (ret & IOSCM_INVOS) // V1.01 printf("\nError: GetVersionEx() Failed.\n\n"); else printf("\nError: Cannot Initialize IOSCM Device (WinNT/2000/XP).\n\n"); return(-1); } // I/O access available. #if 0 printf("I/O Port Address(0x%04X) : %08X (Double WORD)\n",addr, _inpd(addr)); ++addr; printf("I/O Port Address(0x%04X) : %08X (Double WORD)\n",addr, _inpd(addr)); ++addr; printf("I/O Port Address(0x%04X) : %08X (Double WORD)\n",addr, _inpd(addr)); ++addr; printf("I/O Port Address(0x%04X) : %08X (Double WORD)\n",addr, _inpd(addr)); val = _inp(addr); printf("I/O Port Address(0x%x) : %02x\n",addr, _inp(addr)); _outp(addr, val+1); val = _inp(addr); printf("I/O Port Address(0x%x) : %02x\n",addr, _inp(addr)); _outp(addr, val+1); val = _inp(addr); printf("I/O Port Address(0x%x) : %02x\n",addr, _inp(addr)); _outp(addr, val+1); val = _inp(addr); printf("I/O Port Address(0x%x) : %02x\n",addr, _inp(addr)); #endif /*******************************************************************/ /* */ /* Sample MAIN program to demonstrate the use of these routines */ /* */ /*******************************************************************/ unsigned char data1[]={1,2,3,4,5,6,7,8,9,10,0,0,0,0,0,0}; unsigned char data2[]={15,25,35,45,55,65,75,85,95,105}; unsigned char data3[256]; unsigned char data4[128]; // Xicor X25097 TEST Routine // ポートの初期状態を設定する outportb(data_port,mask); /* initialize SI, CS, and SCK on power-up */ // 書き込み可能状態にする。 WP_HIGH(); // Address 0 から 10 バイト書く WRITE_SPI(10,0,(unsigned char *)data1); // 書き込み禁止状態にする。 WP_LOW(); // Address 0 から 256 バイト読む READ_SPI(256,0,(unsigned char *)data4); for(int i=0;i<256;i++){ printf(" %02X ",data4[i]); } printf("\n"); // end of X25097 TEST Routine // WRITE_SPI(1,45,&data1); /* write 1 byte at 45 */ // WRITE_SPI(8,524,&data2); /* write 8 bytes at 524 */ // READ_SPI(71,500,(unsigned char *)data3); /* read 71 bytes from 500 */ // //------------------------ // Stop I/O Access (IOSCM) //------------------------ ret = IOSCM_Stop(); // Call this last(Windows95/98/Me/NT/2000/XP) //---------------------------------------- // 2004-02-15 コンソールを保持させるため! //---------------------------------------- getch(); // return(ret); } // End of sample.cpp