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:
Fri Jan 04 09:52:16 2013 +0000
Revision:
7:ffdd4e75b366
Parent:
6:b547fb6c1095
Code cleanup / comments added

Who changed what in which revision?

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