Jump to content
43oh

Using few wires to control multiple 8-bit parallel devices


Recommended Posts

Hello again,

 

I've been working on a modification of RobG's code ( http://www.43oh.com/forum/viewtopic.php?f=9&t=540 ), for several chips to be controlled by a 'G2231, not just one LCD.

 

When I have this program downloaded to the chip, I tell it to "go", nothing happens. The LEDs on bits 0 & 6 don't even flicker, as they have done with other projects.

I'm using IAR kickstart with a launchpad, no errors. Tried another project on it, "Flashing The LED", works like it should.

 

post-2374-135135500973_thumb.jpg

 

Here's the code:

 

   #include "msp430g2231.h"
   #include "msp430.h"

   #define sendData(data) send(data, 1); dataBus()
   #define sendInstruction(data) send(data, 0); dataBus()
   #define sendAddress(data) send(data, 0); addressBus()
   #define addressBus() P1OUT |= SELECTPIN2; __delay_cycles(100); P1OUT &= ~SELECTPIN2; __delay_cycles(100); P1OUT |= SELECTPIN2;
   #define dataBus() P1OUT |= SELECTPIN1; __delay_cycles(100); P1OUT &= ~SELECTPIN1; __delay_cycles(100); P1OUT |= SELECTPIN1;

   #define DATAPIN BIT7
   #define CLOCKPIN BIT6
   #define WRITEPIN BIT5
   #define SELECTPIN2 BIT4
   #define SELECTPIN1 BIT0

   void send(char data, char registerSelect);
   void sendDataArray(char data[], char length);

   char charIndex = 0;
   char bitCounter = 0;

   void main(void) {
       WDTCTL = WDTPW + WDTHOLD;

       __delay_cycles(1000);

       P1OUT &= ~(CLOCKPIN + DATAPIN);
       P1OUT |= WRITEPIN;
       P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN;
   }

   void sendDataArray(char data[], char length) {
      charIndex = 0;
        while(charIndex < length) {
           sendData(data[charIndex]);
           charIndex++;
        }
   }

   void send(char data, char registerSelect) {
      bitCounter = 0;
      while(bitCounter < 8) {
           (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
           data <<= 1;
           P1OUT |= CLOCKPIN;
           P1OUT &= ~CLOCKPIN;
           bitCounter++;
        }
        registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
        P1OUT &= ~WRITEPIN;
        P1OUT |= WRITEPIN;
   }

   void testPorts();
   void testPorts() {

       sendAddress(0x33);
       sendInstruction(0x55);
       sendData(0xAA);
   }

EDIT: Changed the title to better describe the thread.

Link to post
Share on other sites

Going to have to think on it why your circuit/code is not working... Why not use two 74HC595 and not use the 4093?

 

If you have a parallel device you will also need a control lines for the device. if it is in 8 bit mode, you would need more then 8 bits to control the device.

 

I think you could get by with 4 lines: data clock latch Write. (maybe even three if you connect the 595's in series)

You have to keep in mind timing and data race... you want to data and address information to be stable on the buss.

 

 

First HC595 holds the 8 bit data, second HC595 holds Address, then latch the data to the output.

 

Depending on how many devices you want to control, could be select a bit on the HC595 for that device.

Or use an address to select using a address decoder like 74HC138/HC139.

 

Once you have loaded the data and address, you just change the Write state to load the device.

 

Devices that do not have an enable pin, would have to do something else... but if they have a enable pin, can tie them all in parallel. and select via the enable pin.

Link to post
Share on other sites
Going to have to think on it why your circuit/code is not working...

I figured out what was going on...

   void main(void) {
       WDTCTL = WDTPW + WDTHOLD;

       __delay_cycles(1000);

       P1OUT &= ~(CLOCKPIN + DATAPIN);
       P1OUT |= WRITEPIN;
       P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN;
   }

This is from the script I posted earlier, notice anything peculiar?

 

I forgot to add the "testports()" to it! Here I was, wracking my brain for several hours (and getting a headache in the process), trying to see what I was doing wrong... AND THE PROBLEM WAS RIGHT UNDER MY NOSE!!! :x

 

And then I had to post my foolishness here... Sorry guys... :oops:

 

Anyway, I got it working (properly), and tested a couple of projects on it, flawless.

 

The first one was just writing an 8-bit value to either one of the registers, the second one was a little more complicated.

It used two loops, one nested inside the other, to make a shifting LED go from one end of the first register to the other end of the second register, and return to start the loop over again.

 

I did something neat with the magnitude comparator. When the LED reached the end of the first register, it would turn off before the first LED of the next register came on, therefore having a state when none of the LEDs were lit, and both registers had the same data. Put the LED from the mag. comp. between the two sets of eight, and presto!

 

A 17 position ping-pong-ing LED!

I had some fun with that for a while (including turning the speed up and changing it from hex 1 to hex 5, two LEDs with a space in between).

 

Here's the code, (modified it from something I found online, don't remember where I got it) it uses the schematic above :

//***************************************************************************************
// MSP430 Driver for 74HC595 Shift Register
//
// Description; Drives 16 LED's with 4 digital pins of the MSP430, via a shift register
//
// MSP430x2xx
//
//***************************************************************************************
#include 

//Define our pins
#define DATA BIT7 // DS -> 1.7
#define CLOCK BIT6 // SH_CP -> 1.6
#define LATCH BIT5 // ST_CP -> 1.5
#define LATCH2 BIT4 // ST_CP2 -> 1.4


// Declare functions
void delay ( unsigned int );
void pulseClock ( void );
void shiftOut ( unsigned char );
void shiftOut2 ( unsigned char );
void init ( void );
void pinWrite ( unsigned int, unsigned char );


int main( void )
{
 // Stop watchdog timer to prevent time out reset
 WDTCTL = WDTPW + WDTHOLD;
 P1DIR |= (DATA + CLOCK + LATCH + LATCH2);  // Setup pins as outputs

 int i, j;
 //Do a "ping-pong" effect back and forth
 for(;{
    for ( j = 0 ; j < 9 ; j++ ){
     shiftOut2(5 << j);
     delay(25);
   }
    for ( i = 0 ; i < 8 ; i++ ){
     shiftOut(5 << i);
     delay(25);
   }
    for ( i = 7 ; i >= -1 ; i-- ){
     shiftOut(5 << i);
     delay(25);
   }
    for ( j = 7 ; j >= 0 ; j-- ){
     shiftOut2(5 << j);
     delay(25);
   }

 }
}

// Delays by the specified Milliseconds
// thanks to:
// http://www.threadabort.com/archive/2010/09/05/msp430-delay-function-like-the-arduino.aspx
void delay(unsigned int ms)
{
while (ms--)
   {
       __delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz
   }
}

// Writes a value to the specified bitmask/pin. Use built in defines
// when calling this, as the shiftOut() function does.
// All nonzero values are treated as "high" and zero is "low"
void pinWrite( unsigned int bit, unsigned char val )
{
 if (val){
   P1OUT |= bit;
 } else {
   P1OUT &= ~bit;
 }
}

// Pulse the clock pin
void pulseClock( void )
{
 P1OUT |= CLOCK;
 P1OUT ^= CLOCK;

}

// Take the given 8-bit value and shift it out, LSB to MSB
void shiftOut(unsigned char val)
{
 //Set latch to low (should be already)
 P1OUT &= ~LATCH;

 char i;

 // Iterate over each bit, set data pin, and pulse the clock to send it
 // to the shift register
 for (i = 0; i < 8; i++)  {
     pinWrite(DATA, (val & (1 << i)));
     pulseClock();
 }
 // Pulse the latch pin to write the values into the storage register
 P1OUT |= LATCH;
 P1OUT &= ~LATCH;

}
// Take the given 8-bit value and shift it out, LSB to MSB
void shiftOut2(unsigned char val)
{

   //Set latch to low (should be already)
 P1OUT &= ~LATCH2;

 char j;

 // Iterate over each bit, set data pin, and pulse the clock to send it
 // to the shift register
 for (j = 0; j < 8; j++)  {
     pinWrite(DATA, (val & (1 << j)));
     pulseClock();
 }

 // Pulse the latch pin to write the values into the storage register
 P1OUT |= LATCH2;
 P1OUT &= ~LATCH2;
}

Link to post
Share on other sites
Why not use two 74HC595 and not use the 4093?

I had only one 74HC595 and two 4094s, couldn't find the other 4094, used the 595 instead. I thought it was convenient though, for anyone who wanted to use this, they didn't have to do much changing to use two 595s or 4094s.

If you have a parallel device you will also need a control lines for the device. if it is in 8 bit mode, you would need more then 8 bits to control the device.

 

I think you could get by with 4 lines: data clock latch Write. (maybe even three if you connect the 595's in series)

You have to keep in mind timing and data race... you want to data and address information to be stable on the buss.

 

 

First HC595 holds the 8 bit data, second HC595 holds Address, then latch the data to the output.

 

Depending on how many devices you want to control, could be select a bit on the HC595 for that device.

Or use an address to select using a address decoder like 74HC138/HC139.

 

Once you have loaded the data and address, you just change the Write state to load the device.

 

Devices that do not have an enable pin, would have to do something else... but if they have a enable pin, can tie them all in parallel. and select via the enable pin.

My thoughts exactly. Here's what I've been working on the past two days:post-2374-135135501025_thumb.jpg

 

The code I'm still building:

    #include "msp430g2231.h"
   #include "msp430.h"
   //LCD data bus: port A
   //LCD RS pins: bit 0, port C
   //LCD1 enable pin: bit 1, port C
   //LCD2 enable pin: bit 2, port C
   #define sendDataPA(data) send(data, 0, 0) //send data to port A of the 8255
   #define sendDataPB(data) send(data, 0, 1) //send data to port B of the 8255
   #define sendDataPC(data) send(data, 1, 0) //send data to port C of the 8255
   #define sendInstruction(data) send(data, 1, 1); //send an instruction to the 8255 control register

   //For LCD No.1
   #define PulseLCD1(); sendInstruction(0x02); sendInstruction(0x00);
   #define sendData1(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD1()
   #define sendInstruction1(data) send(data, 0, 0);  sendInstruction(0x00); PulseLCD1()
   #define clearDisplay1(); sendData1(0x01); __delay_cycles(2000)

   //For LCD No.2
   #define PulseLCD2(); sendInstruction(0x04); sendInstruction(0x00);
   #define sendData2(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD2()
   #define sendInstruction2(data) send(data, 0, 0); sendInstruction(0x00);  PulseLCD2()
   #define clearDisplay2(); sendData2(0x01); __delay_cycles(2000)

   //For both LCDs
   #define PulseLCDs(); sendDataPC(0x07); sendDataPC(0x01)
   #define initDisplays(); sendInstruction1(0x38); sendInstruction2(0x30); sendDataPA(0x0C); PulseLCDs(); sendDataPA(0x01); PulseLCDs(); sendDataPA(0x06); PulseLCDs()

   #define DATAPIN BIT7
   #define CLOCKPIN BIT6
   #define WRITEPIN BIT5
   #define ADDRPIN BIT4

   void send(char data, char A0, char A1);
   void testports();

   char charIndex = 0;
   char bitCounter = 0;

   void main(void) {
       WDTCTL = WDTPW + WDTHOLD;

       __delay_cycles(1000);

       P1OUT &= ~(CLOCKPIN + DATAPIN);
       P1OUT |= WRITEPIN;
       P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN + ADDRPIN;

       testports(); //Here now, ha ha

   }

   void send(char data, char A0, char A1) {
      bitCounter = 0;
      while(bitCounter < 8) {
           (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
           data <<= 1;
           P1OUT |= CLOCKPIN;
           P1OUT &= ~CLOCKPIN;
           bitCounter++;
        }
        A0 ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
        A1 ? (P1OUT |= ADDRPIN) : (P1OUT &= ~ADDRPIN);
        __delay_cycles(100);
        P1OUT &= ~WRITEPIN;
        __delay_cycles(400);
        P1OUT |= WRITEPIN;
   }


   void testports() {
       sendInstruction(0x80);       //initialize 8255, Mode 0 
       initDisplays();
       sendDataPC(0x00);          //3 LEDs on bits 7, 6, and 5 of port C to test
       __delay_cycles(50000);
       sendDataPC(0x20);
       __delay_cycles(50000);
       sendDataPC(0x40);
       __delay_cycles(50000);
       sendDataPC(0x60);
       __delay_cycles(50000);
       sendDataPC(0x80);
       __delay_cycles(50000);
       sendDataPC(0xA0);
       __delay_cycles(50000);
       sendDataPC(0xC0);
       __delay_cycles(50000);
       sendDataPC(0xE0);
   }

An 8255? I like old chips (three 8-bit ports too!).

I used the 4094 here because I could just tie the strobe pin high (makes it act like a 74HC164), and not have to worry about latching the data into IT too... As it is I'm already using over 1/4 of the '2231s memory (need to clean it up don't I?).

Link to post
Share on other sites

I have maxed out code space on the 2231, you have to watch what C library functions you use.

Depends on what your trying to do with that chip, you may have to go to another MSP430 with more memory.

 

So far I have just re-written code to save memory space, but in the future maybe will have to go to a larger MSP430.

 

 

I picked up a 20 pin MSP430 for when I need more I/O and memory, maybe start playing with it soon.

 

I am also old school..... my first computer 1Mhz 8-bit, 16K ram..... Just after learning BASIC, started look at ways to make it do other things. Building custom hardware for it.

 

 

 

An 8255? I like old chips (three 8-bit ports too!).

I used the 4094 here because I could just tie the strobe pin high (makes it act like a 74HC164), and not have to worry about latching the data into IT too... As it is I'm already using over 1/4 of the '2231s memory (need to clean it up don't I?).

Link to post
Share on other sites
Wow! 8255, the blast from the past. I still have few of those and some from the Z80 series.

 

Cool! I have a lot of old chips I've scavenged from outdated computers, etc. I'll list a few that I didn't have to de-solder:

 

Flash memories:

1 W29C020 512kb x 8

5 128kb x 8;

2 29F010

2 P28F001

1 W29EE011

 

EEPROMs:

1 XLS28C16AP 2kb x 8

1 28C16A 2kb x 8

1 DS12887A RTC

 

UV-EPROMs:

1 NMC27C32BQ 2kb x 8

1 M5M27C101K 128kb x 8

1 HN27C1024HG 64k-word x 16-bit

 

E-EPROM:

1 W27E512 64kb x 8

 

8051-family micros, 1 ea.:

P87C52EBPN, windowless

P8748N, windowless

M80C31F

SCN8048A

P8039AHL

 

A few 32kb x 8 static rams, somewhere...

 

I/O:

2 8155H 256-bytes x 8, 2 8-bit i/o ports //Z80 series? has ALE

2 8255A 3 8-bit i/o ports

3 8755A 2kb x 8 UV-EPROM, 2 8-bit i/o ports //Z80 series? has ALE

 

PS/2 keyboard/mouse controller:

W83C43, (IDEAS??!! :twisted: )

 

These are all the ones I have handy at the moment.

 

If y'all need info on a chip, enter the number into one of these sites' search boxes:

http://datasheetcatalog.com/

http://www.datasheetarchive.com/

 

(edit)

 

I also have these two interesting chips:

YM3812

YM3814, DAC for YM3812 oscilator

 

These two are really cool! The 3812 has all kinds of tones, so with a little software control, can play any tune!

Link to post
Share on other sites

Added two LCDs.

post-2374-135135501301_thumb.jpg

    #include "msp430g2231.h"
   #include "msp430.h"

   #define sendDataPA(data) send(data, 0, 0) //send data to port A of the 8255
   #define sendDataPB(data) send(data, 0, 1) //send data to port B of the 8255
   #define sendDataPC(data) send(data, 1, 0) //send data to port C of the 8255
   #define sendInstruction(data) send(data, 1, 1); //send an instruction to the 8255 control register

   //For LCD No.1
   #define PulseLCD1(); sendInstruction(0x03); sendInstruction(0x02);
   #define sendData1(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD1()
   #define sendInstruction1(data) send(data, 0, 0);  sendInstruction(0x00); PulseLCD1()
   #define clearDisplay1(); sendData1(0x01); __delay_cycles(2000)

   //For LCD No.2
   #define PulseLCD2(); sendInstruction(0x05); sendInstruction(0x04);
   #define sendData2(data) send(data, 0, 0); sendInstruction(0x01); PulseLCD2()
   #define sendInstruction2(data) send(data, 0, 0); sendInstruction(0x00);  PulseLCD2()
   #define clearDisplay2(); sendData2(0x01); __delay_cycles(2000)

   //For both LCDs
   #define PulseLCDs(); PulseLCD1(); PulseLCD2();
   #define initDisplays(); sendDataPA(0x38); PulseLCDs(); sendDataPA(0x0E); PulseLCDs(); sendDataPA(0x01); PulseLCDs(); sendDataPA(0x06); PulseLCDs()

   #define DATAPIN BIT7
   #define CLOCKPIN BIT6
   #define WRITEPIN BIT5
   #define ADDRPIN BIT4
   #define CSPIN BIT0 //just for fun, pin 6 of 8255

   void send(char data, char A0, char A1);
   void testports();
   void PrintStr1(char *Text);
   void PrintStr2(char *Text);

   char charIndex = 0;
   char bitCounter = 0;

   void main(void) {
       WDTCTL = WDTPW + WDTHOLD;

       __delay_cycles(1000);

       P1OUT &= ~(CLOCKPIN + DATAPIN);
       P1OUT |= WRITEPIN;
       P1DIR |= WRITEPIN + CLOCKPIN + DATAPIN + ADDRPIN + CSPIN;

       P1OUT &= ~CSPIN;
       __delay_cycles(100000);

       testports(); //Here now, ha ha

       P1OUT |= CSPIN;

   }

   void send(char data, char A0, char A1) {
      bitCounter = 0;
      while(bitCounter < 8) {
           (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
           data <<= 1;
           P1OUT |= CLOCKPIN;
           P1OUT &= ~CLOCKPIN;
           bitCounter++;
        }
        A0 ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
        A1 ? (P1OUT |= ADDRPIN) : (P1OUT &= ~ADDRPIN);
        __delay_cycles(400);
        P1OUT &= ~WRITEPIN;
        __delay_cycles(400);
        P1OUT |= WRITEPIN;
   }


   void testports() {
       sendInstruction(0xA0);
       initDisplays();
       PrintStr1("Hello Ibby!"); // my little sister
       sendInstruction1(0xC0);   //DDRAM address 64 (next line)
       PrintStr1("Hello Mom!");

       PrintStr2("Hello Da");  //I did this because LCD#2 is an 8x2, but looks like 16x1
       sendInstruction2(0xC0); //DDRAM address 64 (next line)
       PrintStr2("d!");
   }
   void PrintStr1(char *Text) {  //print a string on lcd1
   char *c;
   c = Text;
   while ((c != 0) && (*c != 0))
   {
       sendData1(*c);
       c++;
   }
}
   void PrintStr2(char *Text) {  //print a string on lcd2
   char *c;
   c = Text;
   while ((c != 0) && (*c != 0))
   {
       sendData2(*c);
       c++;
   }
}

Link to post
Share on other sites

I'm having trouble with a 35-bit shift register and my micro. I tell my 'g2231 to send a 36-bit value to the M5451 (one start bit), but it's only displaying the first 8 bits. I tested the M5451 by hand, it does what it should.

 

I'm still using variations of RobG's code for the LCD.

 

My code:

//***************************************************************************************
// MSP430 Driver for 2 Shift Registers
//
// Description; Drives 35 LEDs and one LCD with 4 digital pins of the MSP430, via two shift registers
//
// MSP430x2xx
//
//***************************************************************************************
#include 

   #define sendLCDData(data) send(data, 1);
   #define sendLCDcmd(data) send(data, 0);
   #define clearDisplay(); sendLCDcmd(0x01); __delay_cycles(2000)
   #define initDisplay(); sendLCDcmd(0x38); sendLCDcmd(0x0C); clearDisplay(); sendLCDcmd(0x06);

//Define our pins
   #define DATAPIN BIT7
   #define CLOCKPIN BIT6
   #define ENABLEPIN BIT5
   #define LEDCLOCKPIN BIT4

// Declare functions
void delay ( unsigned int );
void pulseClock ( void );
void shiftOut (unsigned char );

void pinWrite (unsigned int, unsigned char );

   char bitCounter = 0;
   void send(char data, char RegisterSelect);
   void PrintStr(char *Text);


int main( void )
{
 // Stop watchdog timer to prevent time out reset
 WDTCTL = WDTPW + WDTHOLD;
 P1DIR |= (DATAPIN + CLOCKPIN + ENABLEPIN + LEDCLOCKPIN);  // Setup pins as outputs
       __delay_cycles(100000);

       initDisplay();
       __delay_cycles(100000);
       sendLCDcmd(0x80);
       PrintStr("Hello, 43oh.com!");
       sendLCDcmd(0xC0);
       PrintStr("This is a 35LED ");
       __delay_cycles(3000000);
       sendLCDcmd(0x80);
       PrintStr("ping-pong, with ");
       sendLCDcmd(0xC0);
       PrintStr("an LCD display. ");
       __delay_cycles(3000000);

 int i;
 //Do a "ping-pong" effect back and forth
 for(;{
    for ( i = 0 ; i < 35 ; i++ ){
     shiftOut(1 << i);
     delay(25);
   }
    for ( i = 34 ; i >= 0 ; i-- ){
     shiftOut(1 << i);
     delay(25);
   }

 }
}
   void send(char data, char RegisterSelect) {   //For LCD on 8255
      bitCounter = 0;
      while(bitCounter < 8) {
           (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
           data <<= 1;
           P1OUT |= CLOCKPIN;
           P1OUT &= ~CLOCKPIN;
           bitCounter++;
        }
        RegisterSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
        P1OUT |= ENABLEPIN;
        P1OUT &= ~ENABLEPIN;
   }

   void PrintStr(char *Text) {   //For LCD on 8255
   char *c;
   c = Text;
   while ((c != 0) && (*c != 0))
   {
       sendLCDData(*c);
       c++;
   }
}

// Delays by the specified Milliseconds
// thanks to:
// http://www.threadabort.com/archive/2010/09/05/msp430-delay-function-like-the-arduino.aspx
void delay(unsigned int ms)
{
while (ms--)
   {
       __delay_cycles(1000); // set for 16Mhz change it to 1000 for 1 Mhz
   }
}

// Writes a value to the specified bitmask/pin. Use built in defines
// when calling this, as the shiftOut() function does.
// All nonzero values are treated as "high" and zero is "low"
void pinWrite(unsigned int bit, unsigned char val )
{
 if (val){
   P1OUT |= bit;
 } else {
   P1OUT &= ~bit;
 }
}

// Pulse the clock pin
void pulseClock( void )
{
 P1OUT |= LEDCLOCKPIN;
 __delay_cycles(10);
 P1OUT ^= LEDCLOCKPIN;

}

// Take the given 8-bit value and shift it out, LSB to MSB
void shiftOut(unsigned char val) {
 P1OUT |= DATAPIN;
 pulseClock();
 char i;

 // Iterate over each bit, set data pin, and pulse the clock to send it
 // to the shift register
 for (i = 0; i < 36; i++)  {
     pinWrite(DATAPIN, (val & (1 << i)));
     pulseClock();
 }
}

I've attached the datasheet for the M5451, hopefully y'all can view it.

 

PS: I stayed up a quarter past midnight last night, trying to figure this out... :x

M5451B7.PDF

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...