Simple driver for the ST7920 graphic LCD 128x64. Basic functions for displaying internal ROM fonts like a 16x4 LCD Extended function to fill the screen with a bitmap
Dependents: Graficador_De_Bode_OTERO-OSSO_PPs2018
st7920.h@0:1a97e0243dbc, 2012-06-29 (annotated)
- Committer:
- Bas
- Date:
- Fri Jun 29 22:47:51 2012 +0000
- Revision:
- 0:1a97e0243dbc
- Child:
- 1:c7d041bdb718
Function added for displaying vertical oriented bitmaps
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Bas | 0:1a97e0243dbc | 1 | #ifndef __ST7920_H |
Bas | 0:1a97e0243dbc | 2 | #define __ST7920_H |
Bas | 0:1a97e0243dbc | 3 | |
Bas | 0:1a97e0243dbc | 4 | #define VERSION 1.0 |
Bas | 0:1a97e0243dbc | 5 | |
Bas | 0:1a97e0243dbc | 6 | #include <mbed.h> |
Bas | 0:1a97e0243dbc | 7 | |
Bas | 0:1a97e0243dbc | 8 | // Instruction Set 1: (RE=0: Basic Instruction) |
Bas | 0:1a97e0243dbc | 9 | #define DISPLAY_CLEAR 0x01 // Fill DDRAM with "20H" and set DDRAM address counter (AC) to "00H" |
Bas | 0:1a97e0243dbc | 10 | #define RETURN_HOME 0x02 // Set DDRAM address counter (AC) to "00H", and put cursor |
Bas | 0:1a97e0243dbc | 11 | // to origin �Gthe content of DDRAM are not changed |
Bas | 0:1a97e0243dbc | 12 | #define ENTRY_MODE_SET 0x04 // Set cursor position and display shift when doing write or read |
Bas | 0:1a97e0243dbc | 13 | // operation |
Bas | 0:1a97e0243dbc | 14 | #define DISPLAY_CONTROL 0x08 // D=1: Display ON, C=1: Cursor ON, B=1: Character Blink ON |
Bas | 0:1a97e0243dbc | 15 | #define CURSOR_DISPLAY_CONTROL 0x10 // Cursor position and display shift control; the content of |
Bas | 0:1a97e0243dbc | 16 | // DDRAM are not changed |
Bas | 0:1a97e0243dbc | 17 | #define FUNCTION_SET 0x20 // DL=1 8-bit interface, DL=0 4-bit interface |
Bas | 0:1a97e0243dbc | 18 | // RE=1: extended instruction, RE=0: basic instruction |
Bas | 0:1a97e0243dbc | 19 | #define SET_CGRAM_ADDRESS 0x40 // Set CGRAM address to address counter (AC) |
Bas | 0:1a97e0243dbc | 20 | // Make sure that in extended instruction SR=0 |
Bas | 0:1a97e0243dbc | 21 | #define SET_DDRAM_ADDRESS 0x80 // Set DDRAM address to address counter (AC) |
Bas | 0:1a97e0243dbc | 22 | // AC6 is fixed to 0 |
Bas | 0:1a97e0243dbc | 23 | |
Bas | 0:1a97e0243dbc | 24 | // Instruction set 2: (RE=1: extended instruction) |
Bas | 0:1a97e0243dbc | 25 | #define STANDBY 0x01 // Enter standby mode, any other instruction can terminate. |
Bas | 0:1a97e0243dbc | 26 | // COM1�c32 are halted |
Bas | 0:1a97e0243dbc | 27 | #define SCROLL_OR_RAM_ADDR_SEL 0x02 // SR=1: enable vertical scroll position |
Bas | 0:1a97e0243dbc | 28 | // SR=0: enable CGRAM address (basic instruction) |
Bas | 0:1a97e0243dbc | 29 | #define REVERSE_BY_LINE 0x04 // Select 1 out of 4 line (in DDRAM) and decide whether to |
Bas | 0:1a97e0243dbc | 30 | // reverse the display by toggling this instruction |
Bas | 0:1a97e0243dbc | 31 | // R1,R0 initial value is 0,0 |
Bas | 0:1a97e0243dbc | 32 | #define EXTENDED_FUNCTION_SET 0x20 // DL=1 :8-bit interface, DL=0 :4-bit interface |
Bas | 0:1a97e0243dbc | 33 | // RE=1: extended instruction, RE=0: basic instruction |
Bas | 0:1a97e0243dbc | 34 | #define SET_SCROLL_ADDRESS 0x40 // G=1 :graphic display ON, G=0 :graphic display OFF |
Bas | 0:1a97e0243dbc | 35 | #define SET_GRAPHIC_RAM_ADDRESS 0x80 // Set GDRAM address to address counter (AC) |
Bas | 0:1a97e0243dbc | 36 | // Set the vertical address first and followed the horizontal |
Bas | 0:1a97e0243dbc | 37 | // address by consecutive writings |
Bas | 0:1a97e0243dbc | 38 | // Vertical address range: AC5�cAC0, Horizontal address range: AC3�cAC0 |
Bas | 0:1a97e0243dbc | 39 | |
Bas | 0:1a97e0243dbc | 40 | // Parameters regarding Instruction Sets 1 & 2 |
Bas | 0:1a97e0243dbc | 41 | #define DISPLAY_SHIFT_S 0x01 // Set 1, ENTRY_MODE_SET |
Bas | 0:1a97e0243dbc | 42 | #define INCREASE_DECREASE_ID 0x02 // Set 1, ENTRY_MODE_SET |
Bas | 0:1a97e0243dbc | 43 | #define CURSOR_BLINK_ON_B 0x01 // Set 1, DISPLAY_CONTROL |
Bas | 0:1a97e0243dbc | 44 | #define CURSOR_ON_C 0x02 // Set 1, DISPLAY_CONTROL |
Bas | 0:1a97e0243dbc | 45 | #define DISPLAY_ON_D 0x04 // Set 1, DISPLAY_CONTROL |
Bas | 0:1a97e0243dbc | 46 | #define SHIFT_RL 0x04 // Set 1, CURSOR_DISPLAY_CONTROL |
Bas | 0:1a97e0243dbc | 47 | #define CURSOR_SC 0x08 // Set 1, CURSOR_DISPLAY_CONTROL |
Bas | 0:1a97e0243dbc | 48 | #define EXTENDED_INSTRUCTION_RE 0x04 // Set 1, FUNCTION_SET; Set 2, EXTENDED_FUNTION_SET |
Bas | 0:1a97e0243dbc | 49 | #define DATA_LENGTH_DL 0x10 // Set 1, FUNCTION_SET; Set 2, EXTENDED_FUNTION_SET |
Bas | 0:1a97e0243dbc | 50 | #define REVERSE_BY_LINE_R0 0x01 // Set 2, REVERSE_BY_LINE |
Bas | 0:1a97e0243dbc | 51 | #define REVERSE_BY_LINE_R1 0x02 // Set 2, REVERSE_BY_LINE |
Bas | 0:1a97e0243dbc | 52 | #define EN_VERTICAL_SCROLL_SR 0x01 // Set 2, SCROLL_OR_RAM_ADDR_SEL |
Bas | 0:1a97e0243dbc | 53 | #define GRAPHIC_ON_G 0x02 // Set 2, EXTENDED_FUNTION_SET |
Bas | 0:1a97e0243dbc | 54 | |
Bas | 0:1a97e0243dbc | 55 | #define BUSY_FLAG_BF 0x80 |
Bas | 0:1a97e0243dbc | 56 | |
Bas | 0:1a97e0243dbc | 57 | /*********************************************************************************/ |
Bas | 0:1a97e0243dbc | 58 | |
Bas | 0:1a97e0243dbc | 59 | class ST7920 { |
Bas | 0:1a97e0243dbc | 60 | public: |
Bas | 0:1a97e0243dbc | 61 | /** |
Bas | 0:1a97e0243dbc | 62 | *@brief Constructor, initializes the lcd on the respective pins. |
Bas | 0:1a97e0243dbc | 63 | *@param control pins RS,RW,E |
Bas | 0:1a97e0243dbc | 64 | *@param databus DB0-DB7 data pins |
Bas | 0:1a97e0243dbc | 65 | *@return none |
Bas | 0:1a97e0243dbc | 66 | *@ ----> pin PSB @ Vdd for 8/4-bit parallel bus mode. |
Bas | 0:1a97e0243dbc | 67 | */ |
Bas | 0:1a97e0243dbc | 68 | ST7920 (PinName _RS, PinName _RW, PinName _E, PinName DB0, PinName DB1, PinName DB2, PinName DB3, PinName DB4, PinName DB5, PinName DB6, PinName DB7); |
Bas | 0:1a97e0243dbc | 69 | |
Bas | 0:1a97e0243dbc | 70 | |
Bas | 0:1a97e0243dbc | 71 | /** |
Bas | 0:1a97e0243dbc | 72 | *@brief Display initialision |
Bas | 0:1a97e0243dbc | 73 | * |
Bas | 0:1a97e0243dbc | 74 | *@param none |
Bas | 0:1a97e0243dbc | 75 | *@return none |
Bas | 0:1a97e0243dbc | 76 | * |
Bas | 0:1a97e0243dbc | 77 | */ |
Bas | 0:1a97e0243dbc | 78 | void InitDisplay(void); |
Bas | 0:1a97e0243dbc | 79 | |
Bas | 0:1a97e0243dbc | 80 | |
Bas | 0:1a97e0243dbc | 81 | /** |
Bas | 0:1a97e0243dbc | 82 | *@brief Enable Extended Instructions, RE=1, Graphic on |
Bas | 0:1a97e0243dbc | 83 | * |
Bas | 0:1a97e0243dbc | 84 | *@param none |
Bas | 0:1a97e0243dbc | 85 | *@return none |
Bas | 0:1a97e0243dbc | 86 | * |
Bas | 0:1a97e0243dbc | 87 | */ |
Bas | 0:1a97e0243dbc | 88 | void SetGraphicsMode(void); |
Bas | 0:1a97e0243dbc | 89 | |
Bas | 0:1a97e0243dbc | 90 | /** |
Bas | 0:1a97e0243dbc | 91 | *@brief Go back to Basic Instructions, RE=0 |
Bas | 0:1a97e0243dbc | 92 | * |
Bas | 0:1a97e0243dbc | 93 | *@param none |
Bas | 0:1a97e0243dbc | 94 | *@return none |
Bas | 0:1a97e0243dbc | 95 | * |
Bas | 0:1a97e0243dbc | 96 | */ |
Bas | 0:1a97e0243dbc | 97 | void SetTextMode(void); |
Bas | 0:1a97e0243dbc | 98 | |
Bas | 0:1a97e0243dbc | 99 | /** |
Bas | 0:1a97e0243dbc | 100 | *@brief Sets DDRAM address counter (AC) to '00H' |
Bas | 0:1a97e0243dbc | 101 | *@basic function, clear screen |
Bas | 0:1a97e0243dbc | 102 | *@param none |
Bas | 0:1a97e0243dbc | 103 | *@return none |
Bas | 0:1a97e0243dbc | 104 | * |
Bas | 0:1a97e0243dbc | 105 | */ |
Bas | 0:1a97e0243dbc | 106 | void ClearScreen(void); |
Bas | 0:1a97e0243dbc | 107 | |
Bas | 0:1a97e0243dbc | 108 | void ReturnHome(void); |
Bas | 0:1a97e0243dbc | 109 | void Standby(void); |
Bas | 0:1a97e0243dbc | 110 | |
Bas | 0:1a97e0243dbc | 111 | /** |
Bas | 0:1a97e0243dbc | 112 | *@brief Places a string on the screen with internal characters from the HCGROM |
Bas | 0:1a97e0243dbc | 113 | *@ |
Bas | 0:1a97e0243dbc | 114 | *@param row, column, string |
Bas | 0:1a97e0243dbc | 115 | *@return none |
Bas | 0:1a97e0243dbc | 116 | * |
Bas | 0:1a97e0243dbc | 117 | */ |
Bas | 0:1a97e0243dbc | 118 | /* |
Bas | 0:1a97e0243dbc | 119 | * DESCRIPTIONS: |
Bas | 0:1a97e0243dbc | 120 | * Place a string to the GLCD controller on the specified row and column. |
Bas | 0:1a97e0243dbc | 121 | * Due to the design of the ST7920 controller (to accomodate Mandarin and Cyrillic), you must place the text on the column |
Bas | 0:1a97e0243dbc | 122 | * according to the numbers above the diagram below: |
Bas | 0:1a97e0243dbc | 123 | * |
Bas | 0:1a97e0243dbc | 124 | * |--0--|--1--|--2--|... ...|--7--| |
Bas | 0:1a97e0243dbc | 125 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 126 | * |H |e |l |l |o | ... | <- row 0 (address 0x80) |
Bas | 0:1a97e0243dbc | 127 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 128 | * |T |h |i |s | |i ... | <- row 1 (address 0x90) |
Bas | 0:1a97e0243dbc | 129 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 130 | * |* |* |* |* |* |* ... | <- row 2 (address 0x88) |
Bas | 0:1a97e0243dbc | 131 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 132 | * |- |- |- |- |- |- ... | <- row 3 (address 0x98) |
Bas | 0:1a97e0243dbc | 133 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 134 | * |
Bas | 0:1a97e0243dbc | 135 | * Example: |
Bas | 0:1a97e0243dbc | 136 | * Writing "abc" onto the 1st column, and 1st row: |
Bas | 0:1a97e0243dbc | 137 | * |--0--|--1--|--2--|... ...|--7--| |
Bas | 0:1a97e0243dbc | 138 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 139 | * | | | | | | ... | <- row 0 (address 0x80) |
Bas | 0:1a97e0243dbc | 140 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 141 | * | | |a |b |c | ... | <- row 1 (address 0x90) |
Bas | 0:1a97e0243dbc | 142 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 143 | * | | | | | | ... | <- row 2 (address 0x88) |
Bas | 0:1a97e0243dbc | 144 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 145 | * | | | | | | ... | <- row 3 (address 0x98) |
Bas | 0:1a97e0243dbc | 146 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 147 | * |
Bas | 0:1a97e0243dbc | 148 | ****************************************************************************** |
Bas | 0:1a97e0243dbc | 149 | */ |
Bas | 0:1a97e0243dbc | 150 | void DisplayString(int Row,int Column, unsigned char *ptr,int length); |
Bas | 0:1a97e0243dbc | 151 | |
Bas | 0:1a97e0243dbc | 152 | /** |
Bas | 0:1a97e0243dbc | 153 | *@brief Places a character on the screen with an internal character from the HCGROM |
Bas | 0:1a97e0243dbc | 154 | *@ |
Bas | 0:1a97e0243dbc | 155 | *@param row, column, character |
Bas | 0:1a97e0243dbc | 156 | *@return none |
Bas | 0:1a97e0243dbc | 157 | * |
Bas | 0:1a97e0243dbc | 158 | */ |
Bas | 0:1a97e0243dbc | 159 | /* |
Bas | 0:1a97e0243dbc | 160 | * DESCRIPTIONS: |
Bas | 0:1a97e0243dbc | 161 | * Place a character to the GLCD controller on the specified row and column. |
Bas | 0:1a97e0243dbc | 162 | * Due to the design of the ST7920 controller (to accomodate Mandarin and Cyrillic), you must place the text on the column |
Bas | 0:1a97e0243dbc | 163 | * according to the numbers above the diagram below: |
Bas | 0:1a97e0243dbc | 164 | * |
Bas | 0:1a97e0243dbc | 165 | * |--0--|--1--|--2--|... ...|--7--| |
Bas | 0:1a97e0243dbc | 166 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 167 | * |H |e |l |l |o | ... | <- row 0 (address 0x80) |
Bas | 0:1a97e0243dbc | 168 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 169 | * |T |h |i |s | |i ... | <- row 1 (address 0x90) |
Bas | 0:1a97e0243dbc | 170 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 171 | * |* |* |* |* |* |* ... | <- row 2 (address 0x88) |
Bas | 0:1a97e0243dbc | 172 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 173 | * |- |- |- |- |- |- ... | <- row 3 (address 0x98) |
Bas | 0:1a97e0243dbc | 174 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 175 | * |
Bas | 0:1a97e0243dbc | 176 | * Example: |
Bas | 0:1a97e0243dbc | 177 | * Writing 'a' onto the 1st column, and 1st row: |
Bas | 0:1a97e0243dbc | 178 | * |--0--|--1--|--2--|... ...|--7--| |
Bas | 0:1a97e0243dbc | 179 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 180 | * | | | | | | ... | <- row 0 (address 0x80) |
Bas | 0:1a97e0243dbc | 181 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 182 | * | | |a | | | ... | <- row 1 (address 0x90) |
Bas | 0:1a97e0243dbc | 183 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 184 | * | | | | | | ... | <- row 2 (address 0x88) |
Bas | 0:1a97e0243dbc | 185 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 186 | * | | | | | | ... | <- row 3 (address 0x98) |
Bas | 0:1a97e0243dbc | 187 | * +--+--+--+--+--+---------------------+ |
Bas | 0:1a97e0243dbc | 188 | * |
Bas | 0:1a97e0243dbc | 189 | ******************************************************************************* |
Bas | 0:1a97e0243dbc | 190 | */ |
Bas | 0:1a97e0243dbc | 191 | void DisplayChar(int Row, int Column,int inpChr); |
Bas | 0:1a97e0243dbc | 192 | |
Bas | 0:1a97e0243dbc | 193 | /** |
Bas | 0:1a97e0243dbc | 194 | *@brief Fills the screen with the graphics described in a 1024-byte array |
Bas | 0:1a97e0243dbc | 195 | *@ |
Bas | 0:1a97e0243dbc | 196 | *@param bitmap 128x64, bytes horizontal |
Bas | 0:1a97e0243dbc | 197 | *@return none |
Bas | 0:1a97e0243dbc | 198 | * |
Bas | 0:1a97e0243dbc | 199 | */ |
Bas | 0:1a97e0243dbc | 200 | void FillGDRAM(unsigned char *bitmap); |
Bas | 0:1a97e0243dbc | 201 | |
Bas | 0:1a97e0243dbc | 202 | //same as FILLGDRAM, but turnes all the bytes from vertical to horizontal |
Bas | 0:1a97e0243dbc | 203 | //now pictures for eg KS0108 can be used |
Bas | 0:1a97e0243dbc | 204 | void FillGDRAM_Turned(unsigned char *bitmap); |
Bas | 0:1a97e0243dbc | 205 | |
Bas | 0:1a97e0243dbc | 206 | /** |
Bas | 0:1a97e0243dbc | 207 | *@brief Clears the graphics RAM of the screen |
Bas | 0:1a97e0243dbc | 208 | *@writes all pixels to zero |
Bas | 0:1a97e0243dbc | 209 | *@param none |
Bas | 0:1a97e0243dbc | 210 | *@return none |
Bas | 0:1a97e0243dbc | 211 | * |
Bas | 0:1a97e0243dbc | 212 | */ |
Bas | 0:1a97e0243dbc | 213 | void ClearGDRAM(void); |
Bas | 0:1a97e0243dbc | 214 | |
Bas | 0:1a97e0243dbc | 215 | |
Bas | 0:1a97e0243dbc | 216 | |
Bas | 0:1a97e0243dbc | 217 | private: |
Bas | 0:1a97e0243dbc | 218 | BusInOut DB; |
Bas | 0:1a97e0243dbc | 219 | DigitalOut RS; |
Bas | 0:1a97e0243dbc | 220 | DigitalOut RW; |
Bas | 0:1a97e0243dbc | 221 | DigitalOut E; |
Bas | 0:1a97e0243dbc | 222 | //DigitalOut RST; |
Bas | 0:1a97e0243dbc | 223 | |
Bas | 0:1a97e0243dbc | 224 | unsigned char screen[1024]; |
Bas | 0:1a97e0243dbc | 225 | |
Bas | 0:1a97e0243dbc | 226 | unsigned int ByteReadLCD(void); |
Bas | 0:1a97e0243dbc | 227 | |
Bas | 0:1a97e0243dbc | 228 | void ByteWriteLCD(unsigned int data); |
Bas | 0:1a97e0243dbc | 229 | |
Bas | 0:1a97e0243dbc | 230 | /** |
Bas | 0:1a97e0243dbc | 231 | *@brief Write instruction to the controller. |
Bas | 0:1a97e0243dbc | 232 | *@param Command command to send to the controller |
Bas | 0:1a97e0243dbc | 233 | *@return none |
Bas | 0:1a97e0243dbc | 234 | * |
Bas | 0:1a97e0243dbc | 235 | */ |
Bas | 0:1a97e0243dbc | 236 | void WriteInstruction(unsigned int Command); |
Bas | 0:1a97e0243dbc | 237 | |
Bas | 0:1a97e0243dbc | 238 | /** |
Bas | 0:1a97e0243dbc | 239 | *@brief Write data byte to the controller. |
Bas | 0:1a97e0243dbc | 240 | *@param data data send to the controller chip (DDRAM/CGRAM/GDRAM) |
Bas | 0:1a97e0243dbc | 241 | *@return none |
Bas | 0:1a97e0243dbc | 242 | * |
Bas | 0:1a97e0243dbc | 243 | */ |
Bas | 0:1a97e0243dbc | 244 | void WriteRAM(unsigned int data); |
Bas | 0:1a97e0243dbc | 245 | |
Bas | 0:1a97e0243dbc | 246 | /** |
Bas | 0:1a97e0243dbc | 247 | *@brief Read busy flag, keep looking |
Bas | 0:1a97e0243dbc | 248 | *@param none |
Bas | 0:1a97e0243dbc | 249 | *@return none |
Bas | 0:1a97e0243dbc | 250 | * |
Bas | 0:1a97e0243dbc | 251 | */ |
Bas | 0:1a97e0243dbc | 252 | void ReadBusyFlag(void); |
Bas | 0:1a97e0243dbc | 253 | |
Bas | 0:1a97e0243dbc | 254 | /** |
Bas | 0:1a97e0243dbc | 255 | *@brief Read Address Counter (AC) from the controller. |
Bas | 0:1a97e0243dbc | 256 | *@param none |
Bas | 0:1a97e0243dbc | 257 | *@return read Address Counter (AC) from the controller chip (DDRAM/CGRAM/GDRAM) |
Bas | 0:1a97e0243dbc | 258 | * |
Bas | 0:1a97e0243dbc | 259 | */ |
Bas | 0:1a97e0243dbc | 260 | unsigned int Read_AC(void); |
Bas | 0:1a97e0243dbc | 261 | |
Bas | 0:1a97e0243dbc | 262 | /** |
Bas | 0:1a97e0243dbc | 263 | *@brief Read data byte from the controller. |
Bas | 0:1a97e0243dbc | 264 | *@param none |
Bas | 0:1a97e0243dbc | 265 | *@return data read from the controller chip (DDRAM/CGRAM/GDRAM) |
Bas | 0:1a97e0243dbc | 266 | * |
Bas | 0:1a97e0243dbc | 267 | */ |
Bas | 0:1a97e0243dbc | 268 | unsigned int ReadRAM(void); |
Bas | 0:1a97e0243dbc | 269 | }; |
Bas | 0:1a97e0243dbc | 270 | #endif |