#### Registers: CPU uses registers to store data temporairly. Most AVRs have 8 bit registers. Two kinds of registers. The General Purpose Registers(GPRs) & I/O registers. #### GPRs: ARVs have 32 general purpose registers. They are R0 to R31. And located in the lowers location of memory address($0000 to $001F). They can be used by all arithmatic and logical instructions. #### I/O Registers: I/O registers are dedicated to special functions such as status register, timers, serial comunications, I/O port, ADC etc. For this reason they are called special functions registers(SFRs). The function of each I/O register is fixed by the CPU designer as they are used to controll the microcontroller or peripheral functions supported by the microcontroller. #### Internal SRAM: Internal SRAM is used for storing data. Each loacation of the SRAM can be accessed directly by its address. Each location is 8 bit wide. #### Difference between SRAM and EEPROM EEPROM stores data permanently. data stays if power is off. SRAM loses data if power is off. ## Some Instructions `;` is used for comment in assembly programming. `LDI` instruction is used to Load a data into a GPR ```asm LDI Rd, k ``` Load Imidiate value. Load value `k` into GPR `Rd` where 16 <= d <= 32. `k` can be any binary, hexadecimal or decimal number. --- `LDS` instruction is used to load data into GPRs from a memory address ```asm LDS Rd, K ``` Load from data space. Load `Rd` with data from a memory address `K` where 0 <= d <= 32. `K` is a memory address between $0000 to $FFFF --- `STS` instruction is used to store data to a memory address from GPRs ```asm STS K, Rd ``` Store directly into memory address `K` from GPR `Rd`. Here `K` is an address of a memory location --- `ADD` instruction is used to add the data of two GPRs ```asm ADD Rd, Rr ; Rd = Rd + Rr` ``` Add register `Rd` and `Rr`. And store result in `Rd` --- `IN` instruction is used to store data into GPRs from I/O registers ```asm IN Rd, A ``` Retrieve data from I/O register location `A` and store into the GPR `Rd`. `A` is the memory location of the I/O register. 0<= d <= 32, 0<= A <= 63 --- `OUT` instruction is used to store value in I/O registers from GPRs ```asm OUT A, Rr ``` Store GPR `Rr`'s value to an I/O register who's location is `A` --- `MOV` instruction is used to copy data among GPRs ```asm MOV Rd,Rr ; Rd = Rr ``` copy data from `Rr` to `Rd`. --- `INC` instruction is used to increment data of a register by 1 ```asm INC Rd ; Rd = Rd + 1 ``` Increment the value of `Rd` by 1. --- `SUB` instruction is used to substract one GPR's value from another GPR's value ```asm SUB Rd, Rr ; Rd = Rd - Rr ``` substarct the value of `Rr` from the value of `Rd` and store the result into `Rd`. --- `DEC` instruction is used to decrement the value of a GPR by 1 ```asm DEC Rd ; Rd = Rd - 1 ``` --- `COM` instruction is used to make 1's complement of a GPR ```asm COM Rd ``` invert the bits of `Rd` and then store the value into `Rd` --- `NOP`(No Operation) instruction wastes time by spending one CPU cycle without executing any operation. ```asm NOP ; Spend 1 CPU cycle doing nothing ``` --- `CLR`(Clear) instruction is used to clear a register's value or set to zero. ```asm CLR R20 ; R20 = 0 ``` --- ## DIRECTIVES `.EQU` directive is used to define a constant value / Label for some value of address. ```asm .EQU HEXNUM = 0xFF ``` define `HEXNUM` as a constant hex value `0xFF` --- `.SET` directive is same as `.EQU` but value assigned by set can be re-assigned leter ```asm .SET HEXNUM = 0xFF ``` define `HEXNUM` as a hex value `0xFF` --- `.ORG` directive is used to specify start of a ROM location. Where codes will be burnt. ```asm .ORG $0 ; Burn From ROM location 0x0 ``` ## STATUS REGISTER's FLAGS ```asm Bits D7 D0 --------------------------------- SREG | I | T | H | S | V | N | Z | C | --------------------------------- ``` `C` = Carry Flag, This flag is set whenever there is a carry out from the D7 bit after an arithmetic operation(Addition, subtraction, increment, decrement etc). This flag bit is affected after an 8 bit addition or substruction. `Z` = Zero Flag, This flag is affected after an arithmetic or logic operation. If the result is zero than `Z = 1`, else `Z = 0`. `N` = Negative Flag, It reflects the result of an arithmetic operation. If the D7 bit of the result is zero then `N = 0` and the result is positive. Else `N = 1` and the result is negative. `V` = Overflow Flag, `S` = Sign Flag, `H` = Half Carry Flag, This bit is set if there is a carry from D3 to D4 bit after ADD or SUB instruction. `T` = Bit Copy Storage. Used as a temporary storage for bit. It can be used to copy a bit from a GPR to another GPR. `I` = Global Inturrupt Enable `CLC`(CLear Carry) instruction is used to clear carry bit, `C = 0` `SEC`(SEt Carry) instruction is used to set carry bit, `C = 1` ## BRANCHING INSTRUCTIONS `BRNE` (Branch If Not Equal) instruction is used for looping. `BRNE` instruction uses the zero or Z flag in the status register. CPU jumps to target address if zero flag is low. Z = 0. ```asm LABEL: ; loop body DEC Rn ; Z flag = 1 if Rn = 0. Decrement Rn untill it becomes zero BRNE LABEL ; Goto LABEL if Rn != 0 that means zero flag = 0 ``` Example: Add 10 times ```asm LDI R16, 10 LDI R20, 0 LDI R21, 20 AGAIN: ADD R20, R21 DEC R16 BRNE AGAIN ``` --- `BREQ` (BRanch If EQual). CPU jumps to target address if zero flag is High. ```asm AGAIN: IN R20, PORTB ; Load R20 from PORTB TST R20 ; Examine R20 and set Z & N flag accordingly BREQ AGAIN ; if Z = 1, goto AGAIN ``` --- `BRCC` (BRanch if Carry Cleared). Branch if `C = 0` --- `BRSH` (BRanch if Same or Higher) Branch if `C = 0` --- `BRLO` (BRanch if LOwer) Branch if `C = 1` ## JUMP INSTRUCTIONS **TO DO** ## PROGRAM COUNTER **TO DO** ## AVR I/O PORT PROGRAMMING A powerful feature of AVR I/O ports is their capability of access individual bits of the port without altering the rest of the bits. **32 I/O register's name and their address:** \$ sign indicates hexadecimal value. | Mem Add | I/O Add | Name | Mem Add | I/O Add | Name | | ------- | ------- | ------ | ------- | ------- | ----- | | \$20 | \$00 | TWBR | \$30 | \$10 | PIND | | \$21 | \$01 | TWSR | \$31 | \$11 | DDRD | | \$22 | \$02 | TWAR | \$32 | \$12 | PORTD | | \$23 | \$03 | TWDR | \$33 | \$13 | PINC | | \$24 | \$04 | ADCL | \$34 | \$14 | DDRC | | \$25 | \$05 | ADCH | \$35 | \$15 | PORTC | | \$26 | \$06 | ADCSRA | \$36 | \$16 | PINB | | \$27 | \$07 | ADMUX | \$37 | \$17 | DDRB | | \$28 | \$08 | ACSR | \$38 | \$18 | PORTB | | \$29 | \$09 | UBRRL | \$39 | \$19 | PINA | | \$2A | \$0A | UCSRB | \$3A | \$1A | DDRA | | \$2B | \$0B | UCSRA | \$3B | \$1B | PORTA | | \$2C | \$0C | UDR | \$3C | \$1C | EECR | | \$2D | \$0D | SPCR | \$3D | \$1D | EEDR | | \$2E | \$0E | SPSR | \$3E | \$1E | EEARL | | \$2F | \$0F | SPDR | \$3F | \$1F | EEARH | --- **Following instructions are used to manipulate single bit:** `SBI`(Set Bit in I/O register) instruction is used to set a bit in I/O register. To make a bit 1. ```asm SBI ioReg, bitNumber ; ioReg is the name of I/O register, which is any ; lower 32 I/O register. bitNumber(0 - 7) is the ; position of the bit of the register to manipulate ``` Example: ```asm SBI PORTB, 5 ; This will set the D5(6th) bit of the PORTB register ; to 1. As a result the PB4(5th) pin of Port B will ; output high ``` --- `CBI`(Clear Bit in I/O register) instruction is used to clear a bit in I/O register. To make a bit 0. ```asm CBI ioReg, bitNumber ; ioReg is the name of I/O register, which is any ; lower32 I/O register. bitNumber is the ; number of the bit of the register to manipulate ``` --- Following instructions are used for checking an input pin & make decisions based on the input pin's status. `SIBS`(Skip if Bit in I/O register is Set) instruction tests a bit and skip next instruction if it is HIGH. ```asm SIBS ioReg, bitNumber ; Skip next instruction if bitNumber bit of ioReg ; register is HIGH ``` `SIBC`(Skip if Bit in I/O register is cleared) instruction tests a bit and skip next instruction if it is LOW. ```asm SIBC ioReg, bitNumber ; Skip next instruction if bitNumber bit of ioReg ; register is LOW ``` --- ## ARITHMETIC & LOGICAL OPERATIONS **Unsigned Number Operations:** In this case the sign bit(8th bit) is not taken into account. So numbers can be from 0 to 255. `ADD Rd, Rr` This instruction adds register Rd with Rr and store the number into Rd. Z(Zero), C(Carry), N(Negative), V(Overflow), H(Half Carry), S(Sign) bits of the status register can be affected after this operation. `ADC`(Add with carry) instruction is used to add with carry bit. As it add with carry bit, 16 bit addition is possible with ADC instruction. As when adding two 16 bit data operands we need to concerned about the carry out from lower byte to upper byte. Its is called multi byte addition. Example: Add 0x3CE7 with 0x3B8D ```asm LDI R16, 0x8D ; R16 = 8D LDI R17, 0x3B ; R17 = 3B LDI R18, 0xE7 ; R18 = E7 LDI R19, 0x3C ; R19 = 3C ADD R18, R16 ; R18 = R18 + R16 = E7 + 8D = 74 with C = 1(Carry Out) ; ADD instruction is used for lower byte as carry is ; not a concern here ADC R19, R17 ; R19 = R19 + R17 + C(Carry out from previous operation) ; = 3C + 3B + 1 ; = 78 ; ADC instruction is used as carry is a concern for upper ; byte ; Result: 7874. R19 = 78, R18 = 74 ``` --- There are **five** instrtuctions for substraction in AVR. - `SUB`(Subtract) - `SBC`(Subtruct with borrow) - `SBI`(Subtract immediate) - `SBCI`(Subtract immediate with borrow) - `SBIW`(Subtract a immediate value from register pair) C flag is used for borrow. **Subtraction Instruction Summary:** ```asm SUB Rd, Rr ; Rd = Rd - Rr. Borrow is not a concern for this instruction SBC Rd, Rr ; Subtract with Borrow. Rd = Rd - Rr - C . In this case ; C flag is checked for Borrow. This instruction is useful ; for 16 bit subtraction. SUBI Rd, K ; Subtract a value K from Rd without borrow. Rd = Rd - K. SBCI Rd, K ; Subtract a value K from Rd with borrow. Rd = Rd - K - C ; In this case C flag is checked for borrow. SBIW Rd:Rd+1, K ; Subtract a value K from Rd+1:Rd register pair. ``` In AVR(And most other CPUs) subtraction is done using 2's complement. Separate circuitry isn't used for subtraction as it takes too many transistors. Assuming that the AVR is executing a simple subtractions and C = 0 prior to this execution. The steps of SUB instruction for unsigned numbers are following: 1. Take 2's complement of the righthand operator 2. Add it with the lefthand operator. 3. Invert the carry. Notice that carry is inverted after above operations. Example: Subtract 0x23 from 0x3F ```asm LDI R20, 0x23 ; R20 = 0x23 LDI R21, 0x3F ; R21 = 0x3F SUB R21, R20 ; R21 = R21 - R20 ``` --- There are 3 Multiplication instruction in AVR. ```asm MUL Rd, Rr ; Multiply two unsigned numbers MULS Rd, Rr ; Multiply two signed numbers MULSU Rd, Rr ; Multiply signed number with unsigned number ``` Result is **stored in R1(Higher byte) and R2(Lower byte) registers**. ```asm LDI R23, 0x25 ; R23 = 0x25 LDI R24, 0x65 ; R24 = 0x65 MUL R24, R23 ; R24 * R23 = 0x65 * 0x25 = 0xE99 ; R1 = 0x0E, R2 = 0x99 ``` --- There is no division instruction. But division can be done by repeated subtraction. To divide 95 with 10. Subtract 10 from 95, 9 times. The result is 05. So the quotient is 9 and remainder is 5. So to divide in this method numerator is kept in a register. And the denuminator is subtracted repeatedly. So the quotient is the number of times subtracted. And the remainder is in the register. Example: devide 95 by 10 ```asm .DEF NUM = R20 ; Define R20 as NUM .DEF DENUM = R21 ; Define R21 as DENUM .DEF QUOTIENT = R22 ; Define R22 as QUOTIENT LDI NUM, 90 LDI DENUM, 10 CLR QUOTIENT L1: INC QUOTIENT ; Increment QUOTIENT SUB NUM, DENUM ; Subtact DENUM from NUM BRCC L1 ; Branch if Carry is Cleared. C = 0. After repeated ; subtraction if the result is negative C = 1. And the ; branching / looping will be stopped. DEC QUOTIENT ; As once too many ADD NUM, DENUM ; add back to it ``` --- **Signed Numbers:** For signed numbers the most significant bit(D7 bit for 8 bit number) is reserved for sign. And number is represented by other bits. 0 in the D7 bit indicates positive number & 1 indicates negative number. **Positive Number:** for positive number D7 = 0. So the range of positive number is from +1 to +127. **Negative Number:** For negative number D7 = 1. Negative numbers are represented using 2's complement. To find the binary representation of a negative number first write the magnitude of the number in the 8 bit format. Now take 2's complete of that. It will be the binary of the negative number of that magnitude. ; For example binary of -5 is 11111011. Binary of 5 in 8 bit format is 00000101. Take 2's complement. Its 11111011. So its the binary of -5. Notice that the D7 bit is 1. its indicating that the number is negative. --- **Overflow & V flag:** TO DO --- **Difference between N & S flag:** TO DO --- **Logic `AND` operator:** ```asm AND Rd, Rr ; Rd = Rd & Rr ANDI Rd, K ; Rd = Rd & K ``` `AND` effects N, Z, S flags. N is the D7 bit of the result. Z = 1 if the result is zero. `AND` is often use to mask(Set to zero) bit. For example say I want to mask the D5 & D6 bits of 01100011. I can AND it with 10011111. ```asm LDI R16, 0x63 ; R16 = 0x63 = 0b01100011 ANDI R16, 0x9F ; 0x63 & 0x9F = 01100011 & 10011111 = 00000011 = 0x03 ; R16 = 0x03 ``` --- **Logic `OR` operator:** ```asm OR Rd, Rr ; Rd = Rd | Rr ORI Rd, K ; Rd = Rd | K ``` `OR` effects N, Z, S flags. N is the D7 bit of the result. Z = 1 if the result is zero. OR is often used to set certain bits to 1. For example say I want to set the D3 & D4 bit of the 01100101 to 1. I can OR it with 00011000. ```asm LDI R16, 0x65 ; R16 = 0x65 = 0b01100101 ORI R16, 0x18 ; 0x65 | 0x18 = 01100101 | 00011000 = 01111101 = 0x7D ; R16 = 0x7D ``` --- **Logic exclusive or `XOR`:** ```asm XOR Rd, Rr ; Rd = Rd XOR Rr ``` XOR effects N, Z, S flags. N is the D7 bit of the result. Z = 1 if the result is zero. XOR can be used to check equality of two registers. If two registers are equal then the result of XOR of them will be zero. So Z will be set to 1. And we can take decision based on that. another application of XOR can be toggling the bits. 10101010 XOR 11111111 = 01010101 --- **Logic Inverter / Complement `COM`:** ```asm LDI R20, 0xAA ; R20 = 0xAA = 10101010 COM R20 ; R20 = 0x55 = 01010101 ``` --- **Negation / 2's complement `NEG`:** ```asm LDI R20, 0x56 ; R20 = 0x56 = 01010110 = 86 in decimal NEG R20 ; R20 = 2's complement of 0x56 = 10101001 + 1 = 10101010 = 0xAA = -86 in decimal ``` --- **Compare Instruction CP:** ```asm CP Rd, Rr ; Compare Rd with Rr CPI Rd, K ; Compare Rd with imediate value K ``` compare instruction is really a subtraction except it doesn't change the left hand operator. Compare instruction affects Z, C & S flags. Different branching instruction can be used based on this. After CP instruction Z = 0 means operands are not equal. Z = 1 means operands are equal. After CP instruction for unsigned numbers C = 0 means left hand operand is same or higher than the right hand operator. C = 1 means left hand operator is lower After CP instruction for signed numbers S = 0 means left hand operand is greater than or equal. S = 1 means left hand operand is less than the right hand operand. --- **Branching Instructions:** There are several branching instructions in AVR. Here is most frequently used instructions ```asm BREQ LABEL ; BRanch if EQual zero. Branch to LABEL if the result ; of the previous ; instruction is zero( Z = 1 ). For example if the two ; operands are equal in CP instruction. BRNE LABEL ; BRanch if Not Equal zero. Branch to LABEL if the result ; of the previous ; instruction is not zero( Z = 0 ). For example if the two ; operands are not equal in CP instruction. BRSH LABEL ; BRanch if Same or Higher. Branch to LABEL if C = 0 ; after previous instruction. For example if the left hand ; operand is same or higher in CP instruction. Can be used for ; unsigned numbers BRLO LABEL ; BRanch if LOwer. Branch to LABEL if C = 1 ; after previous instruction. For example if the left hand ; operand is lower in CP instruction. Can be used for ; unsigned numbers BRGE LABEL ; BRanch if Greater than or Equal. Branch to LABEL if S = 0 ; after previous instruction. For example if the left hand ; operand is greater than or equal in CP instruction. Used ; for signed numbers BRLT LABEL ; BRanch if Less Than. Branch to LABEL if S = 1 ; after previous instruction. For example if the left hand ; operand is less than right hand operand in CP instruction. ; Used for signed numbers. BRCS LABEL ; BRanch to LABEL if Carry is Set. C = 1 BRCC LABEL ; BRanch to LABEL if Carry is Cleared. C = 0 BRVS LABEL ; BRanch if V flag is Set. Branch to LABEL if overflow ; happens(V = 1) BRVC LABEL ; BRanch if V flag is Cleared. Branch to LABEL if overflow ; does not happen(V = 0) ``` **Some example of branch instructions:** TO DO --- **Rotational & Shift Instruction:** `ROR`(Rotate right) instruction rotate 1 bit from left to right through carry. As rotate from left to right after rotate command the carry flag enters to MSB and LSB exits to carry. ```asm ROR Rd ; Rotate Rd right through carry ``` Example ```asm CLC ; Clear carry C = 0 LDI R20, 0x26 ; R20 = 0x26 = 0b00100110 ROR R20 ; R20 = 00010011 C = 0 ROR R20 ; R20 = 00001001 C = 1 ROR R20 ; R20 = 10000100 C = 1 ``` --- `ROL`(Rotate Left) instruction rotate 1 bit from right to left through carry. As rotate from right to left after rotate command the carry flag enters to LSB and MSB exits to carry. ```asm ROL Rd ; Rotate Rd left through carry ``` ; Example ```asm SEC ; Set carry C = 1 LDI R20, 0x15 ; R20 = 0x15 = 00010101 ROL R20 ; R20 = 00101011 C = 0 ROL R20 ; R20 = 01010110 C = 0 ROL R20 ; R20 = 10101100 C = 0 ROL R20 ; R20 = 01011000 C = 1 ``` --- **There are three logical shift operator in AVR:** `LSL`(Logical Shift Left) instruction shifts bits from right to left. After shift instruction 0 is entered into LSB and MSB exits to carry. Notice shift instruction multiply the content of the register by 2. ```asm CLC ; Clear carry C = 0 LDI R20, 0x26 ; R20 = 0x26 = 00100110 = 38 LSL R20 ; R20 = 01001100 = 76 C = 0 LSL R20 ; R20 = 10011000 = 152 C = 0 LSL R20 ; R20 = 00110000 = 48 C = 1 ; Notice not multiplied as C = 1, overflow ``` --- `LSR`(Logical Shift Right) instruction shifts bits from left to right. After shift instruction 0 is entered into MSB and LSB exits to carry. Notice shift instruction devides the content of the register by 2. ```asm CLC ; Clear carry C = 0 LDI R20, 0x26 ; R20 = 0x26 = 00100110 = 38 LSR R20 ; R20 = 00010011 = 19 C = 0 LSR R20 ; R20 = 00001001 = 9 C = 1 LSR R20 ; R20 = 00000100 = 4 C = 1 ``` --- `ASR`(Arithmetic shift right) istruction can devide signed numbers by two. As ASR can shift bits to right without altering MSB. LSB exits to carry. ```asm CLC ; C = 0 LDI R20, 0xD0 ; R20 = 11010000 = -48 ASR R20 ; R20 = 11101000 = -24 C = 0 ASR R20 ; R20 = 11110100 = -12 C = 0 ASR R20 ; R20 = 11111010 = -6 C = 0 ASR R20 ; R20 = 11111101 = -3 C = 0 ASR R20 ; R20 = 11111110 = -1 C = 1 ``` --- `SWAP` instruction swaps the nibble of a byte. ```asm SWAP Rd ; Swaps nibble of Rd register where 0 <= d <= 31 ``` ```asm Before: |D7|D6|D5|D4|D3|D2|D1|D0| After: |D3|D2|D1|D0|D7|D6|D5|D4| ``` --- ## ADDRESS MODE CPU can access data in various ways. The data could be in registers, in memory or provided as a direct value. These various ways of accessing data is called addressing modes. AVR supports 13 distinct address modes. They can be catagorized into following groups: 1. Single Register or Immediate address mode(Only single register is involved) 2. Two Register addressing mode 3. Direct address mode(Memory is accessed by their direct addresses) 4. Indirect address mode(Memory is accessed by using registers as pointers pointing to memory) 5. Flash Direct address mode(Direct access to flash rom by flash memory addresses) 6. Flash Indirect address mode (Accessed using pointers) --- **Single register address mode:** In this address mode operand is single register. imediate values can be used in this address mode. So its called immediate address mode too. Registers from R16 to R31 can be used in this address mode. Example: ```asm NEG R16 ; Negate R16 contents COM R16 ; Take complement DEC R16 ; Decrement R16's content by 1 INC R16 ; Increment R16's content by 1 LDI R16, 0xFF ; Load R16 with immediate value ADI R16, 0x05 ; Add R16 with an immediate value ANDI R16, 0b00100101 ; AND R16 with 0x25 ``` - These are 16 bit instructions. - In instructions involving only register: 12 bit for opcode & 4 bit for register's address. - In insstructions with immediate values: 4 bits for opcode, 8 bits for immediate value & 4 bits for register's address. --- **Two register address mode:** Instructions involving two registers. Example: ```asm ADD R16, R17 ; R16 = R16 + R17 MOV R16, R17 ; Move content of R17 to R16 ``` - 16 bits instructions. - 6 bits for opcode, 5 bits for left hand register & 5 bits for right hand register. --- **Direct address mode:** In this address mode content of RAM memory or I/O registers are accessed by their direct addresses. Example: ```asm LDS R16, 0x200 ; Load R16 with the contents of location $200 STS 0x305, R20 ; Save R20's contents is RAM location $305 ``` I/O registers can be accessed by their direct memory address or their direct I/O address. Direct memory address is used in direct memory instructions & I/O addressing is used in I/O instructions. For example following two instructions are same: ```asm OUT 0x18, R16 ; 0x18 is the I/O address of port B. ; This instruction is sending content of R16 to port B. STS 0x38, R16 ; 0x38 is the memory address of port B. ; This instruction also sending content of R16 to port B. ``` I/O instructions are faster than memory instructions. also I/O registers name can be used instead of address. These names are defined in .INCLUDE file. Its safer and portable. As I/O addresses can be different in different AVR. ```asm OUT PORTB, R16 ; Send contents of R16 to port B ``` In memory instructions 16 bit is reserved for memory location. So from $0000 to $FFFF locations of memory can be addressed. So 65536 bytes of data from RAM can be accessed. In I/O instructions address field is 6 bits. So from $00 to $3F addresses can be accessed. So total 64(0 to 63) I/O registers can be accessed. These are standard I/O register memory space. In some AVRs there is more than 64 I/O registers. These extra I/O registers are called extended I/O registers. As in I/O direct addressing mode address space is 6 bits, extended I/O registers can't be accessed via I/O direct addressing mode. For these direct memory addressing mode have to be used. ```asm STS 0x62, R20 ; Save content of R20 in PORT F, which is an extended I/O ; register in ATmega128 ``` --- **Indirect memory addressing:** - `X` pointer is mapped to `R26(low byte, XL)` & `R27(hight byte, XH)` - `Y` pointer is mapped to `R28(low byte, YL)` & `R29(hight byte, YH)` - `Z` pointer is mapped to `R30(low byte, ZL)` & `R31(high byte, ZH)` `LD` instruction is used to read from the location pointed to by pointer. For example to read from location pointed by X: ```asm LD R16, X ; Load R16 with the content of data memory location ; pointed to by X ``` Load the content of data memory location 0x302 into R20: ```asm LDI XL, 0x02 ; Load R26(Lower byte of X) with 0x02 LDI XH, 0x03 ; Load R27(Higher byte of X) with 0x03. ; So, Now X is pointing to 0x302 LD R20, X ; Load R20 with content of location 0x302 ; which is pointed to by X ``` `ST` instruction is used to store a value into a location pointed to by a pointer. Example: Store the content of R20 into location 0x139F ```asm LDI XL, 0x9F ; Load XL with lower byte of the address LDI XH, 0x13 ; Load XH with higher byte of the address ST X, R20 ; Store the content of R20 into location ; pointed to by X, 0x139F ``` **Auto increment:** Incrementing pointer's lower byte with INC instruction has a problem. If the address is 0x1FF, if we increment XL, carry will not propagate into XH. In this case we can use auto increment feature: ```asm LD Rn, X+ ; Load Rn with the content of memory location pointed to ; by X and then increment X to point to the next location. ; In this case if there is a carry from lower byte of ; the address, carry will be propagate to higher byte. ``` --- **Indirect addressing with displacement:** Suppose we want to read / write from a few bytes higher than where Z is pointing. In that case we can use indirect addressing with displacement. `LDD` & `STD` instruction is used for indirect addresing with displacement. ```asm LDD Rn, Z+q ; Load Rn with the contents of memory location pointed to by Z+q STD Z+q, Rn ; Store content of Rn into location pointed to by Z+q ``` Example: Store 0x55 into location 0x401 & 0x405 ```asm LDI R20, 0x55 LDI ZL, 0x01 LDI ZH, 0x04 ST Z, R20 STD Z+4, R20 ``` --- **Look up table:** TO DO --- ### Manipulating the bits of I/O Registers --- **Setting & Clearing Bit:** To set and clear lower 32 I/O register(I/O address 0 to 31) we can use `SBI`( **S**et **B**it in **I**/O Register ) and `CBI`( **C**lear **B**it in **I**/O Register ) instruction. ```asm SBI PORTA, 1 ; Set bit 1 of PORTA CBI PORTB, 5 ; Clear bit 5 of PORTB ``` Example: Toggle PB2 200 times ```asm SBI DDRB, 2 ; PB2 is output LDI R16, 200 LOOP: SBI PORTB, 2 ; PB2 is HIGH CBI PORTB, 2 ; PB2 is LOW DEC R16 BRNE LOOP HERE: RJMP HERE ; Infinite Loop ``` **Checking the bits of I/O Registers:** To check if the bit of a I/O register is set or cleared we can use `SBIS`(Skip next instruction if Bit in I/O register is Set) and`SBIC`(Skip next instruction if Bit in I/O register is Cleared). Example: A switch is connected to pin PC7. Check the status of switch. If switch is HIGH send 'Y' to Port D. Else send 'N' to Port D. ```asm CBI DDRC, 7 ; PC7 is input pin LDI R16, 0xFF OUT DDRD, R16 ; Port D is output LOOP: SBIS PINC, 7 ; Skip next if PC7 is HIGH RJMP SHOWN LDI R16, 'Y' OUT PORTD, R16 RJMP LOOP SHOWN: LDI R16, 'N' OUT PORTD, R16 RJMP LOOP ``` ### Status Register's Bit Addressability --- **Status Reguster:** ```asm Bit: D7 D0 --------------------------------- SREG: | I | T | H | S | V | N | Z | C | --------------------------------- I = Global Interrupt V = Overflow Flag T = Bit Copy N = Negative Flag H = Half Carry Z = Zero Flag S = Sign Flag C = Carry Flag ``` **Manipulating Status Register's Bits:** `BSET` and `BCLR` instruction can be used to set and clear the bit of a status register. ```asm BSET s ; Set the bit s of status register BCLR s ; Clear the bit s of status register ``` Example: ```asm BSET 0 ; Set carry flag, C = 1 BCLR 1 ; Clear Zero flag Z = 0 ``` There are also dedicated instructions for setting and clearing each flags. Shown in the following table: | Instruction | Action | Instruction | Action | | ----------- | --------------------------- | ----------- | ----------------------------- | | SEC | Set Carry, C = 1 | CLC | Clear Carry, C = 0 | | SEZ | Set Zero, Z = 1 | CLZ | Clear Zero, Z = 0 | | SEN | Set Negative, N = 1 | CLN | Clear Negative, N = 0 | | SEV | Set Overflow, V = 1 | CLV | Clear Overflow, V = 0 | | SEH | Set Half Carry, H = 1 | CLH | Clear Half Carry, H = 0 | | SES | Set Sign, S = 1 | CLS | Clear sign, S = 0 | | SET | Set Temporary, T = 1 | CLT | Clear Temporary, T = 0 | | SEI | Set Global Interrupt, I = 1 | CLI | Clear Global Interrupt, I = 0 | **Checking Status Register Bits:** `BRBS`(Branch if status register Bit is Set) and `BRBC`(Branch if status register Bit is Cleared) instruction can be used to examine status register flags and take decisions according to their value. ```asm BRBS s,k ; Branch if bit s is set and go to relative address k BRBC s,k ; Branch if bit s is cleared and go to relative address k ``` Example: ```asm BRBS 0, L1 ; Branch if bit 0 of SREG is set and goto L1 LDI R17, 0xFF ; Otherwise insert 0xFF into R17 L1: ; address L1 ```