Analyzing the data that achieved from sniffing DB4..7 of an LCD's pins

Go To Last Post
40 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I sniffed DB4..7 of an 2*16 LCD using the below circuit :

enter image description here

As you see above I connected En pin of LCD to INT0 of Atmega32 (That is configured for Falling Edge firing).

In the interrupt routine I wrote this below codes:

interrupt [EXT_INT0] void ext_int0_isr(void)
    {
    printf("%c",'#');
    printf("%02x", PINA);
    }

In the other hand, in my computer I wrote this code :

import serial
ser=serial.Serial('COM3')

while(1):
    if (ser.read(1)=='#'):
        print '#'
        print ser.read(2)
    else:
        print 'Oops'

And when I powered on my circuit, This below output appears in python :

#
00
#
30
#
30
#
80
#
c0
#
10
#
10
#
00
#
11
#
41
#
61
#
00
#
91
#
a1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
10
#
10
#
00
#
d1
#
a1
#
00
#
91
#
91
#
91
#
91
#
91
#
91
#
91
#
91
#
00
#
30
#
30
#
80
#
c0
#
10
#
10
#
00
#
11
#
41
#
61
#
01
#
e1
#
a1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
10
#
10
#
00
#
d1
#
a1
#
00
#
91
#
91
#
91
#
91
#
91
#
91
#
81
#
81
#
00
#
30
#
30
#
80
#
c0
#
10
#
10
#
00
#
11
#
41
#
61
#
01
#
e1
#
a1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
b1
#
10
#
10
#
00
#
d1
#
a1
#
00
#
91
#
91
#
91
#
91
#
91
#
91
#
71
#
71

Now I want to analyze this output! But I don't have any idea what is the meaning of it. I appreciate if translate some part of it.

This topic has a solution.
Last Edited: Thu. Jan 28, 2016 - 10:30 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

For a start, having printf inside an ISR is unlikely to go well...!

 

surprise

So there's a high risk that your captured data is incorrect and/or incomplete.

How do you know what the connections to the LCD are? Are you just guessing, or do you have a datasheet?

 

If you have a datasheet, then you should be able to find the information to enable you to decode the comms - without a datasheet, you are just guessing!

 

If the LCD has a standard HD44780-type interface, then there are plenty of references on the interwebs...

 

http://en.wikipedia.org/wiki/Hit...

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Sun. Dec 28, 2014 - 02:03 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If it is an HD44780 type controller then your captured data is wrong.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

How can we comment when you haven't shown all of your code?

 

How have you configured INT0?  Which edge are you capturing?  According to the timing diagram from your other thread, you must capture D4-D7 on the falling edge of E.

 

As mentioned, you shouldn't use printf() in an ISR.  You are almost certainly missing capture points, especially if your serial link from the m32 to the PC is slow.

 

Instead, use the ISR to fill a ring buffer, and empty that buffer in your main loop.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:
use the ISR to fill a ring buffer, and empty that buffer in your main loop.

Absolutely!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes, you are right. Using printf inside an ISR make the received data probably different from that really is. But I think increasing Baud-Rate and the Frequency that MCU uses, reduce the possibility of error. Is this right?

 

If I use a 16MHz crystal and configure the baud-rate=19200, Is there a striking error? The origin of error in these way, is the different between time of compilation of ISR-routine and data-transmission speed in the DB4..7 pins, right?

 

And about the data sheet, Yes! I took a look at the data sheet. And this make me confused. Because :

 

As written in the datasheet, when RS ==1 or RS==0 make difference between Data and Command. And as each command or data is ONE byte and we have 4 line for Data/Command bits (DB4...7) ,we must see an Even number of RS==0 or RS== in a row in sniffed data (The Low Nibble in received data). But in my out put, I see some times we have three 1 or one 1 in the low nibble in a row. So I think I did something wrong. Am I right in conclusion?

Note that My LCD is a TS1620A-20/Y

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Skip!

