فهرست منبع

first tries to get the LCD working

Philipp Hinz 9 سال پیش
والد
کامیت
5db2fcd54e
7فایلهای تغییر یافته به همراه534 افزوده شده و 25 حذف شده
  1. 1 1
      CoffeeCode/.cproject
  2. 1 1
      CoffeeCode/global.h
  3. 449 0
      CoffeeCode/lcd.cpp
  4. 47 0
      CoffeeCode/lcd.h
  5. 8 1
      CoffeeCode/main.cpp
  6. 21 22
      CoffeeCode/spi.cpp
  7. 7 0
      CoffeeCode/spi.h

+ 1 - 1
CoffeeCode/.cproject

@@ -14,7 +14,7 @@
 				</extensions>
 			</storageModule>
 			<storageModule moduleId="cdtBuildSystem" version="4.0.0">
-				<configuration artifactName="speedmanager" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.1231565735" name="Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug" postbuildStep="~/CoffePi/CoffeeCode/deploy coffeecode &quot;${ProjDirPath}&quot; &quot;${ProjName}&quot;">
+				<configuration artifactName="coffeecode" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug,org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.cross.exe.debug.1231565735" name="Debug" parent="cdt.managedbuild.config.gnu.cross.exe.debug" postbuildStep="~/CoffeePi/CoffeeCode/deploy coffeecode &quot;${ProjDirPath}&quot; &quot;${ProjName}&quot;">
 					<folderInfo id="cdt.managedbuild.config.gnu.cross.exe.debug.1231565735." name="/" resourcePath="">
 						<toolChain id="cdt.managedbuild.toolchain.gnu.cross.exe.debug.812446316" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.exe.debug">
 							<option id="cdt.managedbuild.option.gnu.cross.path.1620127555" name="Path" superClass="cdt.managedbuild.option.gnu.cross.path" value="/home/sebastian/ArmCrossCompiler/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin" valueType="string"/>

+ 1 - 1
CoffeeCode/global.h

@@ -12,7 +12,7 @@
 #include <pthread.h>
 
 #define SPI_CHANNEL 	1		// 0 or 1 on Raspberry Pi
-#define SPI_SPEED		10000000	// SPI clock speed in Hz
+#define SPI_SPEED		200000	// SPI clock speed in Hz
 
 #define LED_RED_PIN		7
 #define LED_YELLOW_PIN	3

+ 449 - 0
CoffeeCode/lcd.cpp

