I am doing lab works in a computer hardware subject. Right now I have an EasyAvrV7 board for a few days. Here will be the whole course of the first lab work.

Board looks like:

*Тыкни чтобы посмотреть картинку*

I have no experience writing assembly language code, so no good code. I write as I can. This post is needed more for me not to be lazy and do something about my studies. I'm giving myself 3 days for this lab work. I have a total of 3 works to do.

IMPORTANT NOTE: Comments on screenshots may not match or contradict the code, do not rely on them.

DAY 1:

In this lab work, we need to implement a 'running light' on the LEDs of port A and B. The running light is a binary number where ones are the LEDs that are lit and zeros are the LEDs that are not lit. I.e. there is some binary number, it has as many digits as there are digits in the port register, and it must be cyclically shifted to some side. So far I have implemented cyclic shift to the left. I attach the code:

*Тыкни чтобы посмотреть картинку*

In my code, the main function is executed in an infinite loop, with 'output_fire' being called at each iteration. Therefore, at each iteration the number is cyclically shifted by some number of bits. This number is then put to the port register and a running fire is produced.

DAY 2-3:

Okay, I finally decided to finish this fucking thing. Made it in 3 days like I wanted to, but there are some bugs I'm not able to fix.

First of all, I rewrote the shift logic. Now the running light is displayed on two ports and the step size can be changed by pressing the PD2 button on the board. This is a piece of code with rewritten shifts. The STEP variable contains the step value. If the step is positive, it will be shifted to the left, if it is negative, it will be shifted to the right.

*Тыкни чтобы посмотреть картинку*

By the way, the main program loop looks like this:

*Тыкни чтобы посмотреть картинку*

The variables _X and DELAY_NUMBER are changed when the PD2 and PD1 buttons are pressed, respectively (interrupts int0 and int1).

_X is the step value and DELAY_NUMBER is the number corresponding to the delay: 1 - 0.25ms, 2 - 0.5ms, 3 - 1s. Functions were written beforehand to implement these delays. The delays are not exact, but approximate. I was too lazy to calculate exactly:

*Тыкни чтобы посмотреть картинку*

Next, a little bit about interruptions. An external interrupt is performed by pressing a button. I will show you the example of interrupt int1, which corresponds to pressing the pd3 button on the board (sort of).

Well, first of course you need to enable interrupts and don't forget to configure portd for input (enable button pressing).

Registers of the DDRx kind are responsible for configuring the ports for I/O. For example, if I want to switch portd bits 0,1,4,5,6 to output, I have to put ones in the corresponding DDRD bits, and I will put zeros in the other ones (they will be switched to input mode (pressing buttons)). The interrupt setting code is template, I didn't want to understand special registers for interrupt setting.

*Тыкни чтобы посмотреть картинку*

Great, now we've got the interrupts set up. So we need to write code that will be called when an interrupt occurs. In general, we put the data we don't want to lose (on the screen below - the data in the TMP register) onto the stack and pull it back out after the target code. But it's done in my program more for beauty. In fact, I do not need data in TMP, because it is purely a buffer register.

*Тыкни чтобы посмотреть картинку*

In my target code, the EEWrite_DELAY_NUMBER function is called in the same way. What the fuck is this? It is writing a new value of a variable into non-volatile memory EEPROM, so that the selected value will not be reset after the board is rebooted (accordingly, we need a function that is the opposite of writing into non-volatile memory - a function to read data from it).

It's pretty simple. The TMP register is used to set the address of the cell in the EEPROM, starting from which the variable will be written. Then it is written at this address. Reading from the EEPROM is performed from the same address, which was used for writing. Personally, I have chosen 0x0A. You can choose any other address (there are a couple of megabytes of memory available, maybe less).

*Тыкни чтобы посмотреть картинку*

Also consider the size of the data if you put for example more than one thing in the EEPROM. If the data overlap, you will break everything. For example, I wrote _X to 0x00.

P.S.: A little bit about bugs. I don't know why, but for some reason I don't always cycle through the steps by pressing the button. The step should change (according to the lab work condition) cyclically, like: 1,2,3,-3,-3,-2,-2,-1,-1,1.... But it does not always change cyclically. And I don't understand why. My other groupmates (those whose code I have seen) have the same problem. And I didn't write in this post about entering a custom number (the running light is built on some number in its binary form), because I don't really understand whether it is implemented correctly or not. I don't understand how to test it (simultaneous pressing of several buttons is required).