Last Edited: Sun. Dec 28, 2014 - 05:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Because the number of 0 or in the low-nibble in sniffed data is odd sometimes and it must be even? If so, why? I mean what is wrong with the code? Maybe the rate of data-transmission between LCD and Atmega8 is larger than the capturing the DB4..7 lines?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I mentioned in the pictured that I attached and also in the first line below the picture that I configured the INT0 for Falling-edge. 

I use internal 8Mhz RC and buad rate=9200 for the outputs in the question. Is this slow? or it is big enough for capturing? 

 

1- What is the largest Baud-rate that I can have with a 16MHz crystal?

2- What is the better way instead of using ISR for capturing the lines? I don't understand the idea that you said (fill a ring buffer and ...) May please explain it more clear? 

Last Edited: Sun. Dec 28, 2014 - 06:05 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ebrahim.rcii wrote:
 I took a look at the data sheet. And this make me confused.

That's not surprising - Brian Fairchild has already told you:

Quote:
If it is an HD44780 type controller then your captured data is wrong.

 

Quote:
But in my out put, I see some times we have three 1 or one 1 in the low nibble in a row. So I think I did something wrong. 

Again, you have already been told that having printfs in your ISR is very likely to cause loss of data!

 

ebrahim.rcii wrote:
What is the better way instead of using ISR for capturing the lines?

There is nothing wrong with using the ISR to capture the lines - the problem is in having the printfs in your ISR!

 

Quote:
I don't understand the idea that you said (fill a ring buffer and ...)

http://www.lmgtfy.com?q=ring+buffer

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The data-transmission between Atmega8 and LCD last for 16 hours!!!! So filling a ring buffer is not a good idea as I think! am I right? (Atmega8 sends 5 to 6 character to LCD each second)

May I ask you to teach me what is the difference between using printfs in ISR or in the main(). The only problem is that Interrupt don't wait for completion of sending data in next interrupt firing?!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ebrahim.rcii wrote:
filling a ring buffer is not a good idea as I think! am I right?

You said you didn't understand the idea - so how can you dismiss it so soon??

 

Have you actually taken any time to study what a Ring Buffer is, and how they are used for problems like this?

 

Again: http://www.lmgtfy.com?q=ring+buffer

 

Another search term would be "FIFO" - a First-In, First-Out store...

 

Quote:
The only problem is that Interrupt don't wait for completion of sending data in next interrupt firing?!

The problem in your case is that the printf is a large & complex function that can hold-up execution for a significant time until it is done - hence you are likely to miss capturing data!

 

Other problems arise more generally; eg, printf is unlikely to be reentrant...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Sun. Dec 28, 2014 - 06:55 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Dear awneil, why you looks too angry with me? :) be kind!

May I ask another question? 

What happens if another interrupt-firing occurs before completion of running the previous ISR? does the second one waits for completion of the first one? or the second ISR starts before completion of first one?
 

OK, I am starting to read the RING Buffer and FIFO :) Right Now! :D

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Andy is not angry with you. Most of your problems are due to you not doing some basic research.
The control of the lcd is in the realm of sub- microsecond times. Therefore using printf and outputting via serial is going to take many milliseconds. This is why you miss data. You could use a faster baud rate,but it would still take too long.
As for interrupts - the datasheet tells us that further interrupts are disabled when you enter the isr and re-enabled when you exit. You can nest interrupts if you execute a sei() in the isr. For your application, this has no advantage.
Realise that your project is rather difficult, so it is going to take a bit of work.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Andy is not angry with you.

Not angry - maybe a bit irritated

Most of your problems are due to you not doing some basic research.

And that is the irritating bit!

 

It's been said in some of your other threads, too: you really need to be taking the time to get the basics thoroughly understood before running off into advanced stuff.

 

As the old saying goes, "learn to walk before trying to run"!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It should be relatively easy to sniff the LCD lines,  but you will need to be fairly quick.

 

Although the typical write takes 40-50us,   you are watching a 4-bit interface.    So the double EN pulse might be done in 2us or so.

So when you see the first +ve edge with an ISR(),   you should look for it's pair immediately.

 

In practice,  your LCD is only going to have human-readable throughput.

You can capture data into a ring buffer.    And empty the buffer to SD card or EEPROM in a quiet period.

 

