// ----------------------------------------------------------------------------- /// @file nhd0420.c /// @brief Description // ----------------------------------------------------------------------------- // Micro-Key bv // Industrieweg 28, 9804 TG Noordhorn // Postbus 92, 9800 AB Zuidhorn // The Netherlands // Tel: +31 594 503020 // Fax: +31 594 505825 // Email: support@microkey.nl // Web: www.microkey.nl // ----------------------------------------------------------------------------- /// $Revision$ /// $Author$ /// $Date$ // (c) 2017 Micro-Key bv // ----------------------------------------------------------------------------- /// @file nhd0420.c /// @ingroup {group_name} // ----------------------------------------------------------------------------- // Include files // ----------------------------------------------------------------------------- #include #include #include "stm32f10x.h" #include "nhd0420.h" #include "spi.h" #include "Logger.h" // ----------------------------------------------------------------------------- // Constant and macro definitions // ----------------------------------------------------------------------------- #define NHD0420_CURSOR_OFFSET_ROW1 (0x00) #define NHD0420_CURSOR_OFFSET_ROW2 (0x40) #define NHD0420_CURSOR_OFFSET_ROW3 (0x14) #define NHD0420_CURSOR_OFFSET_ROW4 (0x54) // ----------------------------------------------------------------------------- // Type definitions // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- // File-scope variables // ----------------------------------------------------------------------------- static int nhd0420_cursorRowOffset[NHD0420_NUMBER_OF_ROWS] = { NHD0420_CURSOR_OFFSET_ROW1, NHD0420_CURSOR_OFFSET_ROW2, NHD0420_CURSOR_OFFSET_ROW3, NHD0420_CURSOR_OFFSET_ROW4 }; // ----------------------------------------------------------------------------- // Function declarations // ----------------------------------------------------------------------------- static ErrorStatus setState(const struct DisplayDevice* self, DisplayDevice_functionalState state); static ErrorStatus write(const struct DisplayDevice* self, const char* buffer, size_t length, size_t row, size_t column); static ErrorStatus clear(const struct DisplayDevice* self); static ErrorStatus setBrightness(const struct DisplayDevice* self, size_t brightness); static ErrorStatus setContrast(const struct DisplayDevice* self, size_t contrast); // ----------------------------------------------------------------------------- // Function definitions // ----------------------------------------------------------------------------- ErrorStatus NHD0420_construct(struct NHD0420* self, const struct IODevice* device) { ErrorStatus returnValue = SUCCESS; if (!self->initialized) { if (device != NULL) { self->device = device; struct DisplayDeviceParameters ddParameters; ddParameters.numberOfRows = NHD0420_NUMBER_OF_ROWS; ddParameters.numberOfColumns = NHD0420_NUMBER_OF_COLUMNS; ddParameters.brightnessMin = NHD0420_BRIGHTNESS_MIN; ddParameters.brightnessMax = NHD0420_BRIGHTNESS_MAX; ddParameters.contrastMin = NHD0420_CONTRAST_MIN; ddParameters.contrastMax = NHD0420_CONTRAST_MAX; returnValue = DisplayDevice_construct(&self->displayDevice, &ddParameters, NULL, setState, write, clear, NULL, setBrightness, setContrast, NULL); if (returnValue == SUCCESS) { self->initialized = true; NHD0420_sendData(self, "Hallo", 5); } } else { returnValue = ERROR; } } else { returnValue = ERROR; } return returnValue; } void NHD0420_destruct (struct NHD0420* self) { self->device = NULL; self->initialized = false; } ErrorStatus NHD0420_getSpiParameters(struct SpiParameters* parameters) { ErrorStatus returnValue = SUCCESS; if ((configCPU_CLOCK_HZ / 64) < NHD0420_SPI_MAX_CLK_HZ) { parameters->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64; } else if ((configCPU_CLOCK_HZ / 128) < NHD0420_SPI_MAX_CLK_HZ) { parameters->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128; } else if ((configCPU_CLOCK_HZ / 256) < NHD0420_SPI_MAX_CLK_HZ) { parameters->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256; } else { // The CPU clock is too high. The pre-scaler has a max of 256. A clock higher than 25,6 MHz // results in a SPI CLK higher than 100 kHz, which is the max of the display returnValue = ERROR; } if (returnValue == SUCCESS) { // SPI pre-scaler was no problem - assign the remaining parameters parameters->SPI_CPHA = NHD0420_SPI_CPHA; parameters->SPI_CPOL = NHD0420_SPI_CPOL; parameters->SPI_CRCPolynomial = NHD0420_SPI_CRCPolynomial; parameters->SPI_DataSize = NHD0420_SPI_DataSize; parameters->SPI_Direction = NHD0420_SPI_Direction; parameters->SPI_FirstBit = NHD0420_SPI_FirstBit; parameters->SPI_Mode = NHD0420_SPI_Mode; parameters->SPI_NSS = NHD0420_SPI_NSS; parameters->SPI_NSS_internal = NHD0420_SPI_NSS_INTERNAL; parameters->rxQueueSize = NHD0420_SPI_RX_QUEUE; parameters->txQueueSize = NHD0420_SPI_TX_QUEUE; } return returnValue; } ErrorStatus NHD0420_setCursorToPosition(const struct NHD0420* self, size_t row, size_t column) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { // Setting cursor requires sending a command sequence with an additional // address parameter representing the line/column // Each line has a dedicated offset, the column is simply added to that offset // Make sure to keep within boundaries to avoid glitches row = row -1; column = column - 1; // Check the coordinates to avoid glitches if ((row >= NHD0420_NUMBER_OF_ROWS) && (column >= NHD0420_NUMBER_OF_COLUMNS)) { returnValue = ERROR; } if (returnValue == SUCCESS) { char address = nhd0420_cursorRowOffset[(int)row] + column; char buffer[3] = {NHD0420_CMD_PREFIX, NHD0420_CMD_CURSOR_SET, address}; returnValue = NHD0420_sendData(self, buffer, 3); } } else { returnValue = ERROR; } return returnValue; } ErrorStatus NHD0420_setContrast(const struct NHD0420* self, char contrast) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { // Setting contrast requires sending a command sequence with an additional // parameter representing the contrast // Contrast values must be between NHD0420_CONTRAST_MIN and // NHD0420_CONTRAST_MAX. If boundaries are exceeded, this function will be // left with an ERROR if ((contrast < NHD0420_CONTRAST_MIN) || (contrast > NHD0420_CONTRAST_MAX)) { returnValue = ERROR; } if (returnValue == SUCCESS) { char buffer[3] = {NHD0420_CMD_PREFIX, NHD0420_CMD_SET_CONTRAST, contrast}; returnValue = NHD0420_sendData(self, buffer, 3); } } else { returnValue = ERROR; } return returnValue; } ErrorStatus NHD0420_setBacklightBrightness(const struct NHD0420* self, char brightness) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { // Setting backlight brightness requires sending a command sequence with an // additional parameter representing the brightness // Brightness values must be between NHD0420_BRIGHTNESS_MIN and // NHD0420_BRIGHTNESS_MAX. If boundaries are exceeded, this function will be // left with an ERROR if ((brightness < NHD0420_BRIGHTNESS_MIN) || (brightness > NHD0420_BRIGHTNESS_MAX)) { returnValue = ERROR; } if (returnValue == SUCCESS) { char buffer[3] = {NHD0420_CMD_PREFIX, NHD0420_CMD_SET_BRIGHTNESS, brightness}; returnValue = NHD0420_sendData(self, buffer, 3); } } else { returnValue = ERROR; } return returnValue; } ErrorStatus NHD0420_setRS232Baudrate(const struct NHD0420* self, char baudrate) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { // Setting baudrate requires sending a command sequence with an // additional parameter representing the baudrate // Baudrate values must be between NHD0420_BAUDRATE_MIN and // NHD0420_BAUDRATE_MAX. If boundaries are exceeded, this function will be // left with an ERROR if ((baudrate < NHD0420_BAUDRATE_MIN) || (baudrate > NHD0420_BAUDRATE_MAX)) { returnValue = ERROR; } if (returnValue == SUCCESS) { char buffer[3] = {NHD0420_CMD_PREFIX, NHD0420_CMD_CHANGE_RS232_BR, baudrate}; returnValue = NHD0420_sendData(self, buffer, 3); } } else { returnValue = ERROR; } return returnValue; } ErrorStatus NHD0420_setI2CAddress(const struct NHD0420* self, char address) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { // Setting I2C requires sending a command sequence with an // additional parameter representing the address // Baudrate values must be between NHD0420_BAUDRATE_MIN and // NHD0420_BAUDRATE_MAX. If boundaries are exeeded, this function will be // left with an ERROR if ((address | 0xFE) != 0xFE) { returnValue = ERROR; } if (returnValue == SUCCESS) { char buffer[3] = {NHD0420_CMD_PREFIX, NHD0420_CMD_CHANGE_I2C_ADDRSS, address}; returnValue = NHD0420_sendData(self, buffer, 3); } } else { returnValue = ERROR; } return returnValue; } /** ---------------------------------------------------------------------------- * NHD0420_SendCommand * Send a command to the display * * @param command * * @return ErrorStatus SUCCESS if initialisation was successful * ERROR otherwise * * @todo * ----------------------------------------------------------------------------- */ ErrorStatus NHD0420_sendCommand(const struct NHD0420* self, char command) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { char buffer[NHD0420_CMD_LENGTH]; buffer[0] = NHD0420_CMD_PREFIX; buffer[1] = command; returnValue = IODevice_write(self->device, buffer, NHD0420_CMD_LENGTH); } else { returnValue = ERROR; } return returnValue; } ErrorStatus NHD0420_sendData(const struct NHD0420* self, const char* buffer, size_t length) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { returnValue = IODevice_write(self->device, buffer, length); } else { returnValue = ERROR; } return returnValue; } static ErrorStatus setState(const struct DisplayDevice* self, DisplayDevice_functionalState state) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { if (state == ON) { returnValue = NHD0420_turnOnDisplay((const struct NHD0420*)self); } else { returnValue = NHD0420_turnOffDisplay((const struct NHD0420*)self); } } else { returnValue = ERROR; } return returnValue; } static ErrorStatus write(const struct DisplayDevice* self, const char* buffer, size_t length, size_t row, size_t column) { ErrorStatus returnValue = SUCCESS; if (self->initialized) { if ((length + column) > NHD0420_NUMBER_OF_COLUMNS) { returnValue = ERROR; } // Set cursor on display returnValue = NHD0420_setCursorToPosition((const struct NHD0420*)self, row, column); if (returnValue == SUCCESS) { // Send one byte at a time (display requirement) int loopcounter; for (loopcounter = 0; loopcounter < length; loopcounter++) { returnValue = NHD0420_sendData((const struct NHD0420*)self, &buffer[loopcounter], 1); } } } else { returnValue = ERROR; } return returnValue; } static ErrorStatus clear(const struct DisplayDevice* self) { if (self->initialized) { return NHD0420_clearScreen((const struct NHD0420*)self); } else { return ERROR; } } static ErrorStatus setBrightness(const struct DisplayDevice* self, size_t brightness) { if (self->initialized) { return NHD0420_setBacklightBrightness((const struct NHD0420*)self, brightness); } else { return ERROR; } } static ErrorStatus setContrast(const struct DisplayDevice* self, size_t contrast) { if (self->initialized) { return NHD0420_setContrast((const struct NHD0420*)self, contrast); } else { return ERROR; } }