A web server for monitoring and controlling a MakerBot Replicator over the USB host and ethernet.

Dependencies:   IAP NTPClient RTC mbed-rtos mbed Socket lwip-sys lwip BurstSPI

Fork of LPC1768_Mini-DK by Frank Vannieuwkerke

Makerbot Server for LPC1768 Copyright (c) 2013, jake (at) allaboutjake (dot) com All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  • The name of the author and/or copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER, AUTHOR, OR ANY CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Warnings:

This is not a commercial product or a hardened and secure network appliance. It is intended as a thought experiment or proof of concept and should not be relied upon in any way. Always operate your 3D printer in a safe and controlled manner.

Do not connect this directly to the exposed internet. It is intended to be behind a secure firewall (and NAT) such that it will only accept commands from the local network. Imagine how much fun a hacker could have instructing your 3D printer to continually print Standford bunnies. Well it could be much worse then that- a malicious user could send commands that could crash your machine (both in the software sense, as well as in the "smash your moving parts against the side of the machine repeatedly sense), overheat your extruders, cause your build plate to catch fire, and do severe damage to the machine, any surrounding building and propery. You have been warned.

Never print unattended and be ready to step in and stop the machine if something goes wrong. Keep in mind, a 3D printer has heaters that are operating at high temperatures, and if something starts to burn, it could cause damage to the machine, other property, and/or hurt yourself, pets, or others.

You should understand what you are doing. The source code here is not intended as a finished product or set of step by step instructions. You should engineer your own solution, which may wind up being better than mine.

Proceed at your own risk. You've been warned. (Several times) If you break your Makerbot, burn your house down, or injure yourself or others, I take no responsibility.

Introduction

I've been working on a side project to solve the "last mile" problem for people wanting to print from the network on their bots. I feel like the first half of the problem is solved with the FlashAir- getting the files to the card. The next step is a lightweight way of sending the "play back capture" command to the bot.

I looked around for a microcontroller platform that supports both networking and can function as a USB host. I happened to have an mbed (mbed) on hand that fit the bill. The mbed also has a working online toolchain (you need to own an mbed to gain access to the compiler). Some people don't like the online development environment, but I'm a fan of "working" and "Mac compatible." It was a good start, but cost wise, you would need an mbed LPC1768 module and some sort of carrier board that has both USB host and ethernet, or rig up your own connector solution. I happened to also have a Seedstudio mbed shield carrier board. This provides ethernet and USB connectors, but is another $25, putting the solution at around $75.

I also had an LPC1768 development board here called the "Mini-DK2". It has a USB host and a wired ethernet connector on board (search ebay if you're interested). It's a single-board solution that costs only $32 (and for $40 you can get one with a touchscreen) Its the cheapest development board I've seen with both USB host and an ethernet connector. I considered RasPi, but I'm not on that bandwagon. Since I had the Mini-DK2 on hand from another project that never went anywhere, I moved from the mbed module and carrier board to the DK2.

The mbed environment can compile binaries that work on the DK2 (again, you need to own at least one 1768 mbed already to get a license to use the compiler), and the mbed libraries provide some nice features. A USB Host library and and Ethernet library were readily available. The USBHost library didn't quite work out of the box. It took some time and more learning about the USB protocols than I would have liked, but I have the board communicating over the USB Host and the Makerbot.

Changes to stock mbed libraries

Many libraries are imported, but then converted to folders as to unlink them.

mbed provides a USHost library that includes a USBHostSerial object for connecting to CDC serial devices. Unfortunately, it did not work for me out of the box. I spent some time learning about USB protocols. One good reference is [Jan Axelson's Lakeview Research](http://www.lvr.com/usb_virtual_com_port.htm) discussion about CDC.

I found that the stock library was sending the control transfers to Interface 1. From what I understand, the control transfers needed to go to interface 0. I modified the USBHostSerial library to correct this, and the serial port interface came to life.

Next, I found that I wasn't able to get reliable communication. I traced it to what I think is an odd C++ inheritance and override problem. The USBHostSerial class implements the Stream interface, allowing printf/scanf operations. This is done by overriding the virtual _getc and _putc methods. Unfortunately, and for a reason I can't understand, these methods were not being called consistently. Sometimes they would work, but other times they would not. My solution was to implement transmit/receive methods with different names, and since the names were different, they seemed to get called consistently. I'd like to learn exactly what's going on here, but I don't feel like debugging it for academic purposes when it works just fine with the added methods.

Usage

Connect up your chosen dev board to power, ethernet and the USB host to the Makerbot's USB cable. The Mini-DK uses a USB-OTG adapter for the USB host. If you're using a Mini-DK board with an LCD, it will inform you of it's IP address on the display. This means it is now listening for a connection on port 7654.

If you are using an mbed dev board, or a Mini-DK without a display, the message will be directed to the serial console. Connect your computer to the appropriate port at a baud rate of 115200 to see the messages.

Use a telnet client to connect to the given IP address at port 7654. Telnet clients typically revert to "line mode" on ports other than 21. This means you get a local echo and the command isn't sent until you press enter.

Once connected, you can send the following commands:

A <username>:<password> : Set a username & password for the web interface and the telnet interface. Use the format shown with a colon separating the username from the password.

V : Print the version and Makerbot name, as well as the local firmware version (the Makerbot_Server firmware as discussed here).

B <filename.x3g> : Build from SD the given filename. According tot he protocol spec, this command is limited to 12 characters, so 8.3 filenames only.

P : Pause an active build

R : Resume active build

C : Cancel build- note that this immediately halts the build and does not clear the build area. You might want to pause the build first, and then cancel shortly after to make sure the nozzle isn't left hot and in contact with a printed part.

S : Print build status, tool and platform temps

Q : Quit and logout

The Mini-DK has two onboard buttons (besides the ISP and reset buttons). Currently one button will trigger a pause (if the Makerbot is printing) and the other will resume (if the Makerbot it paused)

Compiling

Edit "Target.h" to set whether you're building for an MBED module or the Mini-DK2

Installation

If you are using a mbed, then you can simply load the BIN file to the mbed using the mass storage bootloader. The mbed mounts as if it were a USB thumbdrive, and you copy the BIN file to the drive. After a reset, you're running the installed firmware.

The MiniDK has a serial bootloader. You connect to this bootloader from the "top" USB connector (not the USB host one). Hold down the ISP button and then tap the reset button and then release the ISP button to put it into programming mode. I use [lpc21isp](http://sourceforge.net/projects/lpc21isp/) to load the binary. The other option is FlashMagic, which uses HEX files, so you'll need to use some sort of bin2hex utility to convert the firmware file if you use this utility. I can't really say if/how this works, as I don't use this method. See this (http://mbed.org/users/frankvnk/notebook/lpc1768-mini-dk/) for more info.

Credits

Some credits, where credit is due.

EthernetInterface - modified to include PHY code for both the MiniDK2 and MBED based on selected #definitions

Mini-DK - Thanks for Frank and Erik for doing all the heavy lifting getting the MBED compiler and libraries and peripherals working on the Mini-DK2

NTP Client - Thanks to Donatien for this library to set the clock over the network

RTC - Thanks to Erik for the RTC library. I've got it in my project, but I don't think I'm using it for anything (yet).

SimpleSocket - Thanks to Yamaguchi-san. Modified slightly to take out references to EthernetInterface::init() and ::getIPAddress(). For some reason these don't like to be called in a thread.

JPEGCamera - Thanks again to Yamaguchi-san. Modified to output the JPEG binary over a socket rather than to a file descriptor.

USBHost - modified as noted above

IAP - Thanks to Okano-san. Pulled out of the Mini-DK folder so that I could link it back to the base repository at the root level.

Committer:
frankvnk
Date:
Tue Dec 11 08:58:06 2012 +0000
Revision:
0:ee7076d8260a
Child:
1:557df792279c
First version - LCD and touch working - no Ethernet

Who changed what in which revision?

UserRevisionLine numberNew contents of line
frankvnk 0:ee7076d8260a 1 /* mbed library for 240*320 pixel TFT with ILI9320 LCD Controller
frankvnk 0:ee7076d8260a 2 * Rewrite from Peter Drescher code - http://mbed.org/cookbook/SPI-driven-QVGA-TFT
frankvnk 0:ee7076d8260a 3 *
frankvnk 0:ee7076d8260a 4 * TODO : BMP routine
frankvnk 0:ee7076d8260a 5 */
frankvnk 0:ee7076d8260a 6
frankvnk 0:ee7076d8260a 7
frankvnk 0:ee7076d8260a 8
frankvnk 0:ee7076d8260a 9 #include "SPI_TFT.h"
frankvnk 0:ee7076d8260a 10 #include "mbed.h"
frankvnk 0:ee7076d8260a 11
frankvnk 0:ee7076d8260a 12
frankvnk 0:ee7076d8260a 13 #define BPP 16 // Bits per pixel
frankvnk 0:ee7076d8260a 14
frankvnk 0:ee7076d8260a 15
frankvnk 0:ee7076d8260a 16 SPI_TFT::SPI_TFT(PinName mosi, PinName miso, PinName sclk, PinName cs, PinName reset, const char *name)
frankvnk 0:ee7076d8260a 17 : _spi(mosi, miso, sclk), _cs(cs), _reset(reset),GraphicsDisplay(name)
frankvnk 0:ee7076d8260a 18 {
frankvnk 0:ee7076d8260a 19 char_x = 0;
frankvnk 0:ee7076d8260a 20 tft_reset();
frankvnk 0:ee7076d8260a 21 set_orientation(0);
frankvnk 0:ee7076d8260a 22 }
frankvnk 0:ee7076d8260a 23
frankvnk 0:ee7076d8260a 24 int SPI_TFT::width()
frankvnk 0:ee7076d8260a 25 {
frankvnk 0:ee7076d8260a 26 if (orientation == 0 || orientation == 2) return 240;
frankvnk 0:ee7076d8260a 27 else return 320;
frankvnk 0:ee7076d8260a 28 }
frankvnk 0:ee7076d8260a 29
frankvnk 0:ee7076d8260a 30 int SPI_TFT::height()
frankvnk 0:ee7076d8260a 31 {
frankvnk 0:ee7076d8260a 32 if (orientation == 0 || orientation == 2) return 320;
frankvnk 0:ee7076d8260a 33 else return 240;
frankvnk 0:ee7076d8260a 34 }
frankvnk 0:ee7076d8260a 35
frankvnk 0:ee7076d8260a 36 //
frankvnk 0:ee7076d8260a 37 void SPI_TFT::set_orientation(unsigned int o)
frankvnk 0:ee7076d8260a 38 {
frankvnk 0:ee7076d8260a 39 orientation = o;
frankvnk 0:ee7076d8260a 40 WindowMax();
frankvnk 0:ee7076d8260a 41 }
frankvnk 0:ee7076d8260a 42
frankvnk 0:ee7076d8260a 43 // ILI9320
frankvnk 0:ee7076d8260a 44 // Orientation is only set before a window command (registers 0x50..0x53)
frankvnk 0:ee7076d8260a 45 // reg 03h (Entry Mode) : BGR = 1 - ORG = 1 - ID0, ID1 and AM are set according to the orientation variable.
frankvnk 0:ee7076d8260a 46 // IMPORTANT : when ORG = 1, the GRAM writing direction follows the orientation (ID0, ID1, AM bits)
frankvnk 0:ee7076d8260a 47 // AND we need to use the window command (reg 50h..53h) to write to an area on the display
frankvnk 0:ee7076d8260a 48 // because we cannot change reg 20h and 21h to set the GRAM address (they both remain at 00h).
frankvnk 0:ee7076d8260a 49 // This means that the pixel routine does not work when ORG = 1.
frankvnk 0:ee7076d8260a 50 // Routines relying on the pixel routine first need to set reg 03h = 0x1030
frankvnk 0:ee7076d8260a 51 // (cls, circle and line do so) AND need to write the data according to the orientation variable.
frankvnk 0:ee7076d8260a 52
frankvnk 0:ee7076d8260a 53 void SPI_TFT::mod_orientation(void)
frankvnk 0:ee7076d8260a 54 {
frankvnk 0:ee7076d8260a 55 switch (orientation)
frankvnk 0:ee7076d8260a 56 {
frankvnk 0:ee7076d8260a 57 case 0:
frankvnk 0:ee7076d8260a 58 wr_reg(0x03, 0x10b0); // ID1 = 1, ID0 = 1, AM = 0 - Portrait
frankvnk 0:ee7076d8260a 59 break;
frankvnk 0:ee7076d8260a 60 case 1:
frankvnk 0:ee7076d8260a 61 wr_reg(0x03, 0x10a8); // ID1 = 1, ID0 = 0, AM = 0 - Landscape
frankvnk 0:ee7076d8260a 62 break;
frankvnk 0:ee7076d8260a 63 case 2:
frankvnk 0:ee7076d8260a 64 wr_reg(0x03, 0x1080); // ID1 = 0, ID0 = 0, AM = 1 - Portrait upside down
frankvnk 0:ee7076d8260a 65 break;
frankvnk 0:ee7076d8260a 66 case 3:
frankvnk 0:ee7076d8260a 67 wr_reg(0x03, 0x1098); // ID1 = 0, ID0 = 1, AM = 1 - Landscape upside down
frankvnk 0:ee7076d8260a 68 break;
frankvnk 0:ee7076d8260a 69 }
frankvnk 0:ee7076d8260a 70 }
frankvnk 0:ee7076d8260a 71
frankvnk 0:ee7076d8260a 72 void SPI_TFT::wr_cmd(unsigned char cmd)
frankvnk 0:ee7076d8260a 73 {
frankvnk 0:ee7076d8260a 74 _cs = 0;
frankvnk 0:ee7076d8260a 75 _spi.write(0x70);
frankvnk 0:ee7076d8260a 76 _spi.write(0x00);
frankvnk 0:ee7076d8260a 77 _spi.write(cmd);
frankvnk 0:ee7076d8260a 78 _cs = 1;
frankvnk 0:ee7076d8260a 79 }
frankvnk 0:ee7076d8260a 80
frankvnk 0:ee7076d8260a 81 void SPI_TFT::wr_dat(unsigned short dat)
frankvnk 0:ee7076d8260a 82 {
frankvnk 0:ee7076d8260a 83 unsigned char u,l;
frankvnk 0:ee7076d8260a 84 u = (dat >> 0x08);
frankvnk 0:ee7076d8260a 85 l = (dat & 0xff);
frankvnk 0:ee7076d8260a 86 _cs = 0;
frankvnk 0:ee7076d8260a 87 _spi.write(0x72);
frankvnk 0:ee7076d8260a 88 _spi.write(u);
frankvnk 0:ee7076d8260a 89 _spi.write(l);
frankvnk 0:ee7076d8260a 90 _cs = 1;
frankvnk 0:ee7076d8260a 91 }
frankvnk 0:ee7076d8260a 92
frankvnk 0:ee7076d8260a 93 void SPI_TFT::wr_dat_start(void)
frankvnk 0:ee7076d8260a 94 {
frankvnk 0:ee7076d8260a 95 _spi.write(0x72);
frankvnk 0:ee7076d8260a 96 }
frankvnk 0:ee7076d8260a 97
frankvnk 0:ee7076d8260a 98 void SPI_TFT::wr_dat_only(unsigned short dat)
frankvnk 0:ee7076d8260a 99 {
frankvnk 0:ee7076d8260a 100 unsigned char u,l;
frankvnk 0:ee7076d8260a 101 u = (dat >> 0x08);
frankvnk 0:ee7076d8260a 102 l = (dat & 0xff);
frankvnk 0:ee7076d8260a 103 _spi.write(u);
frankvnk 0:ee7076d8260a 104 _spi.write(l);
frankvnk 0:ee7076d8260a 105 }
frankvnk 0:ee7076d8260a 106
frankvnk 0:ee7076d8260a 107 unsigned short SPI_TFT::rd_dat(void) // SPI frequency needs to be lowered on read
frankvnk 0:ee7076d8260a 108 {
frankvnk 0:ee7076d8260a 109 unsigned short val = 0;
frankvnk 0:ee7076d8260a 110 _cs = 0;
frankvnk 0:ee7076d8260a 111 _spi.frequency(SPI_F_LO);
frankvnk 0:ee7076d8260a 112 _spi.write(0x73);
frankvnk 0:ee7076d8260a 113 _spi.write(0x00);
frankvnk 0:ee7076d8260a 114 val = _spi.write(0); // Dummy read
frankvnk 0:ee7076d8260a 115 val = _spi.write(0); // Read D8..D15
frankvnk 0:ee7076d8260a 116 val <<= 8;
frankvnk 0:ee7076d8260a 117 val |= _spi.write(0); // Read D0..D7
frankvnk 0:ee7076d8260a 118 _cs = 1;
frankvnk 0:ee7076d8260a 119 _spi.frequency(SPI_F_HI);
frankvnk 0:ee7076d8260a 120 return (val);
frankvnk 0:ee7076d8260a 121 }
frankvnk 0:ee7076d8260a 122
frankvnk 0:ee7076d8260a 123 void SPI_TFT::wr_reg(unsigned char reg, unsigned short val)
frankvnk 0:ee7076d8260a 124 {
frankvnk 0:ee7076d8260a 125 wr_cmd(reg);
frankvnk 0:ee7076d8260a 126 wr_dat(val);
frankvnk 0:ee7076d8260a 127 }
frankvnk 0:ee7076d8260a 128
frankvnk 0:ee7076d8260a 129 unsigned short SPI_TFT::rd_reg(unsigned char reg)
frankvnk 0:ee7076d8260a 130 {
frankvnk 0:ee7076d8260a 131 wr_cmd(reg);
frankvnk 0:ee7076d8260a 132 return(rd_dat());
frankvnk 0:ee7076d8260a 133 }
frankvnk 0:ee7076d8260a 134
frankvnk 0:ee7076d8260a 135 unsigned short SPI_TFT::Read_ID(void) // IMPORTANT : SPI frequency needs to be lowered when reading
frankvnk 0:ee7076d8260a 136 {
frankvnk 0:ee7076d8260a 137 unsigned short val = 0;
frankvnk 0:ee7076d8260a 138 _cs = 0;
frankvnk 0:ee7076d8260a 139 _spi.write(0x70);
frankvnk 0:ee7076d8260a 140 _spi.write(0x00);
frankvnk 0:ee7076d8260a 141 _spi.write(0X00);
frankvnk 0:ee7076d8260a 142 _cs = 1;
frankvnk 0:ee7076d8260a 143 _spi.frequency(SPI_F_LO);
frankvnk 0:ee7076d8260a 144 _cs = 0;
frankvnk 0:ee7076d8260a 145 _spi.write(0x73);
frankvnk 0:ee7076d8260a 146 val = _spi.write(0x00); // Dummy read
frankvnk 0:ee7076d8260a 147 val = _spi.write(0x00); // Read D8..D15
frankvnk 0:ee7076d8260a 148 val <<= 8;
frankvnk 0:ee7076d8260a 149 val |= _spi.write(0x00); // Read D0..D7
frankvnk 0:ee7076d8260a 150 _cs = 1;
frankvnk 0:ee7076d8260a 151 _spi.frequency(SPI_F_HI);
frankvnk 0:ee7076d8260a 152 return (val);
frankvnk 0:ee7076d8260a 153 }
frankvnk 0:ee7076d8260a 154
frankvnk 0:ee7076d8260a 155 void SPI_TFT::SetCursor( unsigned short Xpos, unsigned short Ypos )
frankvnk 0:ee7076d8260a 156 {
frankvnk 0:ee7076d8260a 157 wr_reg(0x20, Xpos );
frankvnk 0:ee7076d8260a 158 wr_reg(0x21, Ypos );
frankvnk 0:ee7076d8260a 159 }
frankvnk 0:ee7076d8260a 160
frankvnk 0:ee7076d8260a 161 void SPI_TFT::tft_reset()
frankvnk 0:ee7076d8260a 162 {
frankvnk 0:ee7076d8260a 163 _spi.format(8,3); // 8 bit spi mode 3
frankvnk 0:ee7076d8260a 164 _spi.frequency(SPI_F_HI); // 48 Mhz SPI clock
frankvnk 0:ee7076d8260a 165
frankvnk 0:ee7076d8260a 166 wr_reg(0x00,0x0000);
frankvnk 0:ee7076d8260a 167 wr_reg(0x01,0x0100); // Driver Output Control
frankvnk 0:ee7076d8260a 168 wr_reg(0x02,0x0700); // LCD Driver Waveform Control
frankvnk 0:ee7076d8260a 169 wr_reg(0x03,0x1030); // Set the scan mode
frankvnk 0:ee7076d8260a 170 wr_reg(0x04,0x0000); // Scaling Control
frankvnk 0:ee7076d8260a 171 wr_reg(0x08,0x0202); // Display Control 2
frankvnk 0:ee7076d8260a 172 wr_reg(0x09,0x0000); // Display Control 3
frankvnk 0:ee7076d8260a 173 wr_reg(0x0a,0x0000); // Frame Cycle Contal
frankvnk 0:ee7076d8260a 174 wr_reg(0x0c,(1<<0)); // Extern Display Interface Control 1
frankvnk 0:ee7076d8260a 175 wr_reg(0x0d,0x0000); // Frame Maker Position
frankvnk 0:ee7076d8260a 176 wr_reg(0x0f,0x0000); // Extern Display Interface Control 2
frankvnk 0:ee7076d8260a 177
frankvnk 0:ee7076d8260a 178 wait_ms(50);
frankvnk 0:ee7076d8260a 179
frankvnk 0:ee7076d8260a 180 wr_reg(0x07,0x0101); // Display Control
frankvnk 0:ee7076d8260a 181
frankvnk 0:ee7076d8260a 182 wait_ms(50);
frankvnk 0:ee7076d8260a 183
frankvnk 0:ee7076d8260a 184 wr_reg(0x10,(1<<12)|(0<<8)|(1<<7)|(1<<6)|(0<<4)); // Power Control 1
frankvnk 0:ee7076d8260a 185 wr_reg(0x11,0x0007); // Power Control 2
frankvnk 0:ee7076d8260a 186 wr_reg(0x12,(1<<8)|(1<<4)|(0<<0)); // Power Control 3
frankvnk 0:ee7076d8260a 187 wr_reg(0x13,0x0b00); // Power Control 4
frankvnk 0:ee7076d8260a 188 wr_reg(0x29,0x0000); // Power Control 7
frankvnk 0:ee7076d8260a 189 wr_reg(0x2b,(1<<14)|(1<<4));
frankvnk 0:ee7076d8260a 190
frankvnk 0:ee7076d8260a 191 wr_reg(0x50,0); // Set X Start
frankvnk 0:ee7076d8260a 192 wr_reg(0x51,239); // Set X End
frankvnk 0:ee7076d8260a 193 wr_reg(0x52,0); // Set Y Start
frankvnk 0:ee7076d8260a 194 wr_reg(0x53,319); // Set Y End
frankvnk 0:ee7076d8260a 195
frankvnk 0:ee7076d8260a 196 wait_ms(50);
frankvnk 0:ee7076d8260a 197
frankvnk 0:ee7076d8260a 198 wr_reg(0x60,0x2700); // Driver Output Control
frankvnk 0:ee7076d8260a 199 wr_reg(0x61,0x0001); // Driver Output Control
frankvnk 0:ee7076d8260a 200 wr_reg(0x6a,0x0000); // Vertical Srcoll Control
frankvnk 0:ee7076d8260a 201
frankvnk 0:ee7076d8260a 202 wr_reg(0x80,0x0000); // Display Position Partial Display 1
frankvnk 0:ee7076d8260a 203 wr_reg(0x81,0x0000); // RAM Address Start Partial Display 1
frankvnk 0:ee7076d8260a 204 wr_reg(0x82,0x0000); // RAM Address End-Partial Display 1
frankvnk 0:ee7076d8260a 205 wr_reg(0x83,0x0000); // Displsy Position Partial Display 2
frankvnk 0:ee7076d8260a 206 wr_reg(0x84,0x0000); // RAM Address Start Partial Display 2
frankvnk 0:ee7076d8260a 207 wr_reg(0x85,0x0000); // RAM Address End Partial Display 2
frankvnk 0:ee7076d8260a 208
frankvnk 0:ee7076d8260a 209 wr_reg(0x90,(0<<7)|(16<<0)); // Frame Cycle Control
frankvnk 0:ee7076d8260a 210 wr_reg(0x92,0x0000); // Panel Interface Control 2
frankvnk 0:ee7076d8260a 211 wr_reg(0x93,0x0001); // Panel Interface Control 3
frankvnk 0:ee7076d8260a 212 wr_reg(0x95,0x0110); // Frame Cycle Control
frankvnk 0:ee7076d8260a 213 wr_reg(0x97,(0<<8));
frankvnk 0:ee7076d8260a 214 wr_reg(0x98,0x0000); // Frame Cycle Control
frankvnk 0:ee7076d8260a 215 wr_reg(0x07,0x0133);
frankvnk 0:ee7076d8260a 216
frankvnk 0:ee7076d8260a 217 wait_ms(100);
frankvnk 0:ee7076d8260a 218 WindowMax();
frankvnk 0:ee7076d8260a 219 }
frankvnk 0:ee7076d8260a 220
frankvnk 0:ee7076d8260a 221
frankvnk 0:ee7076d8260a 222 void SPI_TFT::pixel(int x, int y, int color)
frankvnk 0:ee7076d8260a 223 {
frankvnk 0:ee7076d8260a 224 switch (orientation)
frankvnk 0:ee7076d8260a 225 {
frankvnk 0:ee7076d8260a 226 case 0:
frankvnk 0:ee7076d8260a 227 wr_reg(0x20, x);
frankvnk 0:ee7076d8260a 228 wr_reg(0x21, y);
frankvnk 0:ee7076d8260a 229 break;
frankvnk 0:ee7076d8260a 230 case 1:
frankvnk 0:ee7076d8260a 231 wr_reg(0x20, 239-y);
frankvnk 0:ee7076d8260a 232 wr_reg(0x21, x);
frankvnk 0:ee7076d8260a 233 break;
frankvnk 0:ee7076d8260a 234 case 2:
frankvnk 0:ee7076d8260a 235 wr_reg(0x20, 239-x);
frankvnk 0:ee7076d8260a 236 wr_reg(0x21, 319-y);
frankvnk 0:ee7076d8260a 237 break;
frankvnk 0:ee7076d8260a 238 case 3:
frankvnk 0:ee7076d8260a 239 wr_reg(0x20, y);
frankvnk 0:ee7076d8260a 240 wr_reg(0x21, 319-x);
frankvnk 0:ee7076d8260a 241 break;
frankvnk 0:ee7076d8260a 242 }
frankvnk 0:ee7076d8260a 243 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 244 wr_dat(color);
frankvnk 0:ee7076d8260a 245 }
frankvnk 0:ee7076d8260a 246
frankvnk 0:ee7076d8260a 247
frankvnk 0:ee7076d8260a 248 void SPI_TFT::window(unsigned int x, unsigned int y, unsigned int w, unsigned int h)
frankvnk 0:ee7076d8260a 249 {
frankvnk 0:ee7076d8260a 250 unsigned int xw1, yh1;
frankvnk 0:ee7076d8260a 251 xw1 = x + w - 1;
frankvnk 0:ee7076d8260a 252 yh1 = y + h - 1;
frankvnk 0:ee7076d8260a 253 wr_reg(0x20, x);
frankvnk 0:ee7076d8260a 254 wr_reg(0x21, y);
frankvnk 0:ee7076d8260a 255 switch (orientation)
frankvnk 0:ee7076d8260a 256 {
frankvnk 0:ee7076d8260a 257 case 0:
frankvnk 0:ee7076d8260a 258 wr_reg(0x50, x);
frankvnk 0:ee7076d8260a 259 wr_reg(0x51, xw1);
frankvnk 0:ee7076d8260a 260 wr_reg(0x52, y);
frankvnk 0:ee7076d8260a 261 wr_reg(0x53, yh1);
frankvnk 0:ee7076d8260a 262 break;
frankvnk 0:ee7076d8260a 263 case 1:
frankvnk 0:ee7076d8260a 264 wr_reg(0x50, 239 - yh1);
frankvnk 0:ee7076d8260a 265 wr_reg(0x51, 239 - y);
frankvnk 0:ee7076d8260a 266 wr_reg(0x52, x);
frankvnk 0:ee7076d8260a 267 wr_reg(0x53, xw1);
frankvnk 0:ee7076d8260a 268 break;
frankvnk 0:ee7076d8260a 269 case 2:
frankvnk 0:ee7076d8260a 270 wr_reg(0x50, 239 - xw1);
frankvnk 0:ee7076d8260a 271 wr_reg(0x51, 239 - x);
frankvnk 0:ee7076d8260a 272 wr_reg(0x52, 319 - yh1);
frankvnk 0:ee7076d8260a 273 wr_reg(0x53, 319 - y);
frankvnk 0:ee7076d8260a 274 break;
frankvnk 0:ee7076d8260a 275 case 3:
frankvnk 0:ee7076d8260a 276 wr_reg(0x50, y);
frankvnk 0:ee7076d8260a 277 wr_reg(0x51, yh1);
frankvnk 0:ee7076d8260a 278 wr_reg(0x52, 319 - xw1);
frankvnk 0:ee7076d8260a 279 wr_reg(0x53, 319 - x);
frankvnk 0:ee7076d8260a 280 break;
frankvnk 0:ee7076d8260a 281 }
frankvnk 0:ee7076d8260a 282 }
frankvnk 0:ee7076d8260a 283
frankvnk 0:ee7076d8260a 284
frankvnk 0:ee7076d8260a 285 void SPI_TFT::WindowMax(void)
frankvnk 0:ee7076d8260a 286 {
frankvnk 0:ee7076d8260a 287 window(0, 0, width(), height());
frankvnk 0:ee7076d8260a 288 }
frankvnk 0:ee7076d8260a 289
frankvnk 0:ee7076d8260a 290
frankvnk 0:ee7076d8260a 291 void SPI_TFT::cls (void)
frankvnk 0:ee7076d8260a 292 {
frankvnk 0:ee7076d8260a 293 unsigned long int index=0;
frankvnk 0:ee7076d8260a 294 int color = _background;
frankvnk 0:ee7076d8260a 295 wr_reg(0x03, 0x1030);
frankvnk 0:ee7076d8260a 296 WindowMax();
frankvnk 0:ee7076d8260a 297 SetCursor(0,0);
frankvnk 0:ee7076d8260a 298 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 299 _cs = 0;
frankvnk 0:ee7076d8260a 300 wr_dat_start();
frankvnk 0:ee7076d8260a 301 for( index = 0; index < width() * height(); index++ )
frankvnk 0:ee7076d8260a 302 {
frankvnk 0:ee7076d8260a 303 wr_dat_only(color);
frankvnk 0:ee7076d8260a 304 }
frankvnk 0:ee7076d8260a 305 _cs = 1;
frankvnk 0:ee7076d8260a 306 }
frankvnk 0:ee7076d8260a 307
frankvnk 0:ee7076d8260a 308
frankvnk 0:ee7076d8260a 309 void SPI_TFT::circle(int x0, int y0, int r, int color)
frankvnk 0:ee7076d8260a 310 {
frankvnk 0:ee7076d8260a 311 wr_reg(0x03, 0x1030);
frankvnk 0:ee7076d8260a 312 WindowMax();
frankvnk 0:ee7076d8260a 313
frankvnk 0:ee7076d8260a 314 int draw_x0, draw_y0;
frankvnk 0:ee7076d8260a 315 int draw_x1, draw_y1;
frankvnk 0:ee7076d8260a 316 int draw_x2, draw_y2;
frankvnk 0:ee7076d8260a 317 int draw_x3, draw_y3;
frankvnk 0:ee7076d8260a 318 int draw_x4, draw_y4;
frankvnk 0:ee7076d8260a 319 int draw_x5, draw_y5;
frankvnk 0:ee7076d8260a 320 int draw_x6, draw_y6;
frankvnk 0:ee7076d8260a 321 int draw_x7, draw_y7;
frankvnk 0:ee7076d8260a 322 int xx, yy;
frankvnk 0:ee7076d8260a 323 int di;
frankvnk 0:ee7076d8260a 324 if (r == 0) { /* no radius */
frankvnk 0:ee7076d8260a 325 return;
frankvnk 0:ee7076d8260a 326 }
frankvnk 0:ee7076d8260a 327
frankvnk 0:ee7076d8260a 328 draw_x0 = draw_x1 = x0;
frankvnk 0:ee7076d8260a 329 draw_y0 = draw_y1 = y0 + r;
frankvnk 0:ee7076d8260a 330 if (draw_y0 < height()) {
frankvnk 0:ee7076d8260a 331 pixel(draw_x0, draw_y0, color); /* 90 degree */
frankvnk 0:ee7076d8260a 332 }
frankvnk 0:ee7076d8260a 333
frankvnk 0:ee7076d8260a 334 draw_x2 = draw_x3 = x0;
frankvnk 0:ee7076d8260a 335 draw_y2 = draw_y3 = y0 - r;
frankvnk 0:ee7076d8260a 336 if (draw_y2 >= 0) {
frankvnk 0:ee7076d8260a 337 pixel(draw_x2, draw_y2, color); /* 270 degree */
frankvnk 0:ee7076d8260a 338 }
frankvnk 0:ee7076d8260a 339
frankvnk 0:ee7076d8260a 340 draw_x4 = draw_x6 = x0 + r;
frankvnk 0:ee7076d8260a 341 draw_y4 = draw_y6 = y0;
frankvnk 0:ee7076d8260a 342 if (draw_x4 < width()) {
frankvnk 0:ee7076d8260a 343 pixel(draw_x4, draw_y4, color); /* 0 degree */
frankvnk 0:ee7076d8260a 344 }
frankvnk 0:ee7076d8260a 345
frankvnk 0:ee7076d8260a 346 draw_x5 = draw_x7 = x0 - r;
frankvnk 0:ee7076d8260a 347 draw_y5 = draw_y7 = y0;
frankvnk 0:ee7076d8260a 348 if (draw_x5>=0) {
frankvnk 0:ee7076d8260a 349 pixel(draw_x5, draw_y5, color); /* 180 degree */
frankvnk 0:ee7076d8260a 350 }
frankvnk 0:ee7076d8260a 351
frankvnk 0:ee7076d8260a 352 if (r == 1) {
frankvnk 0:ee7076d8260a 353 return;
frankvnk 0:ee7076d8260a 354 }
frankvnk 0:ee7076d8260a 355
frankvnk 0:ee7076d8260a 356 di = 3 - 2*r;
frankvnk 0:ee7076d8260a 357 xx = 0;
frankvnk 0:ee7076d8260a 358 yy = r;
frankvnk 0:ee7076d8260a 359 while (xx < yy) {
frankvnk 0:ee7076d8260a 360
frankvnk 0:ee7076d8260a 361 if (di < 0) {
frankvnk 0:ee7076d8260a 362 di += 4*xx + 6;
frankvnk 0:ee7076d8260a 363 } else {
frankvnk 0:ee7076d8260a 364 di += 4*(xx - yy) + 10;
frankvnk 0:ee7076d8260a 365 yy--;
frankvnk 0:ee7076d8260a 366 draw_y0--;
frankvnk 0:ee7076d8260a 367 draw_y1--;
frankvnk 0:ee7076d8260a 368 draw_y2++;
frankvnk 0:ee7076d8260a 369 draw_y3++;
frankvnk 0:ee7076d8260a 370 draw_x4--;
frankvnk 0:ee7076d8260a 371 draw_x5++;
frankvnk 0:ee7076d8260a 372 draw_x6--;
frankvnk 0:ee7076d8260a 373 draw_x7++;
frankvnk 0:ee7076d8260a 374 }
frankvnk 0:ee7076d8260a 375 xx++;
frankvnk 0:ee7076d8260a 376 draw_x0++;
frankvnk 0:ee7076d8260a 377 draw_x1--;
frankvnk 0:ee7076d8260a 378 draw_x2++;
frankvnk 0:ee7076d8260a 379 draw_x3--;
frankvnk 0:ee7076d8260a 380 draw_y4++;
frankvnk 0:ee7076d8260a 381 draw_y5++;
frankvnk 0:ee7076d8260a 382 draw_y6--;
frankvnk 0:ee7076d8260a 383 draw_y7--;
frankvnk 0:ee7076d8260a 384
frankvnk 0:ee7076d8260a 385 if ( (draw_x0 <= width()) && (draw_y0>=0) ) {
frankvnk 0:ee7076d8260a 386 pixel(draw_x0, draw_y0, color);
frankvnk 0:ee7076d8260a 387 }
frankvnk 0:ee7076d8260a 388
frankvnk 0:ee7076d8260a 389 if ( (draw_x1 >= 0) && (draw_y1 >= 0) ) {
frankvnk 0:ee7076d8260a 390 pixel(draw_x1, draw_y1, color);
frankvnk 0:ee7076d8260a 391 }
frankvnk 0:ee7076d8260a 392
frankvnk 0:ee7076d8260a 393 if ( (draw_x2 <= width()) && (draw_y2 <= height()) ) {
frankvnk 0:ee7076d8260a 394 pixel(draw_x2, draw_y2, color);
frankvnk 0:ee7076d8260a 395 }
frankvnk 0:ee7076d8260a 396
frankvnk 0:ee7076d8260a 397 if ( (draw_x3 >=0 ) && (draw_y3 <= height()) ) {
frankvnk 0:ee7076d8260a 398 pixel(draw_x3, draw_y3, color);
frankvnk 0:ee7076d8260a 399 }
frankvnk 0:ee7076d8260a 400
frankvnk 0:ee7076d8260a 401 if ( (draw_x4 <= width()) && (draw_y4 >= 0) ) {
frankvnk 0:ee7076d8260a 402 pixel(draw_x4, draw_y4, color);
frankvnk 0:ee7076d8260a 403 }
frankvnk 0:ee7076d8260a 404
frankvnk 0:ee7076d8260a 405 if ( (draw_x5 >= 0) && (draw_y5 >= 0) ) {
frankvnk 0:ee7076d8260a 406 pixel(draw_x5, draw_y5, color);
frankvnk 0:ee7076d8260a 407 }
frankvnk 0:ee7076d8260a 408 if ( (draw_x6 <=width()) && (draw_y6 <= height()) ) {
frankvnk 0:ee7076d8260a 409 pixel(draw_x6, draw_y6, color);
frankvnk 0:ee7076d8260a 410 }
frankvnk 0:ee7076d8260a 411 if ( (draw_x7 >= 0) && (draw_y7 <= height()) ) {
frankvnk 0:ee7076d8260a 412 pixel(draw_x7, draw_y7, color);
frankvnk 0:ee7076d8260a 413 }
frankvnk 0:ee7076d8260a 414 }
frankvnk 0:ee7076d8260a 415 return;
frankvnk 0:ee7076d8260a 416 }
frankvnk 0:ee7076d8260a 417
frankvnk 0:ee7076d8260a 418 void SPI_TFT::fillcircle(int x, int y, int r, int color)
frankvnk 0:ee7076d8260a 419 {
frankvnk 0:ee7076d8260a 420 int i;
frankvnk 0:ee7076d8260a 421 for (i = 0; i <= r; i++)
frankvnk 0:ee7076d8260a 422 circle(x,y,i,color);
frankvnk 0:ee7076d8260a 423 }
frankvnk 0:ee7076d8260a 424
frankvnk 0:ee7076d8260a 425
frankvnk 0:ee7076d8260a 426
frankvnk 0:ee7076d8260a 427 void SPI_TFT::hline(int x0, int x1, int y, int color)
frankvnk 0:ee7076d8260a 428 {
frankvnk 0:ee7076d8260a 429 unsigned int index=0;
frankvnk 0:ee7076d8260a 430 int w;
frankvnk 0:ee7076d8260a 431 w = x1 - x0 + 1;
frankvnk 0:ee7076d8260a 432 mod_orientation();
frankvnk 0:ee7076d8260a 433 window(x0,y,w,1);
frankvnk 0:ee7076d8260a 434 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 435 _cs = 0;
frankvnk 0:ee7076d8260a 436 wr_dat_start();
frankvnk 0:ee7076d8260a 437 for( index = 0; index < (x1 - x0); index++ )
frankvnk 0:ee7076d8260a 438 {
frankvnk 0:ee7076d8260a 439 wr_dat_only(color);
frankvnk 0:ee7076d8260a 440 }
frankvnk 0:ee7076d8260a 441 _cs = 1;
frankvnk 0:ee7076d8260a 442 return;
frankvnk 0:ee7076d8260a 443 }
frankvnk 0:ee7076d8260a 444
frankvnk 0:ee7076d8260a 445 void SPI_TFT::vline(int x, int y0, int y1, int color)
frankvnk 0:ee7076d8260a 446 {
frankvnk 0:ee7076d8260a 447 unsigned int index=0;
frankvnk 0:ee7076d8260a 448 int h;
frankvnk 0:ee7076d8260a 449 h = y1 - y0 + 1;
frankvnk 0:ee7076d8260a 450 mod_orientation();
frankvnk 0:ee7076d8260a 451 window(x,y0,1,h);
frankvnk 0:ee7076d8260a 452 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 453 _cs = 0;
frankvnk 0:ee7076d8260a 454 wr_dat_start();
frankvnk 0:ee7076d8260a 455 for( index = 0; index < (y1 - y0); index++ )
frankvnk 0:ee7076d8260a 456 {
frankvnk 0:ee7076d8260a 457 wr_dat_only(color);
frankvnk 0:ee7076d8260a 458 }
frankvnk 0:ee7076d8260a 459 _cs = 1;
frankvnk 0:ee7076d8260a 460 return;
frankvnk 0:ee7076d8260a 461 }
frankvnk 0:ee7076d8260a 462
frankvnk 0:ee7076d8260a 463 void SPI_TFT::line(int x0, int y0, int x1, int y1, int color)
frankvnk 0:ee7076d8260a 464 {
frankvnk 0:ee7076d8260a 465 wr_reg(0x03, 0x1030);
frankvnk 0:ee7076d8260a 466 WindowMax();
frankvnk 0:ee7076d8260a 467 int dx = 0, dy = 0;
frankvnk 0:ee7076d8260a 468 int dx_sym = 0, dy_sym = 0;
frankvnk 0:ee7076d8260a 469 int dx_x2 = 0, dy_x2 = 0;
frankvnk 0:ee7076d8260a 470 int di = 0;
frankvnk 0:ee7076d8260a 471
frankvnk 0:ee7076d8260a 472 dx = x1-x0;
frankvnk 0:ee7076d8260a 473 dy = y1-y0;
frankvnk 0:ee7076d8260a 474
frankvnk 0:ee7076d8260a 475 if (dx == 0) { /* vertical line */
frankvnk 0:ee7076d8260a 476 if (y1 > y0) vline(x0,y0,y1,color);
frankvnk 0:ee7076d8260a 477 else vline(x0,y1,y0,color);
frankvnk 0:ee7076d8260a 478 return;
frankvnk 0:ee7076d8260a 479 }
frankvnk 0:ee7076d8260a 480
frankvnk 0:ee7076d8260a 481 if (dx > 0) {
frankvnk 0:ee7076d8260a 482 dx_sym = 1;
frankvnk 0:ee7076d8260a 483 } else {
frankvnk 0:ee7076d8260a 484 dx_sym = -1;
frankvnk 0:ee7076d8260a 485 }
frankvnk 0:ee7076d8260a 486 if (dy == 0) { /* horizontal line */
frankvnk 0:ee7076d8260a 487 if (x1 > x0) hline(x0,x1,y0,color);
frankvnk 0:ee7076d8260a 488 else hline(x1,x0,y0,color);
frankvnk 0:ee7076d8260a 489 return;
frankvnk 0:ee7076d8260a 490 }
frankvnk 0:ee7076d8260a 491
frankvnk 0:ee7076d8260a 492 if (dy > 0) {
frankvnk 0:ee7076d8260a 493 dy_sym = 1;
frankvnk 0:ee7076d8260a 494 } else {
frankvnk 0:ee7076d8260a 495 dy_sym = -1;
frankvnk 0:ee7076d8260a 496 }
frankvnk 0:ee7076d8260a 497
frankvnk 0:ee7076d8260a 498 dx = dx_sym*dx;
frankvnk 0:ee7076d8260a 499 dy = dy_sym*dy;
frankvnk 0:ee7076d8260a 500
frankvnk 0:ee7076d8260a 501 dx_x2 = dx*2;
frankvnk 0:ee7076d8260a 502 dy_x2 = dy*2;
frankvnk 0:ee7076d8260a 503
frankvnk 0:ee7076d8260a 504 if (dx >= dy) {
frankvnk 0:ee7076d8260a 505 di = dy_x2 - dx;
frankvnk 0:ee7076d8260a 506 while (x0 != x1) {
frankvnk 0:ee7076d8260a 507
frankvnk 0:ee7076d8260a 508 pixel(x0, y0, color);
frankvnk 0:ee7076d8260a 509 x0 += dx_sym;
frankvnk 0:ee7076d8260a 510 if (di<0) {
frankvnk 0:ee7076d8260a 511 di += dy_x2;
frankvnk 0:ee7076d8260a 512 } else {
frankvnk 0:ee7076d8260a 513 di += dy_x2 - dx_x2;
frankvnk 0:ee7076d8260a 514 y0 += dy_sym;
frankvnk 0:ee7076d8260a 515 }
frankvnk 0:ee7076d8260a 516 }
frankvnk 0:ee7076d8260a 517 pixel(x0, y0, color);
frankvnk 0:ee7076d8260a 518 } else {
frankvnk 0:ee7076d8260a 519 di = dx_x2 - dy;
frankvnk 0:ee7076d8260a 520 while (y0 != y1) {
frankvnk 0:ee7076d8260a 521 pixel(x0, y0, color);
frankvnk 0:ee7076d8260a 522 y0 += dy_sym;
frankvnk 0:ee7076d8260a 523 if (di < 0) {
frankvnk 0:ee7076d8260a 524 di += dx_x2;
frankvnk 0:ee7076d8260a 525 } else {
frankvnk 0:ee7076d8260a 526 di += dx_x2 - dy_x2;
frankvnk 0:ee7076d8260a 527 x0 += dx_sym;
frankvnk 0:ee7076d8260a 528 }
frankvnk 0:ee7076d8260a 529 }
frankvnk 0:ee7076d8260a 530 pixel(x0, y0, color);
frankvnk 0:ee7076d8260a 531 }
frankvnk 0:ee7076d8260a 532 return;
frankvnk 0:ee7076d8260a 533 }
frankvnk 0:ee7076d8260a 534
frankvnk 0:ee7076d8260a 535
frankvnk 0:ee7076d8260a 536 void SPI_TFT::rect(int x0, int y0, int x1, int y1, int color)
frankvnk 0:ee7076d8260a 537 {
frankvnk 0:ee7076d8260a 538 if (x1 > x0) hline(x0,x1,y0,color);
frankvnk 0:ee7076d8260a 539 else hline(x1,x0,y0,color);
frankvnk 0:ee7076d8260a 540
frankvnk 0:ee7076d8260a 541 if (y1 > y0) vline(x0,y0,y1,color);
frankvnk 0:ee7076d8260a 542 else vline(x0,y1,y0,color);
frankvnk 0:ee7076d8260a 543
frankvnk 0:ee7076d8260a 544 if (x1 > x0) hline(x0,x1,y1,color);
frankvnk 0:ee7076d8260a 545 else hline(x1,x0,y1,color);
frankvnk 0:ee7076d8260a 546
frankvnk 0:ee7076d8260a 547 if (y1 > y0) vline(x1,y0,y1,color);
frankvnk 0:ee7076d8260a 548 else vline(x1,y1,y0,color);
frankvnk 0:ee7076d8260a 549
frankvnk 0:ee7076d8260a 550 return;
frankvnk 0:ee7076d8260a 551 }
frankvnk 0:ee7076d8260a 552
frankvnk 0:ee7076d8260a 553
frankvnk 0:ee7076d8260a 554
frankvnk 0:ee7076d8260a 555 void SPI_TFT::fillrect(int x0, int y0, int x1, int y1, int color)
frankvnk 0:ee7076d8260a 556 {
frankvnk 0:ee7076d8260a 557 unsigned long int index=0;
frankvnk 0:ee7076d8260a 558 int h = y1 - y0 + 1;
frankvnk 0:ee7076d8260a 559 int w = x1 - x0 + 1;
frankvnk 0:ee7076d8260a 560 mod_orientation();
frankvnk 0:ee7076d8260a 561 window(x0,y0,w,h);
frankvnk 0:ee7076d8260a 562 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 563 _cs = 0;
frankvnk 0:ee7076d8260a 564 wr_dat_start();
frankvnk 0:ee7076d8260a 565
frankvnk 0:ee7076d8260a 566 for( index = 0; index < h * w; index++ )
frankvnk 0:ee7076d8260a 567 {
frankvnk 0:ee7076d8260a 568 wr_dat_only(color);
frankvnk 0:ee7076d8260a 569 }
frankvnk 0:ee7076d8260a 570 _cs = 1;
frankvnk 0:ee7076d8260a 571 return;
frankvnk 0:ee7076d8260a 572 }
frankvnk 0:ee7076d8260a 573
frankvnk 0:ee7076d8260a 574 void SPI_TFT::locate(int x, int y)
frankvnk 0:ee7076d8260a 575 {
frankvnk 0:ee7076d8260a 576 char_x = x;
frankvnk 0:ee7076d8260a 577 char_y = y;
frankvnk 0:ee7076d8260a 578 }
frankvnk 0:ee7076d8260a 579
frankvnk 0:ee7076d8260a 580 int SPI_TFT::columns()
frankvnk 0:ee7076d8260a 581 {
frankvnk 0:ee7076d8260a 582 return width() / font[1];
frankvnk 0:ee7076d8260a 583 }
frankvnk 0:ee7076d8260a 584
frankvnk 0:ee7076d8260a 585 int SPI_TFT::rows()
frankvnk 0:ee7076d8260a 586 {
frankvnk 0:ee7076d8260a 587 return height() / font[2];
frankvnk 0:ee7076d8260a 588 }
frankvnk 0:ee7076d8260a 589
frankvnk 0:ee7076d8260a 590 int SPI_TFT::_putc(int value)
frankvnk 0:ee7076d8260a 591 {
frankvnk 0:ee7076d8260a 592 if (value == '\n') // new line
frankvnk 0:ee7076d8260a 593 {
frankvnk 0:ee7076d8260a 594 char_x = 0;
frankvnk 0:ee7076d8260a 595 char_y = char_y + font[2];
frankvnk 0:ee7076d8260a 596 if (char_y >= height() - font[2])
frankvnk 0:ee7076d8260a 597 {
frankvnk 0:ee7076d8260a 598 char_y = 0;
frankvnk 0:ee7076d8260a 599 }
frankvnk 0:ee7076d8260a 600 }
frankvnk 0:ee7076d8260a 601 else
frankvnk 0:ee7076d8260a 602 {
frankvnk 0:ee7076d8260a 603 character(char_x, char_y, value);
frankvnk 0:ee7076d8260a 604 }
frankvnk 0:ee7076d8260a 605 return value;
frankvnk 0:ee7076d8260a 606 }
frankvnk 0:ee7076d8260a 607
frankvnk 0:ee7076d8260a 608 void SPI_TFT::character(int x, int y, int c)
frankvnk 0:ee7076d8260a 609 {
frankvnk 0:ee7076d8260a 610 unsigned int hor,vert,offset,bpl,j,i,b;
frankvnk 0:ee7076d8260a 611 unsigned char* bitmap_char;
frankvnk 0:ee7076d8260a 612 unsigned char z,w;
frankvnk 0:ee7076d8260a 613
frankvnk 0:ee7076d8260a 614 if ((c < 31) || (c > 127)) return; // test char range
frankvnk 0:ee7076d8260a 615
frankvnk 0:ee7076d8260a 616 // read font parameter from start of array
frankvnk 0:ee7076d8260a 617 offset = font[0]; // bytes / char
frankvnk 0:ee7076d8260a 618 hor = font[1]; // get hor size of font
frankvnk 0:ee7076d8260a 619 vert = font[2]; // get vert size of font
frankvnk 0:ee7076d8260a 620 bpl = font[3]; // bytes per line
frankvnk 0:ee7076d8260a 621
frankvnk 0:ee7076d8260a 622 if (char_x + hor > width())
frankvnk 0:ee7076d8260a 623 {
frankvnk 0:ee7076d8260a 624 char_x = 0;
frankvnk 0:ee7076d8260a 625 char_y = char_y + vert;
frankvnk 0:ee7076d8260a 626 if (char_y >= height() - font[2])
frankvnk 0:ee7076d8260a 627 {
frankvnk 0:ee7076d8260a 628 char_y = 0;
frankvnk 0:ee7076d8260a 629 }
frankvnk 0:ee7076d8260a 630 }
frankvnk 0:ee7076d8260a 631 mod_orientation();
frankvnk 0:ee7076d8260a 632 window(char_x, char_y,hor,vert); // char box
frankvnk 0:ee7076d8260a 633 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 634 _cs = 0;
frankvnk 0:ee7076d8260a 635 wr_dat_start();
frankvnk 0:ee7076d8260a 636 bitmap_char = &font[((c -32) * offset) + 4]; // start of char bitmap
frankvnk 0:ee7076d8260a 637 w = bitmap_char[0]; // width of actual char
frankvnk 0:ee7076d8260a 638
frankvnk 0:ee7076d8260a 639 for (j=0; j<vert; j++) // vert line
frankvnk 0:ee7076d8260a 640 {
frankvnk 0:ee7076d8260a 641 for (i=0; i<hor; i++) // horz line
frankvnk 0:ee7076d8260a 642 {
frankvnk 0:ee7076d8260a 643 z = bitmap_char[bpl * i + ((j & 0xF8) >> 3)+1];
frankvnk 0:ee7076d8260a 644 b = 1 << (j & 0x07);
frankvnk 0:ee7076d8260a 645 if (( z & b ) == 0x00)
frankvnk 0:ee7076d8260a 646 {
frankvnk 0:ee7076d8260a 647 wr_dat_only(_background);
frankvnk 0:ee7076d8260a 648 }
frankvnk 0:ee7076d8260a 649 else
frankvnk 0:ee7076d8260a 650 {
frankvnk 0:ee7076d8260a 651 wr_dat_only(_foreground);
frankvnk 0:ee7076d8260a 652 }
frankvnk 0:ee7076d8260a 653 }
frankvnk 0:ee7076d8260a 654 }
frankvnk 0:ee7076d8260a 655 _cs = 1;
frankvnk 0:ee7076d8260a 656 if ((w + 2) < hor) // x offset to next char
frankvnk 0:ee7076d8260a 657 {
frankvnk 0:ee7076d8260a 658 char_x += w + 2;
frankvnk 0:ee7076d8260a 659 }
frankvnk 0:ee7076d8260a 660 else char_x += hor;
frankvnk 0:ee7076d8260a 661 }
frankvnk 0:ee7076d8260a 662
frankvnk 0:ee7076d8260a 663
frankvnk 0:ee7076d8260a 664 void SPI_TFT::set_font(unsigned char* f)
frankvnk 0:ee7076d8260a 665 {
frankvnk 0:ee7076d8260a 666 font = f;
frankvnk 0:ee7076d8260a 667 }
frankvnk 0:ee7076d8260a 668
frankvnk 0:ee7076d8260a 669
frankvnk 0:ee7076d8260a 670 void SPI_TFT::Bitmap(unsigned int x, unsigned int y, unsigned int w, unsigned int h,unsigned char *bitmap)
frankvnk 0:ee7076d8260a 671 {
frankvnk 0:ee7076d8260a 672 unsigned int i,j;
frankvnk 0:ee7076d8260a 673 unsigned short *bitmap_ptr = (unsigned short *)bitmap;
frankvnk 0:ee7076d8260a 674 mod_orientation();
frankvnk 0:ee7076d8260a 675 window(x, y, w, h);
frankvnk 0:ee7076d8260a 676 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 677 _cs = 0;
frankvnk 0:ee7076d8260a 678 wr_dat_start();
frankvnk 0:ee7076d8260a 679 _spi.format(16,3);
frankvnk 0:ee7076d8260a 680 bitmap_ptr += ((h - 1)*w);
frankvnk 0:ee7076d8260a 681 for (j = 0; j < h; j++) //Lines
frankvnk 0:ee7076d8260a 682 {
frankvnk 0:ee7076d8260a 683 for (i = 0; i < w; i++) // copy pixel data to TFT
frankvnk 0:ee7076d8260a 684 {
frankvnk 0:ee7076d8260a 685 _spi.write(*bitmap_ptr); // one line
frankvnk 0:ee7076d8260a 686 bitmap_ptr++;
frankvnk 0:ee7076d8260a 687 }
frankvnk 0:ee7076d8260a 688 bitmap_ptr -= 2*w;
frankvnk 0:ee7076d8260a 689 }
frankvnk 0:ee7076d8260a 690 _spi.format(8,3);
frankvnk 0:ee7076d8260a 691 _cs = 1;
frankvnk 0:ee7076d8260a 692 }
frankvnk 0:ee7076d8260a 693
frankvnk 0:ee7076d8260a 694 int SPI_TFT::BMP_16(unsigned int x, unsigned int y, const char *Name_BMP)
frankvnk 0:ee7076d8260a 695 {
frankvnk 0:ee7076d8260a 696 /* // Current code unusable : Rewrite without DMA is needed
frankvnk 0:ee7076d8260a 697 #define OffsetPixelWidth 18
frankvnk 0:ee7076d8260a 698 #define OffsetPixelHeigh 22
frankvnk 0:ee7076d8260a 699 #define OffsetFileSize 34
frankvnk 0:ee7076d8260a 700 #define OffsetPixData 10
frankvnk 0:ee7076d8260a 701 #define OffsetBPP 28
frankvnk 0:ee7076d8260a 702
frankvnk 0:ee7076d8260a 703 char filename[50];
frankvnk 0:ee7076d8260a 704 unsigned char BMP_Header[54];
frankvnk 0:ee7076d8260a 705 unsigned short BPP_t;
frankvnk 0:ee7076d8260a 706 unsigned int PixelWidth,PixelHeigh,start_data;
frankvnk 0:ee7076d8260a 707 unsigned int i,off;
frankvnk 0:ee7076d8260a 708 int padd,j;
frankvnk 0:ee7076d8260a 709 unsigned short *line;
frankvnk 0:ee7076d8260a 710
frankvnk 0:ee7076d8260a 711 // get the filename
frankvnk 0:ee7076d8260a 712 LocalFileSystem local("local");
frankvnk 0:ee7076d8260a 713 sprintf(&filename[0],"/local/");
frankvnk 0:ee7076d8260a 714 i=7;
frankvnk 0:ee7076d8260a 715 while (*Name_BMP!='\0') {
frankvnk 0:ee7076d8260a 716 filename[i++]=*Name_BMP++;
frankvnk 0:ee7076d8260a 717 }
frankvnk 0:ee7076d8260a 718
frankvnk 0:ee7076d8260a 719 fprintf(stderr, "filename : %s \n\r",filename);
frankvnk 0:ee7076d8260a 720
frankvnk 0:ee7076d8260a 721 FILE *Image = fopen((const char *)&filename[0], "rb"); // open the bmp file
frankvnk 0:ee7076d8260a 722 if (!Image) {
frankvnk 0:ee7076d8260a 723 return(0); // error file not found !
frankvnk 0:ee7076d8260a 724 }
frankvnk 0:ee7076d8260a 725
frankvnk 0:ee7076d8260a 726 fread(&BMP_Header[0],1,54,Image); // get the BMP Header
frankvnk 0:ee7076d8260a 727
frankvnk 0:ee7076d8260a 728 if (BMP_Header[0] != 0x42 || BMP_Header[1] != 0x4D) { // check magic byte
frankvnk 0:ee7076d8260a 729 fclose(Image);
frankvnk 0:ee7076d8260a 730 return(-1); // error no BMP file
frankvnk 0:ee7076d8260a 731 }
frankvnk 0:ee7076d8260a 732
frankvnk 0:ee7076d8260a 733 BPP_t = BMP_Header[OffsetBPP] + (BMP_Header[OffsetBPP + 1] << 8);
frankvnk 0:ee7076d8260a 734 if (BPP_t != 0x0010) {
frankvnk 0:ee7076d8260a 735 fclose(Image);
frankvnk 0:ee7076d8260a 736 return(-2); // error no 16 bit BMP
frankvnk 0:ee7076d8260a 737 }
frankvnk 0:ee7076d8260a 738
frankvnk 0:ee7076d8260a 739 PixelHeigh = BMP_Header[OffsetPixelHeigh] + (BMP_Header[OffsetPixelHeigh + 1] << 8) + (BMP_Header[OffsetPixelHeigh + 2] << 16) + (BMP_Header[OffsetPixelHeigh + 3] << 24);
frankvnk 0:ee7076d8260a 740 PixelWidth = BMP_Header[OffsetPixelWidth] + (BMP_Header[OffsetPixelWidth + 1] << 8) + (BMP_Header[OffsetPixelWidth + 2] << 16) + (BMP_Header[OffsetPixelWidth + 3] << 24);
frankvnk 0:ee7076d8260a 741 if (PixelHeigh > height() + y || PixelWidth > width() + x) {
frankvnk 0:ee7076d8260a 742 fclose(Image);
frankvnk 0:ee7076d8260a 743 return(-3); // to big
frankvnk 0:ee7076d8260a 744 }
frankvnk 0:ee7076d8260a 745
frankvnk 0:ee7076d8260a 746 start_data = BMP_Header[OffsetPixData] + (BMP_Header[OffsetPixData + 1] << 8) + (BMP_Header[OffsetPixData + 2] << 16) + (BMP_Header[OffsetPixData + 3] << 24);
frankvnk 0:ee7076d8260a 747
frankvnk 0:ee7076d8260a 748 line = (unsigned short *) malloc (2 * PixelWidth); // we need a buffer for a line
frankvnk 0:ee7076d8260a 749 if (line == NULL) {
frankvnk 0:ee7076d8260a 750 return(-4); // error no memory
frankvnk 0:ee7076d8260a 751 }
frankvnk 0:ee7076d8260a 752
frankvnk 0:ee7076d8260a 753 // the bmp lines are padded to multiple of 4 bytes
frankvnk 0:ee7076d8260a 754 padd = -1;
frankvnk 0:ee7076d8260a 755 do {
frankvnk 0:ee7076d8260a 756 padd ++;
frankvnk 0:ee7076d8260a 757 } while ((PixelWidth * 2 + padd)%4 != 0);
frankvnk 0:ee7076d8260a 758
frankvnk 0:ee7076d8260a 759
frankvnk 0:ee7076d8260a 760 //fseek(Image, 70 ,SEEK_SET);
frankvnk 0:ee7076d8260a 761 window(x, y,PixelWidth ,PixelHeigh);
frankvnk 0:ee7076d8260a 762 wr_cmd(0x22);
frankvnk 0:ee7076d8260a 763 _cs = 0;
frankvnk 0:ee7076d8260a 764
frankvnk 0:ee7076d8260a 765 if (spi_port == 0) { // TFT on SSP0
frankvnk 0:ee7076d8260a 766 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP0->DR; // we send to SSP0
frankvnk 0:ee7076d8260a 767 // LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
frankvnk 0:ee7076d8260a 768 LPC_SSP0->DR = 0x72; // start Data
frankvnk 0:ee7076d8260a 769 LPC_SSP0->CR0 |= 0x08UL; // set to 16 bit
frankvnk 0:ee7076d8260a 770 // Enable SSP0 for DMA.
frankvnk 0:ee7076d8260a 771 LPC_SSP0->DMACR = 0x2;
frankvnk 0:ee7076d8260a 772
frankvnk 0:ee7076d8260a 773 } else {
frankvnk 0:ee7076d8260a 774 LPC_GPDMACH0->DMACCDestAddr = (uint32_t)&LPC_SSP1->DR; // we send to SSP1
frankvnk 0:ee7076d8260a 775 // LPC_SSP1->CR0 &= ~(0x08UL); // set to 8 bit
frankvnk 0:ee7076d8260a 776 LPC_SSP1->DR = 0x72; // start Data
frankvnk 0:ee7076d8260a 777 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
frankvnk 0:ee7076d8260a 778 // Enable SSP1 for DMA.
frankvnk 0:ee7076d8260a 779 LPC_SSP1->DMACR = 0x2;
frankvnk 0:ee7076d8260a 780 }
frankvnk 0:ee7076d8260a 781 for (j = PixelHeigh - 1; j >= 0; j--) { //Lines bottom up
frankvnk 0:ee7076d8260a 782 off = j * (PixelWidth * 2 + padd) + start_data; // start of line
frankvnk 0:ee7076d8260a 783 fseek(Image, off ,SEEK_SET);
frankvnk 0:ee7076d8260a 784 fread(line,1,PixelWidth * 2,Image); // read a line - slow !
frankvnk 0:ee7076d8260a 785
frankvnk 0:ee7076d8260a 786 LPC_GPDMA->DMACIntTCClear = 0x1;
frankvnk 0:ee7076d8260a 787 LPC_GPDMA->DMACIntErrClr = 0x1;
frankvnk 0:ee7076d8260a 788 LPC_GPDMACH0->DMACCSrcAddr = (uint32_t)line;
frankvnk 0:ee7076d8260a 789 LPC_GPDMACH0->DMACCControl = PixelWidth | (0UL << 18) | (0UL << 21) | (1UL << 31) | DMA_CHANNEL_SRC_INC ; // 8 bit transfer , address increment, interrupt
frankvnk 0:ee7076d8260a 790 LPC_GPDMACH0->DMACCConfig = DMA_CHANNEL_ENABLE | DMA_TRANSFER_TYPE_M2P | (spi_port ? DMA_DEST_SSP1_TX : DMA_DEST_SSP0_TX);
frankvnk 0:ee7076d8260a 791 LPC_GPDMA->DMACSoftSReq = 0x1;
frankvnk 0:ee7076d8260a 792 do {
frankvnk 0:ee7076d8260a 793 } while ((LPC_GPDMA->DMACRawIntTCStat & 0x01) == 0); // DMA is running
frankvnk 0:ee7076d8260a 794
frankvnk 0:ee7076d8260a 795 }
frankvnk 0:ee7076d8260a 796
frankvnk 0:ee7076d8260a 797 if (spi_port == 0) { // TFT on SSP0
frankvnk 0:ee7076d8260a 798 do {
frankvnk 0:ee7076d8260a 799 } while ((LPC_SSP0->SR & 0x10) == 0x10); // SPI FIFO not empty
frankvnk 0:ee7076d8260a 800 LPC_SSP0->CR0 &= ~(0x08UL); // set to 8 bit
frankvnk 0:ee7076d8260a 801 } else {
frankvnk 0:ee7076d8260a 802 do {
frankvnk 0:ee7076d8260a 803 } while ((LPC_SSP1->SR & 0x10) == 0x10); // SPI FIFO not empty
frankvnk 0:ee7076d8260a 804 LPC_SSP1->CR0 |= 0x08UL; // set to 16 bit
frankvnk 0:ee7076d8260a 805 }
frankvnk 0:ee7076d8260a 806 _cs = 1;
frankvnk 0:ee7076d8260a 807 free (line);
frankvnk 0:ee7076d8260a 808 fclose(Image);
frankvnk 0:ee7076d8260a 809 WindowMax();
frankvnk 0:ee7076d8260a 810 */
frankvnk 0:ee7076d8260a 811 return(1);
frankvnk 0:ee7076d8260a 812 }