I can't believe that you are getting millions of messages being written to the LCD.    It is more likely to be a few kB over an 8-hour period.

 

I still find it difficult to picture your oil-well.    Are you going to read your LCD at the bottom of the well?     Or read it through black tar-like crude oil?

 

As I said earlier,   Proteus, Hapsim,  ... simulate an LCD.     I bet that some Logic Analysers will be able to decode the signals.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You actually posted a timing diagram at the start of your other thread: https://www.avrfreaks.net/forum/h...

 

david.prentice wrote:
You can capture data into a ring buffer.    And empty the buffer to SD card or EEPROM...

or serial port!

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

Not angry - maybe a bit irritated

Most of your problems are due to you not doing some basic research.

And that is the irritating bit!

I'm so sorry dear Andy. I'll promise that I will do my best to be a good questioner and not irritating you. Your quickly answers make me lazy a little and I know it. I'll try to research first and ask if I can't solve my problems in research in next questions.

Thank you. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

david.prentice wrote:

So when you see the first +ve edge with an ISR(),   you should look for it's pair immediately.


Why? I was thought that I only need to capture data on the falling edges! So why I must search for +ve edge and its pair?

 

david.prentice wrote:

In practice,  your LCD is only going to have human-readable throughput.

You can capture data into a ring buffer.    And empty the buffer to SD card or EEPROM in a quiet period.

Thank you. Other friends mentioned this also. I'll try it today. but not to SD or EEPROM. I'll try this with serial port.  Is it OK?

 

 

david.prentice wrote:

I can't believe that you are getting millions of messages being written to the LCD.    It is more likely to be a few kB over an 8-hour period.

Am I said that I get millions of messages being written to the LCD?! I don't remember. I said I have 4 to 5 character every second for hours. And as I was thought that the Ring-Buffer idea is recording the sniffed data in a big variable (buffer) and then when communication stopped, sending them to serial port, I said "I think ring buffer is not a good idea" (because the sniffed-data need much more space than the size of Atmega32's memory size.)

 

david.prentice wrote:

I still find it difficult to picture your oil-well.    Are you going to read your LCD at the bottom of the well?     Or read it through black tar-like crude oil?

:) 

This is not a part of the Data-Logger (My oil-well as you said :D ). This is a part of Keypad-Simulator that I asked some questions about it. A keypad is connected to an Atmega8  and based on the input of the atmega8, It prints some data on the LCD. I simulate the keypad with an atmega32 to send different data to the atmega8 automatically. Now I want to sniff the output of the Atmega8, to analyze the output.

 

david.prentice wrote:

As I said earlier,   Proteus, Hapsim,  ... simulate an LCD.     I bet that some Logic Analysers will be able to decode the signals.

Unfortunately I don't have a logic analyzer. I'll try the software, but I feel more comfort with hardware rather than the software. moreover, I think in the Logic-Analyzer, I only can see the output in some visual diagrams. Can I have a text file of the data to analyze the with a python program (for example) in logic analyzers?

Last Edited: Mon. Dec 29, 2014 - 04:24 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You haven't understood how to use a ring buffer.  The ISR stuffs a captured byte into the buffer.  Meanwhile, your main loop waits for bytes to appear in the buffer.  As soon as one does, it can push it out the USART.

 

The advantage is that you can capture bytes as fast as your ISR can fire.  USART sending is almost certainly much slower.

 

You pick a ring buffer size sufficient to capture bursts of data as they come from the m8/LCD.  In between bursts, your main loop can work more slowly at pouring the contents of the buffer out the USART.

 

Properly written ring buffer code can detect a full-buffer condition and set a software buffer overflow flag, so your sniffer can tell you if it has dropped any capture data.  You can then rebuild with a larger ring buffer.

 

Since you're indirectly in control of the data being sent to the LCD (via your emulated keyboard setup), you can control how quickly the bursts come.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

joeymorin wrote:

You pick a ring buffer size sufficient to capture bursts of data... 

 

That's the important, and useful, things about ring buffers. They are very good at taking data in at one rate and allowing it to be read out at another, often slower, rate. It smotthes out the difference in rates. As long as the buffer is big enough to take the average maximum length it all just works.

