7-segment display with shift register. Common anode/cathode, any (eh, sort of) number of digits. Kind of framebuffer. Display has to be connected thru shift register, e.g. 4094. More details and picture in header file.

Files at this revision

API Documentation at this revision

Comitter:
amateusz
Date:
Sat Dec 19 13:30:30 2015 +0000
Commit message:
Use a 7-segment display with any (eh, sort of) number of digits. Display connected with shift registers, e.g. 4094. More details and picture in header file.

Changed in this revision

LED7segmDual4094.cpp Show annotated file Show diff for this revision Revisions of this file
LED7segmDual4094.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 55c62e840faf LED7segmDual4094.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LED7segmDual4094.cpp	Sat Dec 19 13:30:30 2015 +0000
@@ -0,0 +1,242 @@
+#include "mbed.h"
+#include "LED7segmDual4094.h"
+
+signed char LED7segmDual4094::digitORascii2char (char input, bool dot) {
+  signed char return7seg = 0;
+  switch (input) {
+    case 0:
+    case '0':
+    case 'O':
+      return7seg =  0b00111111;
+      break;
+    case '1':
+    case 1:
+      return7seg =  0b00000110;
+      break;
+    case '2':
+    case 2:
+    case 'z':
+    case 'Z':
+      return7seg =  0b01011011;
+      break;
+    case 3:
+    case '3':
+      return7seg =  0b01001111;
+      break;
+    case 4:
+    case '4':
+      return7seg =  0b01100110;
+      break;
+    case 5:
+    case '5':
+      return7seg =  0b01101101;
+      break;
+    case 6:
+    case '6':
+      return7seg =  0b01111100;
+      break;
+    case 7:
+    case '7':
+      return7seg =  0b00000111;
+      break;
+    case 8:
+    case '8':
+      return7seg =  0b01111111;
+      break;
+    case 9:
+    case '9':
+      return7seg = 0b01100111;
+      break;
+    case 'a':
+    case 'A':
+      return7seg = 0b01110111;
+      break;
+    case 'b':
+    case 'B':
+      return7seg = 0b01111100;
+      break;
+    case 'c':
+      return7seg = 0b01011000;
+      break;
+    case 'C':
+      return7seg = 0b00111001;
+      break;
+    case 'd':
+    case 'D':
+      return7seg = 0b01011110;
+      break;
+    case 'e':
+      return7seg = 0b01111011;
+      break;
+    case 'E':
+      return7seg = 0b01111001;
+      break;
+    case 'f':
+    case 'F':
+      return7seg = 0b01110001;
+      break;
+    case 'g':
+      return7seg = 0b01101111;
+    case 'G':
+      return7seg = 0b00111101;
+      break;
+    case 'h':
+      return7seg = 0b01110100;
+      break;
+    case 'H':
+      return7seg = 0b01110110;
+      break;
+    case 'i':
+      return7seg = 0b00010000;
+      break;
+    case 'I':
+      return7seg = 0b00110000;
+      break;
+    case 'j':
+      return7seg = 0b00001111;
+      break;
+    case 'J':
+      return7seg = 0b00011111;
+      break;
+    case 'k':
+      return7seg = 0b01111000;
+      break;
+    case 'l':
+      return7seg = 0b00110000;
+      break;
+    case 'L':
+      return7seg = 0b00111000;
+      break;
+    case 'm':
+    case 'n':
+      return7seg = 0b01010100;
+      break;
+    case 'N':
+    case 'M':
+      return7seg = 0b00110111;
+      break;
+    case 'o':
+      return7seg = 0b01011100;
+      break;
+    case 'p':
+    case 'P':
+      return7seg = 0b01110011;
+      break;
+    case 'r':
+    case 'R':
+      return7seg = 0b01010000;
+      break;
+    case 's':
+    case 'S':
+      return7seg = 0b01101101;
+      break;
+    case 'q':
+    case 'Q':
+      return7seg = 0b01100111;
+      break;
+    case 't':
+    case 'T':
+      return7seg = 0b01111000;
+      break;
+    case 'u':
+      return7seg = 0b00011100;
+      break;
+    case 'U':
+      return7seg = 0b00111110;
+      break;
+    case 'v':
+    case 'V':
+      return7seg = 0b00111100;
+      break;
+    case 'w':
+    case 'W':
+      return7seg = 0b01001001;
+      break;
+    case 'x':
+    case 'X':
+      return7seg = 0b01110110;
+      break;
+    case 'y':
+    case 'Y':
+      return7seg = 0b01101110;
+      break;
+    case ' ':
+      return7seg = 0b00000000;
+      break;
+    default:
+      return7seg =  -1;
+      break;
+  }
+  if (dot) return7seg |= (1 << 7);
+  // else clearing the dot ?
+  return return7seg;
+}
+
+LED7segmDual4094::LED7segmDual4094(PinName data, PinName clock, PinName strobe, char numOfSegments): _data(data), _clock(clock), _strobe(strobe) {
+  whichSegmMux = 0;
+  _numOfSegments = numOfSegments;
+  fb = new char [_numOfSegments];
+  _anodesBitMask = new unsigned int[_numOfSegments];
+  for (unsigned int i = 0; i < numOfSegments; i++)
+    _anodesBitMask[i] = ( 1 << i );
+}
+void LED7segmDual4094::setAnodesBitMask(unsigned int *tab) {
+  for (char i = 0; i < _numOfSegments; i++)
+    _anodesBitMask[i] = tab[i];
+};
+void LED7segmDual4094::draw(void){ // a version with no arguments is for internal (i.e. private) use only. the other one is exposed publicly.
+  if (_anodesActiveState)
+	load = 0;
+  else load = ~0;
+  for (char i = 0; i < 8; i++) {
+    if ((fb[whichSegmMux] >> i) & 0x1) load |= 1 << ( 8 + i);
+	else load &= ~(1 << (8+i)); 
+  }
+  if (!_anodesActiveState) {
+    load &= ~_anodesBitMask[(_numOfSegments-1) - whichSegmMux];
+	/*for (int i = 0; i < _numOfSegments; i++)
+      if (whichSegmMux != (_numOfSegments - 1) - i) // when ""if(whichSegmMux != i)"" then reverse direction of printing.
+        load |= _anodesBitMask[i];
+    //load &= ~(_anodesBitMask[(_numOfSegments-1) - whichSegmMux]);
+	*/
+  } else
+    load |= 1 << (_numOfSegments - whichSegmMux); // sets a bit indicating which segment to light up (connect kathode (or anode, I mean positive rail))
+  send4094(load);
+  if (++whichSegmMux > (_numOfSegments - 1)) whichSegmMux = 0;
+}
+/* void LED7segmDual4094::draw(char *tab) {
+  // whichSegmMux equals 0 on start thanks to the header file. || which segment for multiplexing
+  if (_anodesActiveState)
+	load = 0;
+  else load = ~0;
+  for (char i = 0; i < 8; i++) {
+    if ((tab[whichSegmMux] >> i) & 0x1) load |= 1 << ( 8 + i);
+	else load &= ~(1 << (8+i)); 
+  }
+  if (!_anodesActiveState) {
+    load &= ~_anodesBitMask[(_numOfSegments-1) - whichSegmMux];
+	//for (int i = 0; i < _numOfSegments; i++)
+    //  if (whichSegmMux != (_numOfSegments - 1) - i) // when ""if(whichSegmMux != i)"" then reverse direction of printing.
+    //    load |= _anodesBitMask[i];
+    //load &= ~(_anodesBitMask[(_numOfSegments-1) - whichSegmMux]);
+	//
+  } else
+    load |= 1 << (_numOfSegments - whichSegmMux); // sets a bit indicating which segment to light up (connect kathode (or anode, I mean positive rail))
+  send4094(load);
+  if (++whichSegmMux > (_numOfSegments - 1)) whichSegmMux = 0;
+}
+*/
+
+void LED7segmDual4094::send4094(unsigned short _load) { // this shit is straight from the datasheet, just loading these 16bits to two daisy-chained 4094 shift registers
+  _strobe = 0;
+  for (signed char _i = 15; _i >= 0; _i--) {
+    _data =  (_load >> _i) & 0x1 ;
+    _clock = 0;
+    _clock = 1;
+  }
+  _strobe = 1;
+}
+
+void LED7segmDual4094::setAnodesActiveState(bool state) {
+  _anodesActiveState = state;
+}
diff -r 000000000000 -r 55c62e840faf LED7segmDual4094.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/LED7segmDual4094.h	Sat Dec 19 13:30:30 2015 +0000
@@ -0,0 +1,39 @@
+/* This library lets to use a led display made of at most 8 segments as a screen buffer device. Like this one: https://www.dropbox.com/s/a3rvqahxhvpj0w3/general.jpg?dl=0
+The dispaly has to be made of two shift registers - i used 4094 and they are guaranteed to work, but others may also without any change to the code. The 8 digits limit can be easily overcomed daisy-chaining more shift registers. Have in mind though that it will cause the dispaly to be dimmer.
+This library lets you treat the display as a screen buffer device i.e. each digit is a byte-sized and bits are ordered as usual ABCDEFG scheme goes. Object has a field fb, which is the size you have it initialized.
+Size 4 by default. So just write to object.fb[n] whatever you want. You can do all sorts of bitwise operations. And then you have to take care of calling the draw() method periodcaly to update the display. (preffered way: use systick or timer).
+There is also provided function to convert most ASCII characters to bitmasked segments: digitORascii2char. It also allows to toggle a dot. Hope you like it.
+There is a bonus feature: you can arrange the common cathodes/anodes in any way in the shift registers, because you can initialise the library with given order of them.
+The same with segments. (in progress). Moreover there can be different layout of segments between each digit (also not done). Whoa!
+*/
+#include "mbed.h"
+
+#ifndef LED7segmDual4094_h
+#define LED7segmDual4094_h
+	
+class LED7segmDual4094{
+	private:
+		char _numOfSegments;
+		unsigned int *_anodesBitMask;
+		unsigned int _segmentsBitMask;
+		bool _anodesActiveState;
+		DigitalOut _data;
+		DigitalOut _clock;
+		DigitalOut _strobe;
+		void send4094(unsigned short _load);
+	public:
+		LED7segmDual4094(PinName data, PinName clock, PinName strobe, char numOfSegments = 4);
+		char *fb;
+		void draw();
+		void setAnodesBitMask(unsigned int *tab);
+		void setAnodesActiveState(bool state);
+//		void draw(char *tab);
+		unsigned short load;
+		//char i;
+		char whichSegmMux;			
+		signed char digitORascii2char(char input, bool dot=0);
+//		signed char return7seg;
+	
+};
+		
+#endif
\ No newline at end of file