@@ -0,0 +1,449 @@
+/*
+ * lcd.c:
+ *	Text-based LCD driver.
+ *	This is designed to drive the parallel interface LCD drivers
+ *	based in the Hitachi HD44780U controller and compatables.
+ *
+ * Copyright (c) 2012 Gordon Henderson.
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as published by
+ *    the Free Software Foundation, either version 3 of the License, or
+ *    (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public License
+ *    along with wiringPi.  If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include <wiringPi.h>
+
+#include "spi.h"
+#include "lcd.h"
+
+#ifndef	TRUE
+#  define	TRUE	(1==1)
+#  define	FALSE	(1==2)
+#endif
+
+// HD44780U Commands
+
+#define	LCD_CLEAR	0x01
+#define	LCD_HOME	0x02
+#define	LCD_ENTRY	0x04
+#define	LCD_CTRL	0x08
+#define	LCD_CDSHIFT	0x10
+#define	LCD_FUNC	0x20
+#define	LCD_CGRAM	0x40
+#define	LCD_DGRAM	0x80
+
+// Bits in the entry register
+
+#define	LCD_ENTRY_SH		0x01
+#define	LCD_ENTRY_ID		0x02
+
+// Bits in the control register
+
+#define	LCD_BLINK_CTRL		0x01
+#define	LCD_CURSOR_CTRL		0x02
+#define	LCD_DISPLAY_CTRL	0x04
+
+// Bits in the function register
+
+#define	LCD_FUNC_F	0x04
+#define	LCD_FUNC_N	0x08
+#define	LCD_FUNC_DL	0x10
+
+#define	LCD_CDSHIFT_RL	0x04
+
+struct lcdDataStruct {
+	int bits, rows, cols;
+	int rsPin, strbPin;
+	int cx, cy;
+};
+
+struct lcdDataStruct *lcds[MAX_LCDS];
+
+static int lcdControl;
+
+// Row offsets
+
+static const int rowOff[4] = { 0x00, 0x40, 0x14, 0x54 };
+
+/*
+ * strobe:
+ *	Toggle the strobe (Really the "E") pin to the device.
+ *	According to the docs, data is latched on the falling edge.
+ *********************************************************************************
+ */
+
+static void strobe(const struct lcdDataStruct *lcd) {
+
+// Note timing changes for new version of delayMicroseconds ()
+
+	digitalWrite(lcd->strbPin, 1);
+	delayMicroseconds(50);
+	digitalWrite(lcd->strbPin, 0);
+	delayMicroseconds(50);
+}
+
+/*
+ * sentDataCmd:
+ *	Send an data or command byte to the display.
+ *********************************************************************************
+ */
+
+static void sendDataCmd(const struct lcdDataStruct *lcd, unsigned char data) {
+	register unsigned char myData = data;
+	unsigned char i, d4;
+
+	if (lcd->bits == 4) {
+		d4 = (myData >> 4) & 0x0F;
+		shift_data(d4);
+		d4 >>= 4;
+		strobe(lcd);
+
+		d4 = myData & 0x0F;
+		shift_data(d4);
+	} else {
+		shift_data(myData);
+	}
+	strobe(lcd);
+}
+
+/*
+ * putCommand:
+ *	Send a command byte to the display
+ *********************************************************************************
+ */
+
+static void putCommand(const struct lcdDataStruct *lcd, unsigned char command) {
+	digitalWrite(lcd->rsPin, 0);
+	sendDataCmd(lcd, command);
+	delay(2);
+}
+
+static void put4Command(const struct lcdDataStruct *lcd,
+		unsigned char command) {
+	register unsigned char myCommand = command;
+	register unsigned char i;
+
+	digitalWrite(lcd->rsPin, 0);
+	shift_data(command & 0x0F);
+	strobe(lcd);
+}
+
+/*
+ *********************************************************************************
+ * User Callable code below here
+ *********************************************************************************
+ */
+
+/*
+ * lcdHome: lcdClear:
+ *	Home the cursor or clear the screen.
+ *********************************************************************************
+ */
+
+void lcdHome(const int fd) {
+	struct lcdDataStruct *lcd = lcds[fd];
+
+	putCommand(lcd, LCD_HOME);
+	lcd->cx = lcd->cy = 0;
+	delay(5);
+}
+
+void lcdClear(const int fd) {
+	struct lcdDataStruct *lcd = lcds[fd];
+
+	putCommand(lcd, LCD_CLEAR);
+	putCommand(lcd, LCD_HOME);
+	lcd->cx = lcd->cy = 0;
+	delay(5);
+}
+
+/*
+ * lcdDisplay: lcdCursor: lcdCursorBlink:
+ *	Turn the display, cursor, cursor blinking on/off
+ *********************************************************************************
+ */
+
+void lcdDisplay(const int fd, int state) {
+	struct lcdDataStruct *lcd = lcds[fd];
+
+	if (state)
+		lcdControl |= LCD_DISPLAY_CTRL;
+	else
+		lcdControl &= ~LCD_DISPLAY_CTRL;
+
+	putCommand(lcd, LCD_CTRL | lcdControl);
+}
+
+void lcdCursor(const int fd, int state) {
+	struct lcdDataStruct *lcd = lcds[fd];
+
+	if (state)
+		lcdControl |= LCD_CURSOR_CTRL;
+	else
+		lcdControl &= ~LCD_CURSOR_CTRL;
+
+	putCommand(lcd, LCD_CTRL | lcdControl);
+}
+
+void lcdCursorBlink(const int fd, int state) {
+	struct lcdDataStruct *lcd = lcds[fd];
+
+	if (state)
+		lcdControl |= LCD_BLINK_CTRL;
+	else
+		lcdControl &= ~LCD_BLINK_CTRL;
+
+	putCommand(lcd, LCD_CTRL | lcdControl);
+}
+
+/*
+ * lcdSendCommand:
+ *	Send any arbitary command to the display
+ *********************************************************************************
+ */
+
+void lcdSendCommand(const int fd, unsigned char command) {
+	struct lcdDataStruct *lcd = lcds[fd];
+	putCommand(lcd, command);
+}
+
+/*
+ * lcdPosition:
+ *	Update the position of the cursor on the display.
+ *	Ignore invalid locations.
+ *********************************************************************************
+ */
+
+void lcdPosition(const int fd, int x, int y) {
+	struct lcdDataStruct *lcd = lcds[fd];
+
+	if ((x > lcd->cols) || (x < 0))
+		return;
+	if ((y > lcd->rows) || (y < 0))
+		return;
+
+	putCommand(lcd, x + (LCD_DGRAM | rowOff[y]));
+
+	lcd->cx = x;
+	lcd->cy = y;
+}
+
+/*
+ * lcdCharDef:
+ *	Defines a new character in the CGRAM
+ *********************************************************************************
+ */
+
+void lcdCharDef(const int fd, int index, unsigned char data[8]) {
+	struct lcdDataStruct *lcd = lcds[fd];
+	int i;
+
+	putCommand(lcd, LCD_CGRAM | ((index & 7) << 3));
+
+	digitalWrite(lcd->rsPin, 1);
+	for (i = 0; i < 8; ++i)
+		sendDataCmd(lcd, data[i]);
+}
+
+/*
+ * lcdPutchar:
+ *	Send a data byte to be displayed on the display. We implement a very
+ *	simple terminal here - with line wrapping, but no scrolling. Yet.
+ *********************************************************************************
+ */
+
+void lcdPutchar(const int fd, unsigned char data) {
+	struct lcdDataStruct *lcd = lcds[fd];
+
+	digitalWrite(lcd->rsPin, 1);
+	sendDataCmd(lcd, data);
+
+	if (++lcd->cx == lcd->cols) {
+		lcd->cx = 0;
+		if (++lcd->cy == lcd->rows)
+			lcd->cy = 0;
+
+		putCommand(lcd, lcd->cx + (LCD_DGRAM | rowOff[lcd->cy]));
+	}
+}
+
+/*
+ * lcdPuts:
+ *	Send a string to be displayed on the display
+ *********************************************************************************
+ */
+
+void lcdPuts(const int fd, const char *string) {
+	while (*string)
+		lcdPutchar(fd, *string++);
+}
+
+/*
+ * lcdPrintf:
+ *	Printf to an LCD display
+ *********************************************************************************
+ */
+
+void lcdPrintf(const int fd, const char *message, ...) {
+	va_list argp;
+	char buffer[1024];
+
+	va_start (argp, message);
+	vsnprintf(buffer, 1023, message, argp);
+	va_end (argp);
+
+	lcdPuts(fd, buffer);
+}
+
+/*
+ * lcdInit:
+ *	directly initialises the LCD for the CoffeePi
+ *********************************************************************************
+ */
+
+int lcdInit(void) {
+	spi_init();
+	shift_init();
+	pinMode(LCD_RW, OUTPUT);
+	digitalWrite(LCD_RW, LOW);
+	return lcdInitI(2, 16, 8, LCD_RS, LCD_EN);
+}
+
+/*
+ * lcdInit:
+ *	Take a lot of parameters and initialise the LCD, and return a handle to
+ *	that LCD, or -1 if any error.
+ *********************************************************************************
+ */
+
+int lcdInitI(const int rows, const int cols, const int bits, const int rs,
+		const int strb) {
+	static int initialised = 0;
+
+	unsigned char func;
+	int i;
+	int lcdFd = -1;
+	struct lcdDataStruct *lcd;
+
+	if (initialised == 0) {
+		initialised = 1;
+		for (i = 0; i < MAX_LCDS; ++i)
+			lcds[i] = NULL;
+	}
+
+// Simple sanity checks
+
+	if (!((bits == 4) || (bits == 8)))
+		return -1;
+
+	if ((rows < 0) || (rows > 20))
+		return -1;
+
+	if ((cols < 0) || (cols > 20))
+		return -1;
+
+// Create a new LCD:
+
+	for (i = 0; i < MAX_LCDS; ++i) {
+		if (lcds[i] == NULL) {
+			lcdFd = i;
+			break;
+		}
+	}
+
+	if (lcdFd == -1)
+		return -1;
+
+	lcd = (struct lcdDataStruct *) malloc(sizeof(struct lcdDataStruct));
+	if (lcd == NULL)
+		return -1;
+
+	lcd->rsPin = rs;
+	lcd->strbPin = strb;
+	lcd->bits = 8;		// For now - we'll set it properly later.
+	lcd->rows = rows;
+	lcd->cols = cols;
+	lcd->cx = 0;
+	lcd->cy = 0;
+
+	lcds[lcdFd] = lcd;
+
+	digitalWrite(lcd->rsPin, 0);
+	pinMode(lcd->rsPin, OUTPUT);
+	digitalWrite(lcd->strbPin, 0);
+	pinMode(lcd->strbPin, OUTPUT);
+
+	delay(35); // mS
+
+// 4-bit mode?
+//	OK. This is a PIG and it's not at all obvious from the documentation I had,
+//	so I guess some others have worked through either with better documentation
+//	or more trial and error... Anyway here goes:
+//
+//	It seems that the controller needs to see the FUNC command at least 3 times
+//	consecutively - in 8-bit mode. If you're only using 8-bit mode, then it appears
+//	that you can get away with one func-set, however I'd not rely on it...
+//
+//	So to set 4-bit mode, you need to send the commands one nibble at a time,
+//	the same three times, but send the command to set it into 8-bit mode those
+//	three times, then send a final 4th command to set it into 4-bit mode, and only
+//	then can you flip the switch for the rest of the library to work in 4-bit
+//	mode which sends the commands as 2 x 4-bit values.
+
+	if (bits == 4) {
+		func = LCD_FUNC | LCD_FUNC_DL;			// Set 8-bit mode 3 times
+		put4Command(lcd, func >> 4);
+		delay(35);
+		put4Command(lcd, func >> 4);
+		delay(35);
+		put4Command(lcd, func >> 4);
+		delay(35);
+		func = LCD_FUNC;					// 4th set: 4-bit mode
+		put4Command(lcd, func >> 4);
+		delay(35);
+		lcd->bits = 4;
+	} else {
+		func = LCD_FUNC | LCD_FUNC_DL;
+		putCommand(lcd, func);
+		delay(35);
+		putCommand(lcd, func);
+		delay(35);
+		putCommand(lcd, func);
+		delay(35);
+	}
+
+	if (lcd->rows > 1) {
+		func |= LCD_FUNC_N;
+		putCommand(lcd, func);
+		delay(35);
+	}
+
+// Rest of the initialisation sequence
+
+	lcdDisplay(lcdFd, TRUE);
+	lcdCursor(lcdFd, FALSE);
+	lcdCursorBlink(lcdFd, FALSE);
+	lcdClear(lcdFd);
+
+	putCommand(lcd, LCD_ENTRY | LCD_ENTRY_ID);
+	putCommand(lcd, LCD_CDSHIFT | LCD_CDSHIFT_RL);
+
+	return lcdFd;
+}