#1 Hardware Problem? https://www.avrfreaks.net/forum/...

#2 Hardware Problem? Read AVR042.

#3 All grounds are not created equal

#4 Have you proved your chip is running at xxMHz?

#5 "If you think you need floating point to solve the problem then you don't understand the problem. If you really do need floating point then you have a problem you do not understand."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I changed my program to this below program. 



#include <mega32.h>
#include <stdio.h>

int ring[500];
int head=0;
int tail=0;
int overflow=0;


interrupt [EXT_INT0] void ext_int0_isr(void)
{
    ring[head]=PINA;
    ++head;
    if (head==500)
       {
        head=0;
        overflow=1;
       }
}




void main(void)
{


// I remove all the configuration lines to make it easier to read here.

while (1)
      {
      if (tail<head)
        {
            printf("%02x",ring[tail]);
            ++tail;
        }
        
      if (overflow)
        {
        for(int i=tail;tail<500;tail++)
            {      
               printf("%02x",ring[tail]);
            }
            overflow=0;
            tail=0;
        }
      }
}

 

Is this methodology that I used equal to the same ring buffer?

 

Note that I reduce the rate of data transmission on DB4..7 line. It sends data for 1 second and wait 4 second and repeat it. 

Is there any problem?

 

And note that, between each 5 second delay, I receive 200 byte in the python output. So I think the size of ring is big enough for my program. Am I right?

Last Edited: Mon. Dec 29, 2014 - 10:02 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You've implemented half a ring buffer! Overflow is not when the head or tail go past 500 - it's called a ring or circular buffer because it goes around in a ring or circle! Overflow is when the head bumps into the tail. The tail should be behind the head. If tail == head, the buffer is empty.
You'll need to understand the importance of volatile with your code. Cliff has written a tutorial on it and i've written a tutorial on the traps when using interrupts. You've fallen into the trap.
People get irritated when you don't listen - i gave you a solution to your problem but you've chosen to ignore it!

Last Edited: Mon. Dec 29, 2014 - 10:13 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
#include <mega32.h>
#include <stdio.h>

#define RING_BUFF_SIZE 500
volatile unsigned char ring[RING_BUFF_SIZE];
volatile int head=0,tail = 0;
volatile unsigned char overflow = 0;


interrupt [EXT_INT0] void ext_int0_isr(void)
{
    ring[head++] = PINA;
    
    if (head >= RING_BUFF_SIZE)
       {
        head = 0;   //circle around
       }
       if (head == tail) //if we bumped into the tail, overflow!
       {
           overflow = 1;
       }
}




void main(void)
{
unsigned char tmp,found;

// I remove all the configuration lines to make it easier to read here.

while (1)
      {
      found = 0;
      cli();
          
      if (tail != head)
        {
            found = 1;
            tmp = ring[tail++];
            if (tail >= RING_BUFF_SIZE)
            {
                tail = 0;  //circle around
            }
        }
        sei();
        if (found)
        {
            printf("%02X\n",tmp);
            
        }
        
      if (overflow)
        {
            printf("Overflow\n");
            overflow = 0;
        }
      }
}

Untested. 

Last Edited: Mon. Dec 29, 2014 - 10:31 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have to choose how you will handle the case when the Ring Buffer gets full:

  • discard new data?
  • overwrite old data?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Mon. Dec 29, 2014 - 02:27 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok,   5 chars per second for 8 hours is 144000 bytes.   Or a little more if you are capturing control bytes too.

So it would be fine on a PC or SDcard but too much to store on EEPROMs.

 

Since you are only monitoring a 6-wire interface,   there is only DB4-DB7, RS, EN signals.

No HD44780 operation takes less than 35us.    A byte on the 4-bit interface might have two 230ns EN pulses in a 1us period,  you need to be quite swift to catch them.

 

However,  it is far more likely that the two EN pulses are longer and easier to catch.

Since you know what particular hardware you are trying to crack,   I presume you have measured the EN pulses and intervals.

 

