/* * CP/M Program to drive 8x8 LED matrixes with MAX7219 * * Based on Arduino MaxMatrix, by Oscar Kin-Chung Au * * Ported to syntax of HI-TECH C Compiler by Lumir Vanek * https://github.com/agn453/HI-TECH-Z80-C * * This version IS optimalized by ASM code, so switch -O can't be used * * Build on emulator for emulator: * cpm_orig C309-16 -V -URC2014 -DEMULATOR max7219.c * * Build on emulator for RC2014: * cpm_orig C309-16 -V -DRC2014 -DEMULATOR max7219.c * * Build on RC2014 for RC2014: * C309-16 -V -DRC2014 -UEMULATOR max7219.c */ #include #include #ifdef EMULATOR #include "max7219.h" /* Use this line for emulator */ #endif #ifndef EMULATOR #include "H:max7219.h" /* Use this line for CP/M on RC2014, when sources is on drive H: */ #endif /*#define DEBUG*/ #define maxInUse 12 /* The number of MAX7219 8x8 modules used */ #define bufSize maxInUse * 10 /* Each sprite has 10 bytes */ #define DIGITAL_IO_1 0 /*#asm _portAddr EQU 01H ; Output port with 74HCT347 #endasm*/ unsigned char portData; char data; char load; char clock; char buffer[bufSize]; char spriteSpace[] = { 8, 8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; char spriteExclamation[] = { 8, 8, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x30, 0x30 }; char spriteQuotation[] = { 8, 8, 0x66, 0x66, 0x66, 0x44, 0x88, 0x00, 0x00, 0x00 }; char spriteHash[] = { 8, 8, 0x24, 0x24, 0xFE, 0x24, 0x48, 0xFE, 0x48, 0x48 }; char spriteDollar[] = { 8, 8, 0x10, 0x7C, 0xD6, 0x70, 0x18, 0xD6, 0x7C, 0x10 }; char spritePercent[] = { 8, 8, 0x46, 0xAC, 0x48, 0x18, 0x30, 0x24, 0x6A, 0xC4 }; char spriteAnd[] = { 8, 8, 0x20, 0x50, 0x20, 0x50, 0x89, 0x8A, 0x44, 0x3A }; char spriteApostroph[] = { 8, 8, 0x30, 0x30, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00 }; char spriteLeftRoundBracket[] = { 8, 8, 0x18, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x18 }; char spriteRightRoundBracket[] = { 8, 8, 0x30, 0x18, 0x0C, 0x0C, 0x0C, 0x0C, 0x18, 0x30 }; char spriteStar[] = { 8, 8, 0x00, 0x92, 0x54, 0x38, 0xEE, 0x38, 0x54, 0x92 }; char spritePlus[] = { 8, 8, 0x00, 0x00, 0x10, 0x10, 0x7C, 0x10, 0x10, 0x00 }; char spriteComma[] = { 8, 8, 0x00, 0x00, 0x00, 0x30, 0x30, 0x30, 0x20, 0x40 }; char spriteMinus[] = { 8, 8, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00 }; char spriteDot[] = { 8, 8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x60 }; char spriteSlash[] = { 8, 8, 0x06, 0x0C, 0x08, 0x18, 0x30, 0x20, 0x60, 0xC0 }; char sprite0[] = { 8, 8, 0x38, 0x44, 0xD6, 0xD6, 0xD6, 0xD6, 0x44, 0x38 }; char sprite1[] = { 8, 8, 0x18, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E }; char sprite2[] = { 8, 8, 0x7C, 0xC6, 0x06, 0x0C, 0x78, 0xC0, 0xC0, 0xFE }; char sprite3[] = { 8, 8, 0x7C, 0xC6, 0x06, 0x1C, 0x1C, 0x06, 0xC6, 0x7C }; char sprite4[] = { 8, 8, 0x2C, 0x6C, 0x6C, 0xCC, 0xCC, 0xFE, 0x0C, 0x0C }; char sprite5[] = { 8, 8, 0x7E, 0x60, 0x60, 0x3C, 0x06, 0x06, 0xC6, 0x7C }; char sprite6[] = { 8, 8, 0x7C, 0xC6, 0xC0, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C }; char sprite7[] = { 8, 8, 0xFE, 0xC6, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x30 }; char sprite8[] = { 8, 8, 0x7C, 0xC6, 0xC6, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C }; char sprite9[] = { 8, 8, 0x7C, 0xC6, 0xC6, 0xC6, 0x7C, 0x06, 0xC6, 0x7C }; char spriteDoubleDot[] = { 8, 8, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00 }; char spriteSemicolon[] = { 8, 8, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x20, 0x40 }; char spriteLessThan[] = { 8, 8, 0x08, 0x10, 0x20, 0x40, 0x40, 0x20, 0x10, 0x08 }; char spriteEuals[] = { 8, 8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00, 0x00 }; char spriteGreaterThan[] = { 8, 8, 0x20, 0x10, 0x08, 0x04, 0x04, 0x08, 0x10, 0x20 }; char spriteQuestion[] = { 8, 8, 0x7C, 0xC6, 0x06, 0x0C, 0x30, 0x00, 0x30, 0x30 }; char spriteAtSign[] = { 8, 8, 0x3C, 0x42, 0x9A, 0xAA, 0xAA, 0x94, 0x80, 0x7C }; char spriteA[] = { 8, 8, 0x7C, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6 }; char spriteB[] = { 8, 8, 0xF8, 0xC4, 0xC6, 0xFC, 0xC6, 0xC6, 0xC4, 0xF8 }; char spriteC[] = { 8, 8, 0x7C, 0xC6, 0xC0, 0xC0, 0xC0, 0xC0, 0xC6, 0x7C }; char spriteD[] = { 8, 8, 0xF8, 0xC4, 0xC6, 0xC6, 0xC6, 0xC6, 0xC4, 0xF8 }; char spriteE[] = { 8, 8, 0xFE, 0xC0, 0xC0, 0xFC, 0xC0, 0xC0, 0xC0, 0xFE }; char spriteF[] = { 8, 8, 0xFE, 0xC0, 0xC0, 0xF8, 0xC0, 0xC0, 0xC0, 0xC0 }; char spriteG[] = { 8, 8, 0x7C, 0xC6, 0xC0, 0xC0, 0xDC, 0xC6, 0xC6, 0x7C }; char spriteH[] = { 8, 8, 0xC6, 0xC6, 0xC6, 0xFE, 0xC6, 0xC6, 0xC6, 0xC6 }; char spriteI[] = { 8, 8, 0x7E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7E }; char spriteJ[] = { 8, 8, 0xFE, 0x06, 0x06, 0x06, 0x06, 0x86, 0xC6, 0x7C }; char spriteK[] = { 8, 8, 0xC6, 0xC4, 0xCC, 0xD8, 0xF8, 0xCC, 0xC6, 0xC6 }; char spriteL[] = { 8, 8, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE }; char spriteM[] = { 8, 8, 0xC6, 0xEE, 0xD6, 0xD6, 0xD6, 0xC6, 0xC6, 0xC6 }; char spriteN[] = { 8, 8, 0xC6, 0xE6, 0xD6, 0xD6, 0xD6, 0xD6, 0xCE, 0xC6 }; char spriteO[] = { 8, 8, 0x38, 0x44, 0xC6, 0xC6, 0xC6, 0xC6, 0x44, 0x38 }; char spriteP[] = { 8, 8, 0xFC, 0xC6, 0xC6, 0xC6, 0xFC, 0xC0, 0xC0, 0xC0 }; char spriteQ[] = { 8, 8, 0x38, 0x44, 0xC6, 0xC6, 0xC6, 0xD6, 0x4C, 0x3A }; char spriteR[] = { 8, 8, 0xFC, 0xC6, 0xC6, 0xC6, 0xFC, 0xD0, 0xC8, 0xC6 }; char spriteS[] = { 8, 8, 0x7C, 0xC6, 0x60, 0x30, 0x08, 0x0C, 0xC6, 0x7C }; char spriteT[] = { 8, 8, 0x7E, 0xD8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3C }; char spriteU[] = { 8, 8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x44, 0x38 }; char spriteV[] = { 8, 8, 0xC6, 0xC6, 0xC6, 0xC6, 0xC6, 0x44, 0x28, 0x10 }; char spriteW[] = { 8, 8, 0xC6, 0xC6, 0xC6, 0xC6, 0x82, 0x92, 0x54, 0x28 }; char spriteX[] = { 8, 8, 0x82, 0xC6, 0x28, 0x10, 0x28, 0x44, 0xC6, 0x82 }; char spriteY[] = { 8, 8, 0x82, 0xC6, 0x6C, 0x28, 0x10, 0x10, 0x10, 0x10 }; char spriteZ[] = { 8, 8, 0x7E, 0x8C, 0x18, 0x30, 0x30, 0x60, 0xC6, 0xFC }; char spriteLeftSquareBracket[] = { 8, 8, 0x3C, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3C }; char spriteBackSlash[] = { 8, 8, 0xC0, 0x60, 0x20, 0x30, 0x18, 0x08, 0x0C, 0x06 }; char spriteRightSquareBracket[] = { 8, 8, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78 }; char sprite5E[] = { 8, 8, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* 0x5E is ^ */ char spriteUnderscore[] = { 8, 8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E }; char spriteBackApostroph[] = { 8, 8, 0x60, 0x60, 0x60, 0x20, 0x10, 0x00, 0x00, 0x00 }; char spriteHearth[] = { 8, 8, 0x44, 0xEE, 0xFE, 0xFE, 0xFE, 0x7C, 0x38, 0x10 }; char spriteCreature1[] = { 8, 8, 0x42, 0x24, 0x7E, 0xDB, 0xFF, 0xBD, 0x24, 0x42 }; char spriteCreature2[] = { 8, 8, 0x99, 0xBD, 0xDB, 0x7E, 0x24, 0x3C, 0x24, 0x24 }; char spriteTest1[] = { 8, 8, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }; char spriteTest2[] = { 8, 8, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA }; /*char sprite_[] = { 8, 8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };*/ char string[maxInUse + 1]; /* Buffer for displayied chars */ /* * Entry point to program */ int main() { char line[80]; /* Buffer for reading commandline */ char command; int i; int j; int k; int _true; _true = 1; i = 0; i = inp(i); init(); clear(); while (true == _true) { printf("\nEnter command:\n"); printf("=====================================\n"); printf("[0] Print #RC2014 msg.\n"); printf("[W] Print rolling #RC2014 msg.\n"); printf("-------------------------------------\n"); printf("[A] Print A - L\n"); printf("[M] Print M - X\n"); printf("[Y] Print Y - 9\n"); printf("-------------------------------------\n"); printf("[1] Print spec. group 1\n"); printf("[2] Print spec. group 2\n"); printf("[3] Print spec. group 3\n"); printf("-------------------------------------\n"); printf("[T] Run all tests\n"); printf("[X] Run all tests 1000 x\n"); printf("[B] Display predefined string\n"); printf("[N] Display entered string\n"); printf("-------------------------------------\n"); printf("[L R U D] Shift Left/Right/Up/Down\n"); printf("-------------------------------------\n"); printf("[O] Set dot ON\n"); printf("[F] Set dot OFF\n"); printf("[G] Set column\n"); printf("[H] Set All columns\n"); printf("=====================================\n"); printf("[C] Clear\n"); printf("[E] Clear and Exit\n"); do { /*scanf("%c", &command);*/ fgets(line, 8, stdin); command = line[0]; } while ((command < '0') || (command > 'z')); switch (command) { case '0': displayString("bcde#RC2014a"); for (j = 0; j < 100; j++) { delay(); } break; case 'W': case 'w': for (k = 0; k < 10; k++) { writeSprite(0, 0, &spriteHearth); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &sprite4); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &sprite1); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &sprite0); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &sprite2); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &spriteC); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &spriteR); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &spriteHash); if (maxInUse == 12) { for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &spriteCreature1); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &spriteCreature2); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &spriteTest1); for (i = 0; i < 8; i++) { shiftRight(false, true); } writeSprite(0, 0, &spriteTest2); } } break; case 'A': case 'a': displayString("ABCDEFGHIJKL"); for (j = 0; j < 100; j++) { delay(); } break; case 'M': case 'm': displayString("MNOPQRSTUVWX"); for (j = 0; j < 100; j++) { delay(); } break; case 'Y': case 'y': displayString("YZ0123456789"); for (j = 0; j < 100; j++) { delay(); } break; case '1': displayString("!\"#$%&'()*+,"); for (j = 0; j < 100; j++) { delay(); } break; case '2': displayString("-./:;<=>?@[\\"); for (j = 0; j < 100; j++) { delay(); } break; case '3': displayString("]^_`abcde "); for (j = 0; j < 100; j++) { delay(); } break; case 'T': case 't': testAllSprites(); break; case 'X': case 'x': for (k = 0; k < 1000; k++) { if (displayString("BLUE#RC2014a") == 0) { for (j = 0; j < 100; j++) { delay(); } if (testAllSprites() != 0) return 0; } } break; case 'B': case 'b': displayString("BLUE#RC2014a"); for (j = 0; j < 100; j++) { delay(); } break; case 'N': case 'n': printf("Enter string [max. %d chars]:\n", maxInUse); fgets(string, maxInUse, stdin); displayString(&string); for (j = 0; j < 100; j++) { delay(); } break; case 'L': case 'l': shiftLeft(false, true); break; case 'R': case 'r': shiftRight(false, true); break; case 'U': case 'u': shiftUp(false); break; case 'D': case 'd': shiftDown(false); break; case 'O': case 'o': setDotON(); break; case 'F': case 'f': setDotOFF(); break; case 'G': case 'g': testSetColumn(); break; case 'H': case 'h': testSetColumnAll(); break; case 'C': case 'c': clear(); break; case 'E': case 'e': clear(); return 0; default: printf("Wrong command: %c \n", command); } } return 0; } /* * Initialization code */ void init() { int i; portData = 0; /* My output port has lower 4 bits connected to header for driving display (b0-b2 used) ... */ /* ... and high 4 bits driving two-color LED's for easier debugging */ data = 0x11; /* DIN bit 0 */ load = 0x22; /* CS bit 1 */ clock = 0x44; /* CLK bit 2 */ for (i = 0; i < bufSize; i++) buffer[i] = 0; #ifdef DEBUG printf("data: "); printData(data); printf("load: "); printData(load); printf("clock: "); printData(clock); #endif digitalWrite(clock, HIGH); setCommand(max7219_reg_scanLimit, 0x07); /* The scan-limit register sets how many digits are displayed, from 1 to 8 */ setCommand(max7219_reg_decodeMode, 0x00); /* Using an LED matrix (not digits) */ setCommand(max7219_reg_shutdown, 0x01); /* Not in shutdown mode */ setCommand(max7219_reg_intensity, 0x00); /* 0x00 - min, 0x0F max. */ /*setCommand(max7219_reg_displayTest, 0x01);*/ /* Display test - Don't use it for more than 8 modules due to current inrush */ smallDelay(); setCommand(max7219_reg_displayTest, 0x00); /* No display test */ clear(); } void smallDelay() { #ifdef RC2014 /*for (i = 0; i < 2; i++) { }*/ #endif #ifndef RC2014 int i; for (i = 0; i < 100; i++) { } #endif } void delay() { int i; #ifdef RC2014 for (i = 0; i < 3000; i++) { } #endif #ifndef RC2014 for (i = 0; i < 1000; i++) { } #endif } /* * Empty registers, turn all LEDs off */ void clear() { int i; #ifdef DEBUG printf("%s", "============= clear =====================================================\n"); #endif for (i = 0; i < 8; i++) setColumnAll(i, 0); for (i = 0; i < bufSize; i++) buffer[i] = 0; #ifdef DEBUG printf("%s", "=======================================================================\n"); #endif } void setCommand(char command, char value) { int i; /*portData = 0;*/ #ifdef DEBUG printf("%s", "============= setCommand =============\n"); #endif digitalWrite(load, LOW); for (i = 0; i < maxInUse; i++) { shiftOut(data, clock, command); shiftOut(data, clock, value); } digitalWrite(load, LOW); digitalWrite(load, HIGH); #ifdef DEBUG printf("%s", "======================================\n"); #endif } void testSetColumn() { int col, value, j; printf("Enter col [max. %d]:\n", (maxInUse * 8) - 1); scanf("%d", &col); printf("col is: %d \n", col); printf("Enter value [max. 255]:\n"); scanf("%d", &value); printf("value is: %d \n", value); setColumn((char) col, (char) value); for (j = 0; j < 100; j++) { delay(); } } /* * Update a specified column * * col is the index of column to be updated, range from 0 to maxInUse*8 * value is the new values of LEDs, encoded as a unsigned byte */ void setColumn(char col, char value) { int n = col / 8; int c = col % 8; int i; digitalWrite(load, LOW); for (i = 0; i < maxInUse; i++) { if (i == n) { shiftOut(data, clock, c + 1); shiftOut(data, clock, value); } else { shiftOut(data, clock, 0); shiftOut(data, clock, 0); } } digitalWrite(load, LOW); digitalWrite(load, HIGH); buffer[col] = value; } void testSetColumnAll() { int col, value, j; printf("Enter col [max. 7]:\n"); scanf("%d", &col); printf("col is: %d \n", col); printf("Enter value [max. 255]:\n"); scanf("%d", &value); printf("value is: %d \n", value); setColumnAll((char) col, (char) value); for (j = 0; j < 100; j++) { delay(); } } /* * Update the same column of all LED matrix * * col is the index of column to be updated, range from 0 - 7 * value is the new values of LEDs, encoded as a unsigned byte */ void setColumnAll(char col, char value) { int i; digitalWrite(load, LOW); for (i = 0; i < maxInUse; i++) { shiftOut(data, clock, col + 1); shiftOut(data, clock, value); buffer[col * i] = value; } digitalWrite(load, LOW); digitalWrite(load, HIGH); } void setDotON() { int col, row, j; printf("Enter col [max. %d]:\n", (maxInUse * 8) - 1); scanf("%d", &col); printf("col is: %d \n", col); printf("Enter row [max. 7]:\n"); scanf("%d", &row); printf("row is: %d \n", row); setDot((char) col, (char) row, true); for (j = 0; j < 100; j++) { delay(); } } void setDotOFF() { int col, row, j; printf("Enter col [max. %d]:\n", (maxInUse * 8) - 1); scanf("%d", &col); printf("col is: %d \n", col); printf("Enter row [max. 8]:\n"); scanf("%d", &row); printf("row is: %d \n", row); setDot((char) col, (char) row, false); for (j = 0; j < 100; j++) { delay(); } } /* * Update a specified LED * * col is the index of column of the LED to be updated, range from 0 to 79 * row is the index of row of the LED to be updated, range from 0 to 7 * value is the new values of LED, encoded as boolean value (HIGH / LOW) */ void setDot(char col, char row, char value) { int n, c, i; bitWrite(buffer[col], row, value); n = col / 8; c = col % 8; digitalWrite(load, LOW); for (i = 0; i < maxInUse; i++) { if (i == n) { shiftOut(data, clock, c + 1); shiftOut(data, clock, buffer[col]); } else { shiftOut(data, clock, 0); shiftOut(data, clock, 0); } } digitalWrite(load, LOW); digitalWrite(load, HIGH); } /* * Write a sprite * * x is the index of column of the sprite to be displayed, range from 0 to 79 * y is the index of row of the sprite to be displayed, range from 0 to 7 * sprite is the pointer to a byte array, encoding the contains of the sprite */ void writeSprite(int x, int y, char* sprite) { int i, j; int w = sprite[0]; int h = sprite[1]; #ifdef DEBUG printf("%s", "============= writeSprite =============================================\n"); #endif if (h == 8 && y == 0) { for (i = 0; i < w; i++) { int c = x + i; if ((c >= 0) && (c < bufSize)) setColumn(c, sprite[i+2]); } } else { for (i = 0; i < w; i++) { for (j = 0; j < h; j++) { int c = x + i; int r = y + j; if ((c >= 0) && (c < bufSize) && (r >= 0) && (r < 8)) setDot(c, r, bitRead(sprite[i+2], j)); } } } #ifdef DEBUG printf("%s", "=======================================================================\n"); printf("%s", "=======================================================================\n"); #endif } void reload() { int i, j, col; for (i = 0; i < 8; i++) { col = i; digitalWrite(load, LOW); for (j = 0; j < maxInUse; j++) { shiftOut(data, clock, i + 1); shiftOut(data, clock, buffer[col]); col += 8; } digitalWrite(load, LOW); digitalWrite(load, HIGH); } } /* * Shift the matrix * * rotate Rotate the LED values (i.e. the shift-in row/column is filled with shift-out values) * fill_zero shift-in row/column is filled with zero (LED off) */ void shiftLeft(char rotate, char fill_zero) { char old = buffer[0]; int i; for (i = 0; i < bufSize; i++) buffer[i] = buffer[i+1]; if (rotate) buffer[maxInUse * 8 - 1] = old; else if (fill_zero) buffer[maxInUse * 8 - 1] = 0; reload(); } /* * Shift the matrix * * rotate Rotate the LED values (i.e. the shift-in row/column is filled with shift-out values) * fill_zero shift-in row/column is filled with zero (LED off) */ void shiftRight(char rotate, char fill_zero) { int last = maxInUse * 8 - 1; char old = buffer[last]; int i; for (i = bufSize - 1; i > 0; i--) buffer[i] = buffer[i-1]; if (rotate) buffer[0] = old; else if (fill_zero) buffer[0] = 0; reload(); } void shiftUp(char rotate) { int i; for (i = 0; i < maxInUse * 8; i++) { char b = buffer[i] & 1; buffer[i] >>= 1; if (rotate) bitWrite(buffer[i], 7, b); } reload(); } void shiftDown(char rotate) { int i; for (i = 0; i < maxInUse * 8; i++) { char b = buffer[i] & 128; buffer[i] <<= 1; if (rotate) bitWrite(buffer[i], 0, b); } reload(); } /* * https://arduino.stackexchange.com/questions/12285/how-shiftout-function-works-internally-explanation-on-source-code * */ void shiftOut(char dataPin, char clockPin, char val) { unsigned char i; /* i is the bit number, i.e. the 'index' of the next bit to write */ portData = 0; #ifdef DEBUG printf("%s", "============= shiftOut ===============\nval: "); printData(val); #endif for (i = 0; i < 8; i++) { /* * digitalWrite(dataPin, (val & (1 << (7 - i)))); * * 1 is 00000001 in binary * << is the shift left operator. It returns its first argument shifted left by as many positions as indicated by the second argument * so: (1 << (7 - 0)) is 10000000 * & is the 'bitwise AND operator', so 'val' is masked by value from previous line */ /* * Optimalization - instead of calling: digitalWrite(dataPin, (val & (1 << (7 - i)))); * I want to avoid use << operator, that calls 16bit shift realized by * https://github.com/agn453/HI-TECH-Z80-C/blob/master/gen/SHLL.AS */ #asm LD A, 7 ; Local variables can be accessed by IX-displacement SUB (IX - 1) ; Substract 'i' counter from 7 LD B, A ; Shift count is in B LD A, 1 ; The quantity to be shifted JR Z, ZERO_SHIFT ; Check for zero shift SHIFT: SLA A DJNZ SHIFT ZERO_SHIFT: AND (IX + 10) ; 'val' variable LD C, A PUSH BC ; PUSH 'state' argument for digitalWrite ; Function parameters can be accessed by IX+displacement ; The first argument is located at (IX+6) LD C, (IX + 6) PUSH BC ; PUSH 'dataPin' argument for digitalWrite CALL _digitalWrite LD HL, 2+2 ; Because _digitalWrite has two params. on stack ADD HL, SP LD SP, HL #endasm digitalWrite(clockPin, HIGH); digitalWrite(clockPin, LOW); } #ifdef DEBUG printf("%s", "======================================\n"); #endif } void digitalWrite(char dataPin, char state) { if (state == false) { portData &= ~dataPin; } else { portData |= dataPin; } #ifdef RC2014 /* * outp(portAddr, portData); * outp(3, portData); */ /* * Optimalization - instead of calling: outp(portAddr, portData); * I use ASM code: */ #asm ; Variable 'portData' is in A as result from previous operation OUT (1), A ; Output the data to driver board OUT (3), A ; Output the data to Digital I/O board #2 #endasm #endif /*printPortData();*/ /*smallDelay();*/ } void printPortData() { #ifdef DEBUG printf("portData: 0x%4.4x ", portData); if (0 == (portData & 0x080)) printf("0"); else printf("1"); if (0 == (portData & 0x40)) printf("0"); else printf("1"); if (0 == (portData & 0x20)) printf("0"); else printf("1"); if (0 == (portData & 0x10)) printf("0 "); else printf("1 "); if (0 == (portData & 0x08)) printf("0"); else printf("1"); if (0 == (portData & 0x04)) printf("0"); else printf("1"); if (0 == (portData & 0x02)) printf("0"); else printf("1"); if (0 == (portData & 0x01)) printf("0"); else printf("1"); printf("%s", "\n"); #endif } void printData(char charData) { #ifdef DEBUG printf("charData: 0x%4.4x ", charData); if (0 == (charData & 0x80)) printf("0"); else printf("1"); if (0 == (charData & 0x40)) printf("0"); else printf("1"); if (0 == (charData & 0x20)) printf("0"); else printf("1"); if (0 == (charData & 0x10)) printf("0 "); else printf("1"); if (0 == (charData & 0x08)) printf("0"); else printf("1"); if (0 == (charData & 0x04)) printf("0"); else printf("1"); if (0 == (charData & 0x02)) printf("0"); else printf("1"); if (0 == (charData & 0x01)) printf("0"); else printf("1"); printf("%s", "\n"); #endif } /* * Display given string - max. maxInUse characters */ int displayString(register char *str) { int i; int offset; char *_str; for (i = 0; i < maxInUse; i++) { char ch = *str; if ((ch < ' ') || (ch > 'e')) /* 'e' is spriteTest2 - last one */ { ch = ' '; /* Skip undefined chars */ } offset = (ch - 0x20) * 10; /* Each my sprite has 10 bytes */ _str = &spriteSpace + offset; writeSprite(i * 8, 0, _str); str++; /* Next char */ if (inp(DIGITAL_IO_1) != 0) /* If any button pressed, exit */ return -1; } return 0; } int testAllSprites() { int j; if (displayString("ABCDEFGHIJKL") != 0) { return -1; } for (j = 0; j < 100; j++) { delay(); } if (displayString("MNOPQRSTUVWX") != 0) { return -1; } for (j = 0; j < 100; j++) { delay(); } if (displayString("YZ0123456789") != 0) { return -1; } for (j = 0; j < 100; j++) { delay(); } if (displayString("!\"#$%&'()*+,") != 0) { return -1; } for (j = 0; j < 100; j++) { delay(); } if (displayString("-./:;<=>?@[\\") != 0) { return -1; } for (j = 0; j < 100; j++) { delay(); } if (displayString("]^_`abcdeeee") != 0) { return -1; } for (j = 0; j < 100; j++) { delay(); } return 0; }