+ 47 - 0
CoffeeCode/lcd.h

@@ -0,0 +1,47 @@
+/*
+ * lcd.h
+ *
+ *  Created on: Aug 3, 2016
+ *      Author: sebastian
+ */
+
+#ifndef LCD_H_
+#define LCD_H_
+
+#define MAX_LCDS        8
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void lcdHome        (const int fd) ;
+extern void lcdClear       (const int fd) ;
+extern void lcdDisplay     (const int fd, int state) ;
+extern void lcdCursor      (const int fd, int state) ;
+extern void lcdCursorBlink (const int fd, int state) ;
+extern void lcdSendCommand (const int fd, unsigned char command) ;
+extern void lcdPosition    (const int fd, int x, int y) ;
+extern void lcdCharDef     (const int fd, int index, unsigned char data [8]) ;
+extern void lcdPutchar     (const int fd, unsigned char data) ;
+extern void lcdPuts        (const int fd, const char *string) ;
+extern void lcdPrintf      (const int fd, const char *message, ...) ;
+
+extern int  lcdInitI (const int rows, const int cols, const int bits,
+        const int rs, const int strb) ;
+
+extern int  lcdInit (void) ;
+
+#ifdef __cplusplus
+}
+#endif
+
+// Pinbelegung für das LCD, an verwendete Pins anpassen
+
+#define LCD_RW		24
+#define LCD_RS		27
+#define LCD_EN		23
+
+
+
+
+#endif /* LCD_H_ */