Anyway,  you could have an ISR(INT0_vect) that captures the -ve edge of EN and stores data in a modest 16-byte ring buffer.

And the main foreground code simply empties the ring buffer through the UART.    Even at 9600 baud,   your 5 bytes per second only take about 10ms.    I can't see an 8x2 display receiving more than 900 bytes in a second.    Especially when the average is 5 per second.

 

I might even write a sniffer after I have taken Ralfie for a walk.

 

David.

Last Edited: Mon. Dec 29, 2014 - 03:33 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I choose to overwrite old data. And both my program (in #22 post) and dear Kartman program (in #24 post) works fine and have a same output fortunately :) 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you dear friend. Your program works fine.  I just delete cli() and sei() from the program :D (My codevision detect errors in those lines.)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank you dear David. My program works fine know. But I appreciate your time if you write another program, I am sure that it will have some points to learn for me :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
I choose to overwrite old data.
Why on earth?

 

If you have an overflow, you have missed captured data.  Your sniffer will be lying to you.

 

Instead, use the overflow to notify you that it has occurred.  Then you can adjust your design with either a larger buffer, faster USART, or slower keypad emulation.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Again, we have given you guidance and you have ignored it! The cli() and sei() are rather critical. Maybe in Codevision it is SEI() and CLI()? Had you read my tutorial you would've understood the reason for these.

From a quick Google it seems Codevision uses:
#asm("sei"). And #asm("cli")
Without these the program will have a random error.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

joeymorin wrote:

Why on earth?

Instead, use the overflow to notify you that it has occurred.  Then you can adjust your design with either a larger buffer, faster USART, or slower keypad emulation.

 

Let me to explain my program, please tell me what's wrong in my program :

 

This is my program :

 

#include <mega32.h>
#include <stdio.h>

int ring[500];
int head=0;
int tail=0;
int overflow=0;


interrupt [EXT_INT0] void ext_int0_isr(void)
{
    ring[head]=PINA;
    ++head;
    if (head==500)
       {
        head=0;
        overflow=1;
       }
}

In the ISR, I capture the RS and Data-Bus lines on each falling-edge of the En. if head==500 that means ring is full, so it starts from beginning of the ring and make an overflow-flag=1 instead. 

 

Now take a look at the main() loop :

void main(void)
{


// I remove all the configuration lines to make it easier to read here.

while (1)
      {
      if (tail<head)
        {
            printf("%02x",ring[tail]);
            ++tail;
        }
        
      if (overflow)
        {
        for(int i=tail;tail<500;tail++)
            {      
               printf("%02x",ring[tail]);
            }
            overflow=0;
            tail=0;
        }
      }
}

until tail is less than head, it sends ring[tail] to serial port and add tail by one.  it also check the overflow-flag in each loop. if the overflow-flag==1,  it means the tail must iterate to 499 instead of to head. (because head started agian from 0)

 

And why I think this program is OK? 
Because : I change the input of the ATMEGA8 in a way that it sends data/command to LCD for 1 second, and then waits 4 second and then again send data/command for 1 second and so on ...

In every 5-second I receive only about 200 character in sniffing. (In the other word, in that 1-second I capture only 200 character). This means that all the data that are transmitted in 5-second periods, are 200 character. and in the 4 seconds waiting, the buffer will empty! so, I don't loose any data with overwriting. right? I also capture all the data(because the length of them is 200 and is less than 500). is it right also?
So what the problem in this program?

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

Without these the program will have a random error.

 

Would you please tell me what is the origin of this random error in my case? (base on my previous reply) I don't understand what's the point!

 

*AND I will read them. (cli and sei).

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That's not a ring buffer.

 

#include <mega32.h>
#include <stdio.h>

#define RING_SIZE 512

volatile unsigned char ring[512];
volatile unsigned int head=0;
volatile unsigned int tail=0;
volatile unsigned char overflow=0;

interrupt [EXT_INT0] void ext_int0_isr(void) {
  ring[head]=PINA;
  head = (head + 1) % RING_SIZE;
  if (head == tail) {
    overflow = 1;
  }
}
void main(void)
{


// I remove all the configuration lines to make it easier to read here.

while (!overflow) {
  if (tail != head) {
    printf("%02x",ring[tail]);
    tail = (tail + 1) % RING_SIZE;
  }
}
printf("ERROR:  Buffer overflow.  Aborting.");

Untested.

 

Technically, the overflow flag is set when there is still one byte left in the buffer, but it simplifies the code somewhat.

 

Note the use of the % operator.  This should result in decently fast code when RING_SIZE is a power-of-two.  If you really want to use a non-power-of-two, use a comparison instead:

  if (head < (RING_SIZE - 1)) {
    head++;
  }
  else {
    head = 0;
  }

Note also the use of volatile.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

Last Edited: Mon. Dec 29, 2014 - 11:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Joey, i see your 'ring size' is bigger than mine! Not sure if Codevision (or gcc for that matter) will pick up on using a 'and' for the modulus.

Ebrahim - what is the source of the random error? Atomicity. I explain it in my tutorial i suggested you read.
We understood what you did with your code, but it wasn't a ring buffer! If you want a linear fifo, then do that. In this instance you don't need a tail variable as a global. The ring buffer is a generic solution. If we say ring buffer, implement it as a ring buffer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:
Joey, i see your 'ring size' is bigger than mine!
I was trying not brag ;)

 

Quote:
Not sure if Codevision (or gcc for that matter) will pick up on using a 'and' for the modulus.
Can't say with Codevision, but AVR GCC does.  With -O1:

      tail = (tail + 1) % RING_SIZE;
 110:	80 91 62 00 	lds	r24, 0x0062
 114:	90 91 63 00 	lds	r25, 0x0063
 118:	01 96       	adiw	r24, 0x01	; 1
 11a:	91 70       	andi	r25, 0x01	; 1
 11c:	90 93 63 00 	sts	0x0063, r25
 120:	80 93 62 00 	sts	0x0062, r24

 

Quote:
Ebrahim - what is the source of the random error? Atomicity.
Agree that this is a general issue and a frequent pitfall, but in the case of my example code above at least it isn't a problem, even though ring[] is an array of 16-bit values.

 

The reason is that there are no circumstances under which an element of that array will be modified part way through the reading of it.  The only writer is the ISR, and since interrupts are disabled by hardware it is inherently atomic.  The only reader is the main loop, and it won't begin the read of any element until head is not equal to tail, which is a condition which cannot occur until after an element is fully written by the ISR.  A similar condition is prevented by the overflow flag.

 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Where I can find these tutorials? :)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The tutorial section of course! I just entered 'kartman traps' in the search box on the top of the page. What was the first hit?
