summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-04-19 01:16:40 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2011-04-19 01:16:40 +0000
commit6307d71a343657595bac35731061dab9e9937c65 (patch)
tree662df13862b934cede2069055a7cf020eee794f4
parent02834f24e9ba0a19a0bd04cf345ea24e69553213 (diff)
downloadnuttx-6307d71a343657595bac35731061dab9e9937c65.tar.gz
nuttx-6307d71a343657595bac35731061dab9e9937c65.tar.bz2
nuttx-6307d71a343657595bac35731061dab9e9937c65.zip
Finish integration of the LPCXpresso OLED NX example
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@3523 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--apps/examples/nx/nx_internal.h4
-rw-r--r--apps/examples/nx/nx_main.c4
-rw-r--r--nuttx/TODO1
-rwxr-xr-xnuttx/configs/lpcxpresso-lpc1768/README.txt2
-rwxr-xr-xnuttx/configs/lpcxpresso-lpc1768/nx/defconfig10
-rwxr-xr-xnuttx/configs/nucleus2g/README.txt4
-rwxr-xr-xnuttx/configs/olimex-lpc1766stk/README.txt2
-rwxr-xr-xnuttx/drivers/lcd/ssd1305.h2
-rwxr-xr-xnuttx/drivers/lcd/ug-9664hswag01.c215
9 files changed, 164 insertions, 80 deletions
diff --git a/apps/examples/nx/nx_internal.h b/apps/examples/nx/nx_internal.h
index 3af7329a4..2f41fba42 100644
--- a/apps/examples/nx/nx_internal.h
+++ b/apps/examples/nx/nx_internal.h
@@ -116,8 +116,8 @@
# endif
#endif
-#ifndef CONFIG_TOOLBAR_HEIGHT
-# define CONFIG_TOOLBAR_HEIGHT 16
+#ifndef CONFIG_EXAMPLES_NX_TOOLBAR_HEIGHT
+# define CONFIG_EXAMPLES_NX_TOOLBAR_HEIGHT 16
#endif
#ifdef CONFIG_NX_MULTIUSER
diff --git a/apps/examples/nx/nx_main.c b/apps/examples/nx/nx_main.c
index 48f4a11d5..3f0578e3f 100644
--- a/apps/examples/nx/nx_main.c
+++ b/apps/examples/nx/nx_main.c
@@ -705,7 +705,7 @@ int user_start(int argc, char *argv[])
#ifndef CONFIG_EXAMPLES_NX_RAWWINDOWS
message("user_start: Add toolbar to window #1\n");
- ret = nxeq_opentoolbar(hwnd1, CONFIG_TOOLBAR_HEIGHT, &g_tbcb, &g_wstate[0]);
+ ret = nxeq_opentoolbar(hwnd1, CONFIG_EXAMPLES_NX_TOOLBAR_HEIGHT, &g_tbcb, &g_wstate[0]);
if (ret < 0)
{
goto errout_with_hwnd1;
@@ -766,7 +766,7 @@ int user_start(int argc, char *argv[])
#ifndef CONFIG_EXAMPLES_NX_RAWWINDOWS
message("user_start: Add toolbar to window #2\n");
- ret = nxeq_opentoolbar(hwnd2, CONFIG_TOOLBAR_HEIGHT, &g_tbcb, &g_wstate[1]);
+ ret = nxeq_opentoolbar(hwnd2, CONFIG_EXAMPLES_NX_TOOLBAR_HEIGHT, &g_tbcb, &g_wstate[1]);
if (ret < 0)
{
goto errout_with_hwnd2;
diff --git a/nuttx/TODO b/nuttx/TODO
index 15852c314..ac485d505 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -483,6 +483,7 @@ o Graphics subystem (graphics/)
not certain if these are consequences of the 4bpp logic or if these
are anomalies that have always been in NX, but are only visible
now at the low resolution of the p14201 LCD (128x96).
+ Update: Same defects in the LPCXpresso a 1bpp (96x64).
Status: Open
Priority: Low (unless you need the p13201 then it is certainly higher).
diff --git a/nuttx/configs/lpcxpresso-lpc1768/README.txt b/nuttx/configs/lpcxpresso-lpc1768/README.txt
index ca5de5ef5..4a9280a0e 100755
--- a/nuttx/configs/lpcxpresso-lpc1768/README.txt
+++ b/nuttx/configs/lpcxpresso-lpc1768/README.txt
@@ -515,7 +515,7 @@ LEDs
intialialized, but is not takint interrupts.
- If a fatal assertion or a fatal unhandled exception occurs, the LED will flash
- strongly as a slow, 1Hz rate.
+ strongly as a slow, 2Hz rate.
LPCXpresso Configuration Options
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/configs/lpcxpresso-lpc1768/nx/defconfig b/nuttx/configs/lpcxpresso-lpc1768/nx/defconfig
index f06875b35..69b497b9a 100755
--- a/nuttx/configs/lpcxpresso-lpc1768/nx/defconfig
+++ b/nuttx/configs/lpcxpresso-lpc1768/nx/defconfig
@@ -791,9 +791,9 @@ CONFIG_LCD_MAXPOWER=2
CONFIG_LCD_MAXCONTRAST=255
CONFIG_NX_MOUSE=y
CONFIG_NX_KBD=y
-#CONFIG_NXTK_BORDERWIDTH=4
-CONFIG_NXTK_BORDERCOLOR1=8
-CONFIG_NXTK_BORDERCOLOR2=4
+CONFIG_NXTK_BORDERWIDTH=2
+CONFIG_NXTK_BORDERCOLOR1=1
+CONFIG_NXTK_BORDERCOLOR2=0
CONFIG_NXTK_AUTORAISE=n
CONFIG_NXFONT_SANS=y
CONFIG_NXFONTS_CHARBITS=7
@@ -826,7 +826,7 @@ CONFIG_NX_MXCLIENTMSGS=16
# CONFIG_SPI_CMDDATA - Include support for cmd/data selection.
#
CONFIG_LCD_UG9664HSWAG01=y
-CONFIG_UG9664HSWAG01_SPIMODE=2
+CONFIG_UG9664HSWAG01_SPIMODE=0
CONFIG_UG9664HSWAG01_FREQUENCY=3500000
CONFIG_UG9664HSWAG01_NINTERFACES=1
CONFIG_UG9664HSWAG01_POWER=y
@@ -1011,6 +1011,7 @@ CONFIG_EXAMPLES_USBSTRG_TRACEINTERRUPTS=n
# buffer driver for use in the test. Default: 0
# CONFIG_EXAMPLES_NX_DEVNO - The LCD device to select from the LCD
# driver for use in the test: Default: 0
+# CONFIG_EXAMPLES_NX_TOOLBAR_HEIGHT - The height of the toolbar in rows.
# CONFIG_EXAMPLES_NX_BGCOLOR -- The color of the background. Default depends on
# CONFIG_EXAMPLES_NX_BPP.
# CONFIG_EXAMPLES_NX_COLOR1 -- The color of window 1. Default depends on
@@ -1033,6 +1034,7 @@ CONFIG_EXAMPLES_USBSTRG_TRACEINTERRUPTS=n
# nx_eventnotify(). Default: 4
CONFIG_EXAMPLES_NX_VPLANE=0
CONFIG_EXAMPLES_NX_DEVNO=0
+CONFIG_EXAMPLES_NX_TOOLBAR_HEIGHT=4
CONFIG_EXAMPLES_NX_BGCOLOR=0
CONFIG_EXAMPLES_NX_COLOR1=1
CONFIG_EXAMPLES_NX_COLOR2=1
diff --git a/nuttx/configs/nucleus2g/README.txt b/nuttx/configs/nucleus2g/README.txt
index 1a3b8d659..2353fe34b 100755
--- a/nuttx/configs/nucleus2g/README.txt
+++ b/nuttx/configs/nucleus2g/README.txt
@@ -249,7 +249,7 @@ LEDs
#define LED_INIRQ 4 /* NC NC ON (momentary) */
#define LED_SIGNAL 5 /* NC NC ON (momentary) */
#define LED_ASSERTION 6 /* NC NC ON (momentary) */
- #define LED_PANIC 7 /* NC NC ON (0.5Hz flashing) */
+ #define LED_PANIC 7 /* NC NC ON (2Hz flashing) */
#undef LED_IDLE /* Sleep mode indication not supported */
After the system is booted, this logic will no longer use LEDs 1 and 2. They
@@ -269,7 +269,7 @@ LEDs
The heartbeat LED is illuminated during all interrupt and signal procressing.
Normally, it will glow dimly to inicate that the LPC17xx is taking interrupts.
- On an assertion PANIC, it will flash at 1Hz.
+ On an assertion PANIC, it will flash at 2Hz.
Nucleus 2G Configuration Options
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/nuttx/configs/olimex-lpc1766stk/README.txt b/nuttx/configs/olimex-lpc1766stk/README.txt
index 056b5aa36..b85d2a87a 100755
--- a/nuttx/configs/olimex-lpc1766stk/README.txt
+++ b/nuttx/configs/olimex-lpc1766stk/README.txt
@@ -337,7 +337,7 @@ LEDs
- ON/OFF toggles means that various events are happening.
- GLowing: LED2 is turned on and off on every interrupt so even timer interrupts
should cause LED2 to glow faintly in the normal case.
- - Flashing. If the LED2 is flashing at about 0.5Hz, that means that a crash
+ - Flashing. If the LED2 is flashing at about 2Hz, that means that a crash
has occurred. If CONFIG_ARCH_STACKDUMP=y, you will get some diagnostic
information on the console to help debug what happened.
diff --git a/nuttx/drivers/lcd/ssd1305.h b/nuttx/drivers/lcd/ssd1305.h
index 246ca63c5..87c955de4 100755
--- a/nuttx/drivers/lcd/ssd1305.h
+++ b/nuttx/drivers/lcd/ssd1305.h
@@ -118,7 +118,7 @@
# define SSD1305_SETBANK31(c) (c << 4) /* Data 4, Bits 4-5: Bank 31 color */
# define SSD1305_SETBANK32(c) (c << 6) /* Data 4, Bits 6-7: Bank 32 color */
#define SSD1305_MAPCOL0 0xa0 /* 0xa0: Column address 0 is mapped to SEG0 */
-#define SSD1305_MAPCOL131 0xa1 /* 0xa1: Column address 131 is mapped to SEG0*/
+#define SSD1305_MAPCOL131 0xa1 /* 0xa1: Column address 131 is mapped to SEG0 */
#define SSD1305_DISPRAM 0xa4 /* 0xa4: Resume to RAM content display */
#define SSD1305_DISPENTIRE 0xa5 /* 0xa5: Entire display ON */
#define SSD1305_DISPNORMAL 0xa6 /* 0xa6: Normal display */
diff --git a/nuttx/drivers/lcd/ug-9664hswag01.c b/nuttx/drivers/lcd/ug-9664hswag01.c
index 0aecbabcf..b68aef3b8 100755
--- a/nuttx/drivers/lcd/ug-9664hswag01.c
+++ b/nuttx/drivers/lcd/ug-9664hswag01.c
@@ -92,13 +92,13 @@
*/
#ifndef CONFIG_UG9664HSWAG01_SPIMODE
-# define CONFIG_UG9664HSWAG01_SPIMODE SPIDEV_MODE2
+# define CONFIG_UG9664HSWAG01_SPIMODE SPIDEV_MODE0
#endif
/* SPI frequency */
#ifndef CONFIG_UG9664HSWAG01_FREQUENCY
-# define CONFIG_UG9664HSWAG01_FREQUENCY SPIDEV_MODE2
+# define CONFIG_UG9664HSWAG01_FREQUENCY 3500000
#endif
/* CONFIG_UG9664HSWAG01_NINTERFACES determines the number of physical interfaces
@@ -160,8 +160,8 @@
/* Color is 1bpp monochrome with leftmost column contained in bits 0 */
-#if defined(CONFIG_NX_DISABLE_1BPP) || !defined(CONFIG_NX_PACKEDMSFIRST)
-# warning "1-bit, big-endian pixel support needed"
+#ifdef CONFIG_NX_DISABLE_1BPP
+# warning "1 bit-per-pixel support needed"
#endif
/* Color Properties *******************************************************************/
@@ -182,14 +182,19 @@
#define UG_BPP 1
#define UG_COLORFMT FB_FMT_Y1
-/* Bytes per visible and actual device row */
+/* Bytes per logical row andactual device row */
-#define UG_STRIDE (UG_XRES >> 3)
-#define UG_DEV_STRIDE (UG_DEV_XRES >> 3)
+#define UG_XSTRIDE (UG_XRES >> 3) /* Pixels arrange "horizontally for user" */
+#define UG_YSTRIDE (UG_YRES >> 3) /* But actual device arrangement is "vertical" */
/* The size of the shadow frame buffer */
-#define UG_FBSIZE (UG_STRIDE * UG_YRES)
+#define UG_FBSIZE (UG_XRES * UG_YSTRIDE)
+
+/* Bit helpers */
+
+#define LS_BIT (1 << 0)
+#define MS_BIT (1 << 7)
/* Debug ******************************************************************************/
@@ -291,7 +296,7 @@ static inline void up_clear(FAR struct ug_dev_s *priv);
* if there are multiple LCD devices, they must each have unique run buffers.
*/
-static uint8_t g_runbuffer[UG_STRIDE];
+static uint8_t g_runbuffer[UG_XSTRIDE];
/* This structure describes the overall LCD video controller */
@@ -468,11 +473,11 @@ static int ug_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
FAR struct ug_dev_s *priv = &g_ugdev;
FAR uint8_t *fbptr;
+ FAR uint8_t *ptr;
uint8_t devcol;
- uint8_t startcol;
- uint8_t endcol;
+ uint8_t fbmask;
uint8_t page;
- uint8_t pixelno;
+ uint8_t usrmask;
uint8_t i;
int pixlen;
@@ -494,45 +499,81 @@ static int ug_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
return OK;
}
- /* Update the shadow frame buffer memory */
+ /* Get the page number. The range of 64 lines is divided up into eight
+ * pages of 8 lines each.
+ */
- fbptr = &priv->fb[row * UG_STRIDE];
- pixelno = 0;
- endcol = col + pixlen;
+ page = row >> 3;
- for (i = col; i < endcol; i++)
- {
- /* Point to the byte to be modified */
+ /* Update the shadow frame buffer memory. First determine the pixel
+ * position in the frame buffer memory. Pixels are organized like
+ * this:
+ *
+ * --------+---+---+---+---+-...-+-----+
+ * Segment | 0 | 1 | 2 | 3 | ... | 131 |
+ * --------+---+---+---+---+-...-+-----+
+ * Bit 0 | | X | | | | |
+ * Bit 1 | | X | | | | |
+ * Bit 2 | | X | | | | |
+ * Bit 3 | | X | | | | |
+ * Bit 4 | | X | | | | |
+ * Bit 5 | | X | | | | |
+ * Bit 6 | | X | | | | |
+ * Bit 7 | | X | | | | |
+ * --------+---+---+---+---+-...-+-----+
+ *
+ * So, in order to draw a white, horizontal line, at row 45. we
+ * would have to modify all of the bytes in page 45/8 = 5. We
+ * would have to set bit 45%8 = 5 in every byte in the page.
+ */
- FAR uint8_t *ptr = &fbptr[i >> 3];
+ fbmask = 1 << (row & 7);
+ fbptr = &priv->fb[page * UG_XRES + col];
+ ptr = fbptr;
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ usrmask = MS_BIT;
+#else
+ usrmask = LS_BIT;
+#endif
+ for (i = 0; i < pixlen; i++)
+ {
/* Set or clear the corresponding bit */
- uint8_t mask = (1 << (i & 7));
- if ((*buffer & (1 << pixelno)) != 0)
+ if ((*buffer & usrmask) != 0)
{
- *ptr |= mask;
+ *ptr++ |= fbmask;
}
else
{
- *ptr &= ~mask;
+ *ptr++ &= ~fbmask;
}
- /* Increment to the next source pixel */
+ /* Inc/Decrement to the next source pixel */
- if (++pixelno >= 8)
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ if (usrmask == LS_BIT)
+ {
+ buffer++;
+ usrmask = MS_BIT;
+ }
+ else
+ {
+ usrmask >>= 1;
+ }
+#else
+ if (usrmask == MS_BIT)
{
buffer++;
- pixelno = 0;
+ usrmask = LS_BIT;
+ }
+ else
+ {
+ usrmask <<= 1;
}
+#endif
}
- /* Get the page number. The range of 64 lines is divided up into eight
- * pages or 8 lines each.
- */
-
- page = row >> 3;
-
/* Offset the column position to account for smaller horizontal
* display range.
*/
@@ -559,9 +600,7 @@ static int ug_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer,
/* Then transfer all of the data */
- startcol = col >> 3;
- endcol = (col + pixlen + 7) >> 3;
- (void)SPI_SNDBLOCK(priv->spi, &fbptr[startcol], endcol - startcol + 1);
+ (void)SPI_SNDBLOCK(priv->spi, fbptr, pixlen);
/* Unlock and de-select the device */
@@ -589,9 +628,10 @@ static int ug_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
/* Because of this line of code, we will only be able to support a single UG device */
FAR struct ug_dev_s *priv = &g_ugdev;
- uint8_t *fbptr;
- uint8_t endcol;
- uint8_t pixelno;
+ FAR uint8_t *fbptr;
+ uint8_t page;
+ uint8_t fbmask;
+ uint8_t usrmask;
uint8_t i;
int pixlen;
@@ -614,33 +654,77 @@ static int ug_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer,
}
/* Then transfer the display data from the shadow frame buffer memory */
+ /* Get the page number. The range of 64 lines is divided up into eight
+ * pages of 8 lines each.
+ */
- fbptr = &priv->fb[row * UG_STRIDE];
- pixelno = 0;
- endcol = col + pixlen;
- *buffer = 0;
-
- for (i = col; i < endcol; i++)
- {
- /* Point to the byte to be modified */
+ page = row >> 3;
- uint8_t *ptr = &fbptr[i >> 8];
+ /* Update the shadow frame buffer memory. First determine the pixel
+ * position in the frame buffer memory. Pixels are organized like
+ * this:
+ *
+ * --------+---+---+---+---+-...-+-----+
+ * Segment | 0 | 1 | 2 | 3 | ... | 131 |
+ * --------+---+---+---+---+-...-+-----+
+ * Bit 0 | | X | | | | |
+ * Bit 1 | | X | | | | |
+ * Bit 2 | | X | | | | |
+ * Bit 3 | | X | | | | |
+ * Bit 4 | | X | | | | |
+ * Bit 5 | | X | | | | |
+ * Bit 6 | | X | | | | |
+ * Bit 7 | | X | | | | |
+ * --------+---+---+---+---+-...-+-----+
+ *
+ * So, in order to draw a white, horizontal line, at row 45. we
+ * would have to modify all of the bytes in page 45/8 = 5. We
+ * would have to set bit 45%8 = 5 in every byte in the page.
+ */
- /* Set or clear the corresponding bit */
+ fbmask = 1 << (row & 7);
+ fbptr = &priv->fb[page * UG_XRES + col];
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ usrmask = MS_BIT;
+#else
+ usrmask = LS_BIT;
+#endif
- if ((*ptr & (1 << (i & 7))) != 0)
+ *buffer = 0;
+ for (i = 0; i < pixlen; i++)
+ {
+ /* Set or clear the corresponding bit */
+
+ uint8_t byte = *fbptr++;
+ if ((byte & fbmask) != 0)
{
- *buffer |= (1 << pixelno);
+ *buffer |= usrmask;
}
- /* Increment to the next source pixel */
+ /* Inc/Decrement to the next destination pixel */
- if (++pixelno >= 8)
+#ifdef CONFIG_NX_PACKEDMSFIRST
+ if (usrmask == LS_BIT)
{
- pixelno = 0;
buffer++;
- *buffer = 0;
+ usrmask = MS_BIT;
}
+ else
+ {
+ usrmask >>= 1;
+ }
+#else
+ if (usrmask == MS_BIT)
+ {
+ buffer++;
+ *buffer = 0;
+ usrmask = LS_BIT;
+ }
+ else
+ {
+ usrmask <<= 1;
+ }
+#endif
}
return OK;
@@ -820,9 +904,8 @@ static int ug_setcontrast(struct lcd_dev_s *dev, unsigned int contrast)
static inline void up_clear(FAR struct ug_dev_s *priv)
{
FAR struct spi_dev_s *spi = priv->spi;
- int row;
+ int page;
int i;
- int j;
/* Clear the framebuffer */
@@ -834,7 +917,7 @@ static inline void up_clear(FAR struct ug_dev_s *priv)
/* Go through all 8 pages */
- for (row = 0, i = 0; i < 8; i++)
+ for (page = 0, i = 0; i < 8; i++)
{
/* Select command transfer */
@@ -842,20 +925,17 @@ static inline void up_clear(FAR struct ug_dev_s *priv)
/* Set the starting position for the run */
- (void)SPI_SEND(priv->spi, SSD1305_SETPAGESTART+i); /* Set the page start */
- (void)SPI_SEND(priv->spi, SSD1305_SETCOLL); /* Set the low column=0 */
- (void)SPI_SEND(priv->spi, SSD1305_SETCOLH); /* Set the high column=0 */
+ (void)SPI_SEND(priv->spi, SSD1305_SETPAGESTART+i);
+ (void)SPI_SEND(priv->spi, SSD1305_SETCOLL + (UG_XOFFSET & 0x0f));
+ (void)SPI_SEND(priv->spi, SSD1305_SETCOLH + (UG_XOFFSET >> 4));
/* Select data transfer */
SPI_CMDDATA(spi, SPIDEV_DISPLAY, false);
- /* Then transfer all of the data */
+ /* Then transfer all 96 columns of data */
- for (j = 0; j < 8; j++, row++)
- {
- (void)SPI_SNDBLOCK(priv->spi, &priv->fb[row * UG_STRIDE], UG_STRIDE);
- }
+ (void)SPI_SNDBLOCK(priv->spi, &priv->fb[page * UG_XRES], UG_XRES);
}
/* Unlock and de-select the device */
@@ -918,7 +998,7 @@ FAR struct lcd_dev_s *ug_initialize(FAR struct spi_dev_s *spi, unsigned int devn
(void)SPI_SEND(spi, SSD1305_SETCOLL + 2); /* Set low column address */
(void)SPI_SEND(spi, SSD1305_SETCOLH + 2); /* Set high column address */
(void)SPI_SEND(spi, SSD1305_SETSTARTLINE+0); /* Display start set */
- (void)SPI_SEND(spi, SSD1305_SCROLL_STOP); /* Stop horzontal scroll */
+ (void)SPI_SEND(spi, SSD1305_SCROLL_STOP); /* Stop horizontal scroll */
(void)SPI_SEND(spi, SSD1305_SETCONTRAST); /* Set contrast control register */
(void)SPI_SEND(spi, 0x32); /* Data 1: Set 1 of 256 contrast steps */
(void)SPI_SEND(spi, SSD1305_SETBRIGHTNESS); /* Brightness for color bank */
@@ -941,6 +1021,7 @@ FAR struct lcd_dev_s *ug_initialize(FAR struct spi_dev_s *spi, unsigned int devn
(void)SPI_SEND(spi, SSD1305_COLORMODE_MONO | SSD1305_POWERMODE_LOW);
(void)SPI_SEND(spi, SSD1305_SETPRECHARGE); /* Set pre-charge period */
(void)SPI_SEND(spi, 15 << SSD1305_PHASE2_SHIFT | 1 << SSD1305_PHASE1_SHIFT);
+ (void)SPI_SEND(spi, SSD1305_SETCOMCONFIG); /* Set COM configuration */
(void)SPI_SEND(spi, SSD1305_COMCONFIG_ALT); /* Data 1, Bit 4: 1=Alternative COM pin configuration */
(void)SPI_SEND(spi, SSD1305_SETVCOMHDESEL); /* Set VCOMH deselect level */
(void)SPI_SEND(spi, SSD1305_VCOMH_x7p7); /* Data 1: ~0.77 x Vcc */