1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/bsp.c Sun May 19 21:18:16 2013 +0000
1.3 @@ -0,0 +1,316 @@
1.4 +/*
1.5 + * Ben NanoNote and EM027AS012 E-Paper Display Adapter Board communication.
1.6 + *
1.7 + * Copyright (C) 2013 Paul Boddie
1.8 + *
1.9 + * SPI functions derived from those in lib/atben.c by Werner Almesberger:
1.10 + *
1.11 + * Copyright (C) 2010-2011 Werner Almesberger
1.12 + *
1.13 + * This program is free software; you can redistribute it and/or modify
1.14 + * it under the terms of the GNU General Public License as published by
1.15 + * the Free Software Foundation; either version 2 of the License, or
1.16 + * (at your option) any later version.
1.17 + *
1.18 + * Driver-related code originally provided under the following terms:
1.19 + *
1.20 + * Copyright 2013 Pervasive Displays, Inc.
1.21 + *
1.22 + * Licensed under the Apache License, Version 2.0 (the "License");
1.23 + * you may not use this file except in compliance with the License.
1.24 + * You may obtain a copy of the License at:
1.25 + *
1.26 + * http://www.apache.org/licenses/LICENSE-2.0
1.27 + *
1.28 + * Unless required by applicable law or agreed to in writing,
1.29 + * software distributed under the License is distributed on an
1.30 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
1.31 + * express or implied. See the License for the specific language
1.32 + * governing permissions and limitations under the License.
1.33 + */
1.34 +
1.35 +#include <ubb/ubb.h>
1.36 +#include <unistd.h>
1.37 +#include <sys/time.h>
1.38 +#include <time.h>
1.39 +#include <stdio.h>
1.40 +#include "bsp.h"
1.41 +#include "Display_Hardware_Driver.h"
1.42 +
1.43 +void bsp_init()
1.44 +{
1.45 + OUT(UBB_DAT2);
1.46 + OUT(UBB_DAT3);
1.47 + OUT(UBB_CMD);
1.48 + OUT(UBB_CLK);
1.49 + OUT(UBB_DAT0);
1.50 + OUT(UBB_DAT1);
1.51 +}
1.52 +
1.53 +/* NanoNote-specific functions. */
1.54 +
1.55 +void shift_select()
1.56 +{
1.57 + CLR(MUX_S0);
1.58 +}
1.59 +
1.60 +void shift_update()
1.61 +{
1.62 + SET(SHIFT_RCK);
1.63 + CLR(SHIFT_RCK);
1.64 +}
1.65 +
1.66 +void shift_init()
1.67 +{
1.68 + /* Initiate a clear operation. */
1.69 +
1.70 + CLR(SHIFT_SCLR);
1.71 +
1.72 + /* Set clocks to known state. */
1.73 +
1.74 + CLR(SHIFT_SCK);
1.75 + CLR(SHIFT_RCK);
1.76 +
1.77 + /* Propagate the clear operation. */
1.78 +
1.79 + shift_update();
1.80 +
1.81 + /* Finalise the initialisation. */
1.82 +
1.83 + SET(SHIFT_SCLR);
1.84 +}
1.85 +
1.86 +void shift_reinit()
1.87 +{
1.88 + /* Set clocks to known state. */
1.89 +
1.90 + CLR(SHIFT_SCK);
1.91 + CLR(SHIFT_RCK);
1.92 +
1.93 + /* Avoid clear operation. */
1.94 +
1.95 + SET(SHIFT_SCLR);
1.96 +}
1.97 +
1.98 +void shift_in(uint8_t v)
1.99 +{
1.100 + if (v)
1.101 + SET(SHIFT_SI);
1.102 + else
1.103 + CLR(SHIFT_SI);
1.104 +
1.105 + SET(SHIFT_SCK);
1.106 + CLR(SHIFT_SCK);
1.107 +}
1.108 +
1.109 +void epd_select()
1.110 +{
1.111 + SET(MUX_S0);
1.112 +}
1.113 +
1.114 +/* Callback functions. */
1.115 +
1.116 +void bsp_InitDisplayHardware()
1.117 +{
1.118 + /* This should do the following:
1.119 +
1.120 + PANEL = 0
1.121 + CS/SSEL = 0
1.122 + PWM = 0
1.123 + RESET = 0
1.124 + DIS = 0
1.125 +
1.126 + (Could shift 0, 0 -> PANEL, DIS
1.127 + or 0, 0, 0 -> PANEL, BORDER, DIS.)
1.128 + */
1.129 +
1.130 + shift_select();
1.131 + shift_init(); /* PANEL = DIS = 0 */
1.132 +
1.133 + epd_select();
1.134 + CLR(EPD_SSEL);
1.135 + CLR(EPD_PWM);
1.136 + CLR(EPD_RESET);
1.137 + CLR(EPD_MOSI);
1.138 +
1.139 + printf("Hardware initialised.\n");
1.140 +}
1.141 +
1.142 +void bsp_PowerOn()
1.143 +{
1.144 + /* This should do the following:
1.145 +
1.146 + RESET = 0
1.147 + DIS = 0
1.148 + CS/SSEL = 0
1.149 + */
1.150 +
1.151 + epd_select();
1.152 + epd_rst_low();
1.153 +
1.154 + shift_select();
1.155 + shift_init(); /* PANEL = DIS = 0 */
1.156 +
1.157 + printf("RESET = PANEL = DIS = 0\n");
1.158 +
1.159 + /* Then, the following:
1.160 +
1.161 + PWM = 1/0 (5ms)
1.162 + PANEL = 1
1.163 + PWM = 1/0 (10ms)
1.164 + BORDER = 1?
1.165 + RESET = 1
1.166 + PWM = 1/0 (5ms)
1.167 + RESET = 0
1.168 + PWM = 1/0 (5ms)
1.169 + RESET = 1
1.170 + PWM = 1/0 (5ms)
1.171 +
1.172 + (Could shift 1 -> PANEL => PANEL=1, DIS=0
1.173 + or 1, 1 -> PANEL, BORDER => PANEL=1, BORDER=1, DIS=0)
1.174 + */
1.175 +
1.176 + epd_select();
1.177 + epd_spi_init();
1.178 + printf("PWM at 5ms starting: %u\n", bsp_getMsTicks());
1.179 + epd_pwm_active(5);
1.180 + printf("PWM at 5ms done: %u\n", bsp_getMsTicks());
1.181 +
1.182 + shift_select();
1.183 + shift_init(); /* PANEL = DIS = 0 (still) */
1.184 + shift_in(1); /* PANEL = 1 */
1.185 + shift_update();
1.186 + printf("PANEL = 1\n");
1.187 +
1.188 + epd_select();
1.189 + printf("PWM at 10ms starting: %u\n", bsp_getMsTicks());
1.190 + epd_pwm_active(10);
1.191 + printf("PWM at 10ms done: %u\n", bsp_getMsTicks());
1.192 + epd_cs_high();
1.193 + epd_rst_high();
1.194 + printf("PWM at 5ms starting: %u\n", bsp_getMsTicks());
1.195 + epd_pwm_active(5);
1.196 + printf("PWM at 5ms done: %u\n", bsp_getMsTicks());
1.197 + epd_rst_low();
1.198 + printf("PWM at 5ms starting: %u\n", bsp_getMsTicks());
1.199 + epd_pwm_active(5);
1.200 + printf("PWM at 5ms done: %u\n", bsp_getMsTicks());
1.201 + epd_rst_high();
1.202 + printf("PWM at 5ms starting: %u\n", bsp_getMsTicks());
1.203 + epd_pwm_active(5);
1.204 + printf("PWM at 5ms done: %u\n", bsp_getMsTicks());
1.205 +
1.206 + printf("Hardware powered.\n");
1.207 +}
1.208 +
1.209 +void bsp_pwm_active(uint16_t delayInMs)
1.210 +{
1.211 + uint16_t numOfIterations;
1.212 +
1.213 + numOfIterations = delayInMs * 100;
1.214 + for (; numOfIterations > 0; numOfIterations--)
1.215 + {
1.216 + // PWM_SET_HIGH;
1.217 + SET(EPD_PWM);
1.218 + bsp_delayUs(5); //100kHz (96kHz ideal)
1.219 + // PWM_SET_LOW;
1.220 + CLR(EPD_PWM);
1.221 + bsp_delayUs(5);
1.222 + }
1.223 +}
1.224 +
1.225 +void bsp_Shutdown()
1.226 +{
1.227 + /* This should complete the power off operation as follows:
1.228 +
1.229 + RESET = 0
1.230 + CS/SSEL = 0
1.231 + PANEL = 0
1.232 + BORDER = 0?
1.233 + DIS = 1
1.234 + DIS = 0 (after 150ms)
1.235 +
1.236 + (Could shift 0 -> PANEL => PANEL=0, DIS=1
1.237 + or 0, 0 -> PANEL, BORDER => PANEL=0, BORDER=0, DIS=1)
1.238 + */
1.239 +
1.240 + epd_select();
1.241 + epd_rst_low();
1.242 + epd_cs_low();
1.243 + epd_spi_detach();
1.244 +
1.245 + shift_reinit();
1.246 + shift_select();
1.247 + shift_in(0); /* PANEL = 0; DIS = 1 */
1.248 + shift_update();
1.249 + printf("Wait for 150ms, starting: %u\n", bsp_getMsTicks());
1.250 + epd_delay_ms(150);
1.251 + printf("Wait for 150ms, done: %u\n", bsp_getMsTicks());
1.252 + shift_in(0); /* PANEL = 0; DIS = 0 */
1.253 + shift_update();
1.254 +
1.255 + printf("Hardware shut down.\n");
1.256 +}
1.257 +
1.258 +void bsp_spiInit()
1.259 +{
1.260 + CLR(EPD_SCK);
1.261 +}
1.262 +
1.263 +/**
1.264 + * Send the given value via MOSI.
1.265 + */
1.266 +void bsp_writeToDisplay(uint8_t *data, uint16_t len)
1.267 +{
1.268 + uint8_t mask, *ptr, *limit = data + len;
1.269 +
1.270 + for (ptr = data; ptr < limit; ptr++)
1.271 + {
1.272 + for (mask = 0x80; mask; mask >>= 1)
1.273 + {
1.274 + if (*ptr & mask)
1.275 + {
1.276 + SET(EPD_MOSI);
1.277 + }
1.278 + else
1.279 + {
1.280 + CLR(EPD_MOSI);
1.281 + }
1.282 +
1.283 + SET(EPD_SCK);
1.284 + CLR(EPD_SCK);
1.285 + }
1.286 + }
1.287 +}
1.288 +
1.289 +void bsp_delayMs(uint32_t ms)
1.290 +{
1.291 + bsp_delayUs(ms * 1000);
1.292 +}
1.293 +
1.294 +void bsp_delayUs(uint32_t us)
1.295 +{
1.296 + #ifndef NANONOTE
1.297 + struct timespec tv;
1.298 + tv.tv_sec = 0;
1.299 + tv.tv_nsec = us * 100;
1.300 + nanosleep(&tv, NULL);
1.301 + #else
1.302 + uint64_t i = us * 16;
1.303 + while (i-- > 0);
1.304 + #endif
1.305 +}
1.306 +
1.307 +uint32_t bsp_getMsTicks()
1.308 +{
1.309 + struct timeval tv;
1.310 + gettimeofday(&tv, NULL);
1.311 + return tv.tv_sec * 1000 + tv.tv_usec / 1000;
1.312 +}
1.313 +
1.314 +/* Unsupported. */
1.315 +
1.316 +int16_t bsp_getTemp()
1.317 +{
1.318 + return 20;
1.319 +}