+ 8 - 1
CoffeeCode/main.cpp

@@ -20,6 +20,7 @@
 #include "timer.h"
 #include "database.h"
 #include "logger.h"
+#include "lcd.h"
 
 const int buildno = (1+(int)(
 #include "buildno"
@@ -164,7 +165,7 @@ int main(int argc, char *argv[]) {
 
 	logger_reset();
 	initTimers();
-	initLed();
+	//initLed();
 
 
 //	timer statusT = timer(&printStatus);
@@ -202,6 +203,12 @@ int main(int argc, char *argv[]) {
 	pthread_attr_destroy(&attr);
 
 	// Insert main stuff here.
+	int lcd = lcdInit();
+	if (lcd < 0) logger_error("Error: unable to init LCD (%d)\n", lcd);
+	lcdClear(lcd);
+	lcdHome(lcd);
+	lcdPrintf(lcd,"Wer das liest ist doof.");
+
 	sleep(2);
 
 

+ 21 - 22
CoffeeCode/spi.cpp

@@ -5,9 +5,6 @@
  *      Author: Philipp Hinz
  */
 
-#if defined (__AVR_ARCH__)
-#include <avr/io.h>
-#else
 #include <wiringPi.h>
 #include <wiringPiSPI.h>
 #include <stdio.h>
@@ -15,9 +12,9 @@
 #include <errno.h>
 #include "global.h"
 #include "logger.h"
-#endif
 
 #include <inttypes.h>
+#include <unistd.h>
 #include "spi.h"
 
 /**
@@ -27,18 +24,12 @@
  */
 
 uint8_t spi_readwrite(uint8_t data) {
-#if defined (__AVR_ARCH__)
-	SPDR = data;
-	while (!(SPSR & 0x80)); // wait until byte is sent
-	return SPDR;
-#else
 	uint8_t tmp[1];
 	tmp[0] = data;
 	wiringPiSPIDataRW(SPI_CHANNEL, tmp, 1); // int wiringPiSPIDataRW (int channel, unsigned char *data, int len) ;
 	if (verbose >= V_SPI)
 		logger(V_SPI, "SPI Write %x Read %x\n", data, tmp[0]);
 	return tmp[0];
-#endif
 }
 
 /**
@@ -46,22 +37,30 @@ uint8_t spi_readwrite(uint8_t data) {
  */
 
 void spi_init(void) {
-#if defined (__AVR_ARCH__)
-	// MCP 2510 Chip Select output:
-	PORTB |= 0x10;// deselect (CS is active Low)
-	DDRB |= 0x10;// set pin B4 as output
-
-	// Init SPI
-	DDRB |= 0xA0;// Set MOSI (=B5) and SCK (B7) output,
-	DDRB &= 0xBF;// Set MISO (B6) as input
-	SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR0);// Enable SPI, Master, set clock rate fck/16
-	SPSR = 1;
-#else
 	if (wiringPiSPISetup(SPI_CHANNEL, SPI_SPEED) < 0) { //int wiringPiSPISetup (int channel, int speed) ;
 		logger_error("Unable to setup SPI on channel %d: %s\n", SPI_CHANNEL,
 				strerror(errno));
 		return;
 	}
-#endif
+}
+
+void shift_init(void) {
+	pinMode(SHIFT_G, OUTPUT);
+	pinMode(SHIFT_RCK, OUTPUT);
+	pinMode(SHIFT_SCLR, OUTPUT);
+	digitalWrite(SHIFT_G, HIGH);
+	digitalWrite(SHIFT_RCK, HIGH);
+	digitalWrite(SHIFT_SCLR, LOW);
+	usleep(10);
+	digitalWrite(SHIFT_G, LOW);
+	digitalWrite(SHIFT_RCK, LOW);
+	digitalWrite(SHIFT_SCLR, HIGH);
+}
+
+void shift_data(uint8_t data) {
+	spi_readwrite(data);
+	digitalWrite(SHIFT_RCK, HIGH);
+	usleep(10);
+	digitalWrite(SHIFT_RCK, LOW);
 }
 

+ 7 - 0
CoffeeCode/spi.h

@@ -7,9 +7,16 @@
 
 #ifndef SPI_H_
 #define SPI_H_
+#include <inttypes.h>
 
 uint8_t spi_readwrite(uint8_t data);
 void spi_init(void);
+void shift_init(void);
+void shift_data(uint8_t data);
+
+#define SHIFT_SCLR	21 // ~Master Reset
+#define SHIFT_RCK	22 // storage register clock input
+#define SHIFT_G		26 // ~Output Enable
 
 
 #endif /* SPI_H_ */