Search first, ask questions later.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Not sure if Codevision (or gcc for that matter) will pick up on using a 'and' for the modulus.

Can't say with Codevision, but AVR GCC does.  With -O1: ...

FWIW, with a recent CodeVision version:

 

#include <io.h>

#define RING_SIZE 512

volatile unsigned char ring[512];
volatile unsigned int head=0;

register unsigned int tail = 0;

void main(void)
{  


  ring[head]=PIND;
  head = (head + 1) % RING_SIZE;
  tail = (tail + 1) % RING_SIZE;
for( ;; ) 
    {
      
    }  
}  
    
                 ; 0000 000F   head = (head + 1) % RING_SIZE;
000079 91e0 0400 	LDS  R30,_head
00007b 91f0 0401 	LDS  R31,_head+1
00007d 9631      	ADIW R30,1
00007e 70f1      	ANDI R31,HIGH(0x1FF)
00007f 93e0 0400 	STS  _head,R30
000081 93f0 0401 	STS  _head+1,R31
                 ; 0000 0010   tail = (tail + 1) % RING_SIZE;
000083 01f2      	MOVW R30,R4
000084 9631      	ADIW R30,1
000085 70f1      	ANDI R31,HIGH(0x1FF)
000086 012f      	MOVW R4,R30

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello, i have worked out completed on this project, if u need help then let me know. thanx

 

* This smells like spam so it is being locked. Moderator *

Last Edited: Thu. Jan 28, 2016 - 10:30 AM
Topic locked