Uživatel:Dvoral10

Z MAM wiki

Přejít na: navigace, hledání

Obsah

[editovat] Hardwarový klíč k softwaru

[editovat] ZADÁNÍ

Program v PC vygeneruje vždy jinou sekvenci bitů a pošle do AVR. Tajným algoritmem jsou bity přeměněny na jinou sekvenci, která se pošle zpět do PC. Program v PC také zná stejný tajný algoritmus a podle něj ověří, zda je klíč pravý. Lze použít paralelní port, RS232 či USB.

[editovat] Zpracování

Pro komunikaci mezi počítačem a procesorem jsme využili seriový port RS232. Pro šifrování dat jsme využili šifrovací algoritmus AES - Advance Encription Standart. Program je napsán v jazyku C. Spolupracovali Lukáš Dvořák Matyáš Del Campo Václav Punda

[editovat] Prezentace

[editovat] Seriový port RS232

Ze strany procesoru je přenos řešen pomocí USART. Ze strany počítače je komunikace a její parametry nastaveny pomocí knihovny termios.h.

Parametry přenosu RS232:

  • délka slova - 8bit
  • Baud rate - 9600 Bd
  • Parity bit - Ne

Do registru UDRn se nahrávají data k přenosu, nebo přijatá data.

Kontrolní registr sériové komunikace USART0.

  • BIT 7 : RXCn indikuje kompletní příjem dat.
  • BIT 6: TXCn indikuje kompletní odeslání dat.
  • BIT 5: UDREn registr UDRn je prázdný a připraven přijmout data.

[editovat] Šifrovací algoritmus AES

Jedná se o symetrický algoritmus, to znamená že klíč musí být k dispozici jak na straně počítače, tak procesoru. Hlavní výhodou symetrického šifrování je, že je obecně velmi rychlé a dá se použít pro šifrování velkého objemu dat. Zásadní nevýhodou (pro řadu aplikací) je ale samotné použití sdíleného klíče: ten kdo data zašifroval je umí i dešifrovat a komunikují-li spolu dvě strany, je nutné, aby si klíč bezpečně předaly důvěrnou cestou. Bezpečnost šifry také závisí na kvalitě použitého klíče, musí být dostatečně komplexní a dostatečně náhodný, jinak je šifra snadno prolomitelná. Algoritmus je aplikován na data s pevně danou délkou - v tomto konkrétním případě 128 bitů. Vstupní data je datové pole o velikosti 16-ti prvků, každý prvek má velikost 8 bitů.

[editovat] Popis šifrování

Vstupní data a klíč v maticovém tvaru 4x4.

Postup šifrování

V prním kroku se maticově sečtou vstupní data a klíč. Takto upravená data se několikrát cyklicky upraví. Celkem je provedeno 10 cyklů při posledním oběhu je vynechána operace MixCulums.

Každý cyklus se skládá ze 4 úprav. Pro každý cyklus nastane změna klíče, která je popsána níže.

SubBytes :Hodnoty upravené matice dat se postupně nahradí pomocí matice S-Box, jak

ShiftRows : V tomto kroce se provede rotace řádků matice. První řádek se nerotuje, druhý se rotuje o jedno místo apod.

MixColumns : Tato záměna je provedena vynásobením předem danou maticí.

V tomto kroku se sečtou data s klíčem.

V této fázi vytváříme z předchozího klíče klíč následují.

[editovat] Dešifrování

Při dešifrování se využívá vlastnosti linearity některých operací. Požívají se operace jako : InvMixColumns , InvShiftRows a InvSubByte.

[editovat] Kód

[editovat] PC

//
//  main.c
//  Program:
//Program posílá pres RS232 kod, ten se zasifruje v procesoru a prijde zpet, potom se data rozsifrují. Pouziva se AES kodovani.
//Dvorak Lukas, Punda Vaclav, Del Campo Matyas
//ZDROJE:
//dekodovaní:http://kprox1.blogspot.cz/2012/12/c-code-of-128-bit-decryption-algorithm.html
//seriová komunikace RS232: Bakalářská práce Del Campo Matyáš 
#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <stdlib.h>
#include <conio.h>

// The number of columns comprising a state in AES. This is a constant in AES. Value=4
#define Nb 4

int main(void){
    int Nr=0;
    int Nk=0;
    unsigned char out2[16],state[4][4];
    unsigned char RoundKey[240];
    unsigned char Key[32];    
    Nr=128;
    Nk = Nr / 32;
    Nr = Nk + 6;
    
    unsigned char temp[16] = {'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5'};
    for(int i=0;i<Nk*4;i++)
    {
        Key[i]=temp[i];
    }
    char rbuffer[300];
    unsigned char out[16];
    memset(rbuffer,0,sizeof(rbuffer));
    //inicializace portu stabilně nastvena adresa dev/ttyUSB3
    int port =open("/dev/ttyUSB3", O_RDWR | O_NDELAY);//open port
    fcntl(port, F_SETFL, O_NONBLOCK);
    struct termios options;
    tcgetattr(port,&options);
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;//8 bits
    cfsetispeed(&options, B9600);//set up baud speed
    cfsetospeed(&options, B9600);
    options.c_cflag |= (CLOCAL | CREAD);
    options.c_cflag |= CS8;    /* Select 8 data bits */
    tcsetattr(port, TCSANOW, &options);
    tcflush(port,TCIOFLUSH);

    for(int i=0;i<16;i++){
        srand(time(NULL));
        out[i]=rand()%9;
    }
    write(port,out,8);
    readf(port,&rbuffer[0],sizeof(rbuffer));
    //decryption
    KeyExpansion();
    InvCipher();
    printf("%",out2);
    return 0;
}

void readf(int port, char *rbuffer, int sz){
    char mbuffer [300];
    int i;
    char *rbuffptr;
    memset(mbuffer,0,sizeof(mbuffer));//flush buffer
    int nbytesr;
    rbuffptr=mbuffer;
    while((nbytesr=read(port,mbuffer,mbuffer+sizeof(mbuffer)-rbuffptr-1))>0){
        rbuffptr+=nbytesr;
    }
    for(i=0;i<sz;i++){
        rbuffer[i]=mbuffer[i];
    }
}
//prevzato z :...

int getSBoxInvert(int num)
{
    int rsbox[256] =
    { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb
        , 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb
        , 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e
        , 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25
        , 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92
        , 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84
        , 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06
        , 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b
        , 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73
        , 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e
        , 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b
        , 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4
        , 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f
        , 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef
        , 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61
        , 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d };
    
    return rsbox[num];
}

int getSBoxValue(int num)
{
    int sbox[256] =   {
        //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 };
    return sbox[num];
}

// The round constant word array, Rcon[i], contains the values given by
// x to th e power (i-1) being powers of x (x is denoted as {02}) in the field GF(2^8)
// Note that i starts at 1, not 0).
int Rcon[255] = {
    0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
    0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
    0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
    0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
    0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
    0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
    0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
    0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
    0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
    0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
    0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
    0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
    0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
    0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
    0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
    0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb  };

// This function produces Nb(Nr+1) round keys. The round keys are used in each round to decrypt the states.
void KeyExpansion()
{
    int i,j;
    unsigned char temp[4],k;
    
    // The first round key is the key itself.
    for(i=0;i<Nk;i++)
    {
        RoundKey[i*4]=Key[i*4];
        RoundKey[i*4+1]=Key[i*4+1];
        RoundKey[i*4+2]=Key[i*4+2];
        RoundKey[i*4+3]=Key[i*4+3];
    }
    
    // All other round keys are found from the previous round keys.
    while (i < (Nb * (Nr+1)))
    {
        for(j=0;j<4;j++)
        {
            temp[j]=RoundKey[(i-1) * 4 + j];
        }
        if (i % Nk == 0)
        {
            // This function rotates the 4 bytes in a word to the left once.
            // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
            
            // Function RotWord()
            {
                k = temp[0];
                temp[0] = temp[1];
                temp[1] = temp[2];
                temp[2] = temp[3];
                temp[3] = k;
            }
            
            // SubWord() is a function that takes a four-byte input word and
            // applies the S-box to each of the four bytes to produce an output word.
            
            // Function Subword()
            {
                temp[0]=getSBoxValue(temp[0]);
                temp[1]=getSBoxValue(temp[1]);
                temp[2]=getSBoxValue(temp[2]);
                temp[3]=getSBoxValue(temp[3]);
            }
            
            temp[0] =  temp[0] ^ Rcon[i/Nk];
        }
        else if (Nk > 6 && i % Nk == 4)
        {
            // Function Subword()
            {
                temp[0]=getSBoxValue(temp[0]);
                temp[1]=getSBoxValue(temp[1]);
                temp[2]=getSBoxValue(temp[2]);
                temp[3]=getSBoxValue(temp[3]);
            }
        }
        RoundKey[i*4+0] = RoundKey[(i-Nk)*4+0] ^ temp[0];
        RoundKey[i*4+1] = RoundKey[(i-Nk)*4+1] ^ temp[1];
        RoundKey[i*4+2] = RoundKey[(i-Nk)*4+2] ^ temp[2];
        RoundKey[i*4+3] = RoundKey[(i-Nk)*4+3] ^ temp[3];
        i++;
    }
}

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void AddRoundKey(int round)
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[j][i] ^= RoundKey[round * Nb * 4 + i * Nb + j];
        }
    }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void InvSubBytes()
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[i][j] = getSBoxInvert(state[i][j]);
            
        }
    }
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void InvShiftRows()
{
    unsigned char temp;
    
    // Rotate first row 1 columns to right
    temp=state[1][3];
    state[1][3]=state[1][2];
    state[1][2]=state[1][1];
    state[1][1]=state[1][0];
    state[1][0]=temp;
    
    // Rotate second row 2 columns to right
    temp=state[2][0];
    state[2][0]=state[2][2];
    state[2][2]=temp;
    
    temp=state[2][1];
    state[2][1]=state[2][3];
    state[2][3]=temp;
    
    // Rotate third row 3 columns to right
    temp=state[3][0];
    state[3][0]=state[3][1];
    state[3][1]=state[3][2];
    state[3][2]=state[3][3];
    state[3][3]=temp;
}

// xtime is a macro that finds the product of {02} and the argument to xtime modulo {1b}
#define xtime(x)   ((x<<1) ^ (((x>>7) & 1) * 0x1b))

// Multiplty is a macro used to multiply numbers in the field GF(2^8)
#define Multiply(x,y) (((y & 1) * x) ^ ((y>>1 & 1) * xtime(x)) ^ ((y>>2 & 1) * xtime(xtime(x))) ^ ((y>>3 & 1) * xtime(xtime(xtime(x)))) ^ ((y>>4 & 1) * xtime(xtime(xtime(xtime(x))))))

// MixColumns function mixes the columns of the state matrix.
// The method used to multiply may be difficult to understand for the inexperienced.
// Please use the references to gain more information.
void InvMixColumns()
{
    int i;
    unsigned char a,b,c,d;
    for(i=0;i<4;i++)
    {
        
        a = state[0][i];
        b = state[1][i];
        c = state[2][i];
        d = state[3][i];
        
        
        state[0][i] = Multiply(a, 0x0e) ^ Multiply(b, 0x0b) ^ Multiply(c, 0x0d) ^ Multiply(d, 0x09);
        state[1][i] = Multiply(a, 0x09) ^ Multiply(b, 0x0e) ^ Multiply(c, 0x0b) ^ Multiply(d, 0x0d);
        state[2][i] = Multiply(a, 0x0d) ^ Multiply(b, 0x09) ^ Multiply(c, 0x0e) ^ Multiply(d, 0x0b);
        state[3][i] = Multiply(a, 0x0b) ^ Multiply(b, 0x0d) ^ Multiply(c, 0x09) ^ Multiply(d, 0x0e);
    }
}

// InvCipher is the main function that decrypts the CipherText.
void InvCipher()
{
    int i,j,round=0;
    
    //Copy the input CipherText to state array.
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[j][i] = rbuffer[i*4 + j];
        }
    }
    
    // Add the First round key to the state before starting the rounds.
    AddRoundKey(Nr);
    
    // There will be Nr rounds.
    // The first Nr-1 rounds are identical.
    // These Nr-1 rounds are executed in the loop below.
    for(round=Nr-1;round>0;round--)
    {
        InvShiftRows();
        InvSubBytes();
        AddRoundKey(round);
        InvMixColumns();
    }
    
    // The last round is given below.
    // The MixColumns function is not here in the last round.
    InvShiftRows();
    InvSubBytes();
    AddRoundKey(0);
    
    // The decryption process is over.
    // Copy the state array to output array.
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            out2[i*4+j]=state[j][i];
        }
    }
}

[editovat] Procesor

//
//  main.c
//  semest
//ZDROJE:
//http://kprox1.blogspot.cz/2012/12/c-code-of-128-bit-encryption-algorithm.html
//  Created by Lukas Dvorak, Matyas Del Campo, Vaclav Punda on 5/13/13.
//  Copyright (c) 2013 Lukas Dvorak. All rights reserved.
//

#include <avr/iom168.h>
#include <conio.h>
#include <stdio.h>


#define FOSC 1843200 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
#define Nb 4
int Nr=0;
int Nk=0;
unsigned char in[16], out[16], state[4][4];
unsigned char RoundKey[240];
unsigned char Key[32];


//hl. program
void main( void )
{
    USART_Init(MYUBRR);
    
    char data_L = USART_rx();    char data_H = USART_rx();
    char out_L[8];
    char out_H[8];
    Nr=128;
    
    Nk = Nr / 32;
    Nr = Nk + 6;
    
    unsigned char temp[16] = {'0','1','2','3','4','5','6','7','8','9','0','1','2','3','4','5'};
    for(int i=0;i<Nk*4;i++)
    {
        Key[i]=temp[i];
    }
    

    for (int i=0;i<16;i++){
        in[i] = USART_rx();
        }
    KeyExpansion();
    Cipher();
    for (int i=0;i<16;i++){
        if i<8 out_L[i]=out[i];
        else  out_H[i-8]=out[i];
            }
    USART_tx(out_L);
    USART_tx(out_H);
}

// funkce

void USART_Init( unsigned int ubrr) {
    /*Set baud rate */
    UBRR0H = (unsigned char)(ubrr>>8); UBRR0L = (unsigned char)ubrr;
    Enable receiver and transmitter */ UCSR0B = (1<<RXEN0)|(1<<TXEN0);
    /* Set frame format: 8data, 2stop bit */ UCSR0C = (1<<USBS0)|(3<<UCSZ00);
}

void USART_tx (unsigned char out){
    while(!(UCSRnA & (1<<UDREn)));//čekání na prázdný buffer
    UDRn = out; //posílání dat
}

void USART_rx (void){
    while(!(UCSRnA & (1<<RXCn)));
    return UDRn
}

int getSBoxValue(int num)

{
    int sbox[256] =   {
        //0     1    2      3     4    5     6     7      8    9     A      B    C     D     E     F
        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, //0
        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, //1
        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, //2
        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, //3
        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, //4
        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, //5
        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, //6
        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, //7
        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, //8
        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, //9
        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, //A
        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, //B
        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, //C
        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, //D
        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, //E
        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; //F
    return sbox[num];
}

int Rcon[255] = {
    0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
    0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39,
    0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a,
    0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8,
    0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef,
    0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc,
    0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b,
    0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3,
    0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94,
    0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20,
    0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35,
    0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f,
    0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04,
    0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63,
    0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd,
    0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb  };


void KeyExpansion()
{
    int i,j;
    unsigned char temp[4],k;
    
    // The first round key is the key itself.
    for(i=0;i<Nk;i++)
    {
        RoundKey[i*4]=Key[i*4];
        RoundKey[i*4+1]=Key[i*4+1];
        RoundKey[i*4+2]=Key[i*4+2];
        RoundKey[i*4+3]=Key[i*4+3];
    }
    
    
    while (i < (Nb * (Nr+1)))
    {
        for(j=0;j<4;j++)
        {
            temp[j]=RoundKey[(i-1) * 4 + j];
        }
        if (i % Nk == 0)
        {
            // This function rotates the 4 bytes in a word to the left once.
            // [a0,a1,a2,a3] becomes [a1,a2,a3,a0]
            
            // Function RotWord()
            {
                k = temp[0];
                temp[0] = temp[1];
                temp[1] = temp[2];
                temp[2] = temp[3];
                temp[3] = k;
            }
            
            // SubWord() is a function that takes a four-byte input word and
            // applies the S-box to each of the four bytes to produce an output word.
            
            // Function Subword()
            {
                temp[0]=getSBoxValue(temp[0]);
                temp[1]=getSBoxValue(temp[1]);
                temp[2]=getSBoxValue(temp[2]);
                temp[3]=getSBoxValue(temp[3]);
            }
            
            temp[0] =  temp[0] ^ Rcon[i/Nk];
        }
        else if (Nk > 6 && i % Nk == 4)
        {
            // Function Subword()
            {
                temp[0]=getSBoxValue(temp[0]);
                temp[1]=getSBoxValue(temp[1]);
                temp[2]=getSBoxValue(temp[2]);
                temp[3]=getSBoxValue(temp[3]);
            }
        }
        RoundKey[i*4+0] = RoundKey[(i-Nk)*4+0] ^ temp[0];
        RoundKey[i*4+1] = RoundKey[(i-Nk)*4+1] ^ temp[1];
        RoundKey[i*4+2] = RoundKey[(i-Nk)*4+2] ^ temp[2];
        RoundKey[i*4+3] = RoundKey[(i-Nk)*4+3] ^ temp[3];
        i++;
    }
}

// This function adds the round key to state.
// The round key is added to the state by an XOR function.
void AddRoundKey(int round)
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[j][i] ^= RoundKey[round * Nb * 4 + i * Nb + j];
        }
    }
}

// The SubBytes Function Substitutes the values in the
// state matrix with values in an S-box.
void SubBytes()
{
    int i,j;
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[i][j] = getSBoxValue(state[i][j]);
            
        }
    }
}

// The ShiftRows() function shifts the rows in the state to the left.
// Each row is shifted with different offset.
// Offset = Row number. So the first row is not shifted.
void ShiftRows()
{
    unsigned char temp;
    
    // Rotate first row 1 columns to left
    temp=state[1][0];
    state[1][0]=state[1][1];
    state[1][1]=state[1][2];
    state[1][2]=state[1][3];
    state[1][3]=temp;
    
    // Rotate second row 2 columns to left
    temp=state[2][0];
    state[2][0]=state[2][2];
    state[2][2]=temp;
    
    temp=state[2][1];
    state[2][1]=state[2][3];
    state[2][3]=temp;
    
    // Rotate third row 3 columns to left
    temp=state[3][0];
    state[3][0]=state[3][3];
    state[3][3]=state[3][2];
    state[3][2]=state[3][1];
    state[3][1]=temp;
}

// xtime is a macro that finds the product of {02} and the argument to xtime modulo {1b}
#define xtime(x)   ((x<<1) ^ (((x>>7) & 1) * 0x1b))

// MixColumns function mixes the columns of the state matrix
void MixColumns()
{
    int i;
    unsigned char Tmp,Tm,t;
    for(i=0;i<4;i++)
    {
        t=state[0][i];
        Tmp = state[0][i] ^ state[1][i] ^ state[2][i] ^ state[3][i] ;
        Tm = state[0][i] ^ state[1][i] ; Tm = xtime(Tm); state[0][i] ^= Tm ^ Tmp ;
        Tm = state[1][i] ^ state[2][i] ; Tm = xtime(Tm); state[1][i] ^= Tm ^ Tmp ;
        Tm = state[2][i] ^ state[3][i] ; Tm = xtime(Tm); state[2][i] ^= Tm ^ Tmp ;
        Tm = state[3][i] ^ t ; Tm = xtime(Tm); state[3][i] ^= Tm ^ Tmp ;
    }
}

// Cipher is the main function that encrypts the PlainText.
void Cipher()
{
    int i,j,round=0;
    
    //Copy the input PlainText to state array.
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            state[j][i] = in[i*4 + j];
        }
    }
    
    // Add the First round key to the state before starting the rounds.
    AddRoundKey(0);
    
    // There will be Nr rounds.
    // The first Nr-1 rounds are identical.
    // These Nr-1 rounds are executed in the loop below.
    for(round=1;round<Nr;round++)
    {
        SubBytes();
        ShiftRows();
        MixColumns();
        AddRoundKey(round);
    }
    
    // The last round is given below.
    // The MixColumns function is not here in the last round.
    SubBytes();
    ShiftRows();
    AddRoundKey(Nr);
    
    // The encryption process is over.
    // Copy the state array to output array.
    for(i=0;i<4;i++)
    {
        for(j=0;j<4;j++)
        {
            out[i*4+j]=state[j][i];
        }
    }
}





//udělat_ vyřešit pro poslání 16 bitů...toto je zatím 8;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


/* komenty
 void tr(unsigned char* out){
 unsigned char i;
 for(i=0;í<8;i++){
 if (out & (1<<8))
 portd |=1
 else
 portd &= ~1
 
 out <<=1
 out &= (portd&2)>>1
 
 }
 }
 */

[editovat] cviceni

Cviceni jsou vypracovana za spoluprace s Matyas Del Campo

[editovat] DU1

;-----------------PRVNI DOMACI UKOL--------------------------------------------------------------------
;								  	   
;		LUKÁŠ DVOŘÁK, MATYÁŠ DEL CAMPO 	      
;-------------------------------------------------------------------------------------------------------

.INCLUDE "m88def.inc"

.ORG 0x0000 
	rjmp Main ;

.ORG 0x0008 
	rjmp preruseni ; 

;------------Stack pointer init-----------------------------------------------------------------------------

	ldi r16,high(RAMEND); Main program start
	out SPH,r16 ; Set Stack Pointer to top of RAM
	ldi r16,low(RAMEND)
	out SPL,r16

;-----------inicializace vstupů a výstupů---------------------------------------------------------------------

cbi DDRC, 4; zapojení dveří
sbi PORTC, 4 Pull-ups

sbi DDRD, 5; výstup pro diodu - OCOB
sbi DDRD, 3; výstup pro diodu - OCOB

;-----------------PWMs inicializace-------------------------------------------------------------------------


	ldi R17, 0b00100011	; Fast PWM Mode, out on OC0B, non Inverting
	out TCCR0A, R17			; 
	ldi R17, 0b00001001	; WGM2:1 (Fast PWM), CS2..0:001 (internal clock,prescale=1)
	out TCCR0B, R17
	ldi R17, 0xFF	; load number of clock pulses for 1 PWM period
	out OCR0A, R17   

	ldi	r17, 0b00100011	; Fast PWM Mode, vystup na OC0B, neinverujici
	sts	TCCR2A	, r17	; sts - store direct
	ldi	r17, 0b00001001	; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1)
	sts	TCCR2B, r167	
	ldi	r16, 0xFF	; pocet pulzu pro jednu periodu
	sts	OCR2A, r16		; ocra - vystupni porovnavaci registr

;---------------SLEEP MODE-------------------------------------------------------------------------------

	ldi r16,0b00000001 ; Idle mode 
	out SMCR,r16 ; Sleep mode set

;---------------------------------------------------------------------------------------------------------
	ldi r26, PCICR ; load address of PCICR in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00000010 ; activate PCINT1
	st X, r16 ; store new PCINT1

	ldi r26, PCMSK1 ; load address of PCMSK1 in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00010001 ; allow pin change interrupt on portC bit 4, 0
	st X, r16 ; store new PCMSK1

	sei ; Enable interrupts
	
;---------------------------inicializace AD------------------------------------------------------------------

	ldi	r16,0b10000011	;Enable ADC system clk/8
	sts	ADCSRA,r16
	ldi	r16,0b01100000	;Input PC0 selected and Vcc as reference and data left alignment
	sts	ADMUX,r16
	ldi	r16,0b00000000	;Free running mode
	sts	ADCSRB,r16		
	ldi	r16,0b00000001	;Digital input ADC0 disable
	sts	DIDR0,r16

;------------------------------hl. program------------------------------------------------------------------
	ldi R21, 0x00;  dveře jsou zavřené
	ldi R20, 0x00;

loop:
	sleep ; now AVR sleeps
	nop ; return from Interrupt to this instruction
	rjmp loop ; and sleep again

preruseni:
	sbic R20,4
	rjmp bylootevreno
	rjmp bylozavreno
	
bylootevreno:
	sbis pinc,4
	rjmp interier
	rjmp budiky
	
		
bylozavreno:
	sbic pinc,4
	rjmp interier
 	rjmp budiky
	
interier:
	nesviti:
		sbrc 21,0
		rjmp cekej
		rjmp rozsvit
		
	rozsvit: 
		ldi r21, 0xFF
		out OCR0B, R16
		ldi R20, 0XFF
		reti
	
	cekej: 
		ldi r21, 0xFF
		rcall WAIT
	zhasni:
		out OCR0B, R21
		rcall WAIT2;
		dec R21
		breq 0
		rjmp zhasni
		ldi R21, 0x00
		out OCR0B, R21
		ldi R20, 0x00
		reti

	budiky:

	;ADC_start
	lds	r16,ADCSRA
	ori	r16,0b01000000	;Start conversion
	sts	ADCSRA,r16
	
	lds	r16,ADCSRA		;nacteni konfigurace z ADC
	sbrs	r16,(ADIF)		;kontrola hotoveho prevodu
	reti
	
	lds	r16,ADCH		;nacteni zmerene hodnoty
	lds r18,ADCL		

	rcall uroven		; nacteni urovne do R19 0-255	
	out OCR2B, R19
	reti
	
;------------------------zjisteni urovne--------------------------------------------------------
uroven:	
	cpi R16, 0b0000 0001
	brlo uroven0az2
	cpi R16 0b0000 0010 
	brlo uroven3az5
	cpi R16 0b0000 0011
	brlo uroven6az7
	rjmp utoven8az10
	
uroven0az2:
	cpi R18, 0b0000 0000
	breq uroven0
	cpi R18, 0b0110 0100 
	brlo uroven1
	cpi R18, 0b1100 1000
	brlo uroven2
	cpi R18, 0b1111 1111
	brlo uroven3
	rjmp uroven3
	
uroven3az5:
	cpi R18, 0b0010 1100
	brlo uroven3
	cpi R18, 0b1001 0000
	brlo uroven4
	cpi R18, 0b1111 0100
	brlo uroven5
	;brsh uroven6
	cpi R18, 0b1111 1111
	brlo uroven6
	rjmp uroven6
	
uroven6az7:
	cpi R18, 0b0101 1000
	brlo uroven6
	cpi R18, 0b1011 1100
	brlo uroven7
	cpiR18, 0b1111 1111
	brlo uroven8
	rjmp uroven8

uroven8az10:
	cpi R18, 0b0010 0000
	brlo uroven8
	cpiR18 , 0b1000 0100
	brlo uroven9
	brsh uroven10

uroven0:
	ldi R19, 0
        ret
uroven1:
	ldi R19, 25
        ret
uroven2:
	ldi R19, 50
        ret
uroven3:
	ldi R19, 75
        ret
uroven4:
	ldi R19, 100
        ret
uroven5:
	ldi R19,  125
        ret
uroven6:
	ldi R19,  150
        ret
uroven7:
	ldi R19,  175
        ret
uroven8:
	ldi R19,  200
        ret
uroven9:
	ldi R19,  225
        ret
uroven10:
	ldi R19, 255
	ret
;----------------------------WAIT----------------------------------------------------------
; wait cca 5s , F = 20MHz
WAIT:
	LDI	R16, 3			; LDI - Load Immediate
WAIT1:	
	INC	R1
	BRNE	WAIT1
	INC	R2
	BRNE	WAIT1
	INC R3
	BRNE	WAIT1
	DEC	R16
	BRNE	WAIT1
	RET

; wait cca 6ms
WAIT2:				
	INC	R4
	BRNE	WAIT2
	INC	R5
	BRNE	WAIT2
	RET
;-------------------poznámky ---------------------------------------------------------------
	;0X00	0000 0000 0000 0000
  	;0X64	0000 0000 0110 0100 
	;0XC8	0000 0000 1100 1000 

	;0X12C	0000 0001 0010 1100
	;0x190	0000 0001 1001 0000
	;0x1F4	0000 0001 1111 0100

	;0x258	0000 0010 0101 1000
	;0x2BC	0000 0010 1011 1100

	;0x320	0000 0011 0010	0000
	;0X384	0000 0011 1000	0100
	;0X3FF (0X3E8)	0000 0011 1111 1111 ( 0000 0011 1110 1000)

[editovat] Ledka


       
;Del Campo Matyas & Dvorak Lukas zapojena dve tlacitka, ovladani ledky

.EQU DDRB = $17         ; DDRB address
.EQU PORTB = $18        ; PORTB address
.EQU PINB = $16
.EQU DDRD = $11
.EQU PORTD = $12
.EQU PIND = $10
.EQU LED_X = 0          ; LED_X is on PB0, pin 12 of ATtiny2313  
.EQU LED_Y = 1          ; LED_Y is on PB1, pin 13 of ATtiny2313

; Pins connected to LED are outputs, DDRx=1 (set):
        SBI     DDRB, LED_X     ; SBI - Set Bit in I/O Register
        SBI     DDRB, LED_Y
        SBI DDRD, 2
        SBI PORTB, 2
    SBI PORTB, 3

GO:
        RCALL   DARK
        //RCALL WAIT
        SBIS    PINB, 2
        RCALL   COLOR2
//      RCALL   WAIT
    SBIS    PINB,3
        RCALL   COLOR1
    RJMP    GO
;;;
;;;
;;; P R O C E D U R E S
;;;
;;;

SMALLWAIT:
        INC     R1                              ; INC - Increment
        BRNE    SMALLWAIT       ; BRNE - Branch if Not Equal (Z flag)
        RET                                     ; RET - Return from Subroutine

WAIT:
        LDI     R16, 4                  ; LDI - Load Immediate
WAIT1:  INC     R1
        BRNE    WAIT1
        INC     R2
        BRNE    WAIT1
        DEC     R16
        BRNE    WAIT1
        RET

COLOR1:
    SBI PORTB, LED_X
        CBI     PORTB, LED_Y    ; CBI - Clear Bit in I/O Register
        RET

COLOR2:
    SBI PORTB, LED_Y
        CBI     PORTB, LED_X
        RET

COL3W:
        LDI     R16, 2
COL3X:  RCALL   COLOR1
        RCALL   SMALLWAIT
        RCALL   COLOR2
        RCALL   SMALLWAIT
        INC     R2
        BRNE    COL3X
        DEC     R16
        BRNE    COL3X

DARK:
    CBI PORTB, LED_X
        CBI     PORTB, LED_Y
        RET



[editovat] PWM s klavesnici

;Del Campo Matyas & Dvorak Lukas 
; example fan program for ATmega88
	.INCLUDE "m88def.inc"  ; replaces previous lines of the program
	.EQU FAN = 2
	SBI	DDRB, FAN

; Basic keyboard init:

; One switch of matrix keyboard is connected between PINC 2 a PIND 2
; Zero values of DDRC, 2 and PORTB, 2 are implicit
; Keyboard init:
	cbi DDRC, 2 ; set inputs for keyboard (COL1-3)
	cbi DDRC, 3
	cbi DDRC, 4

	sbi PORTC, 2 ; set internal Pull-Ups for keyboard
	sbi PORTC, 3
	sbi PORTC, 4

	sbi DDRD, 0 ; set driving outputs for keyboard
	sbi DDRD, 1 ; (ROW1-ROW4)
	sbi DDRD, 2
	sbi DDRD, 3

	cbi PORTD, 0	; log. 0 on all rows
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3

	LDI	R16, 0


; Init:
	RCALL   FAN_OFF


	GO:   
	RCALL KEYPRESS
	RCALL	PWM   ; Simple PWM control of the FAN, if the key is pressed
	RJMP	GO   
;;;
;;;
;;; P R O C E D U R E S
;;;
;;;
    
VERYSMALLWAIT:
	LDI R20, 0xFC
	MOV R1, R20
SMALLWAIT:
	INC	R1
	BRNE	SMALLWAIT
	RET

WAIT:
	LDI	R21, 4
WAIT1:
	INC	R1
	BRNE	WAIT1
	INC	R2
	BRNE	WAIT1
	DEC	R21
	BRNE	WAIT1
	RET
    
FAN_ON:
	SBI	PORTB, FAN
	RET

FAN_OFF:
	CBI	PORTB, FAN
	RET

FAN_PWM:
	RCALL	FAN_ON
	RCALL	WAIT ; pulse ratio controlled by number of waits
	RCALL	VERYSMALLWAIT  ; 4:1 in this case
	RCALL	VERYSMALLWAIT
	RCALL	VERYSMALLWAIT
	RCALL	FAN_OFF
	RCALL	VERYSMALLWAIT 

	RET

PWM:
	MOV 	R17, R16
	INC		R17
	LDI		R18, 0xF8
	OR		R18, R16
PWM_ON:
	DEC		R17
	BREQ	PWM_OFF
	SBI		PORTB, FAN
	RCALL 	VERYSMALLWAIT
	RJMP	PWM_ON
PWM_OFF:
	INC		R18
	BREQ	PWM_RET
	CBI		PORTB, FAN
	RCALL 	VERYSMALLWAIT
	RJMP	PWM_OFF
PWM_RET:
	RET
KEYPRESS:
KEY0:
	sbi 	PORTD, 0
	sbi 	PORTD, 1
	sbi 	PORTD, 2
	cbi 	PORTD, 3	;log. 0 to the row with *, 0, #, D	
	sbic	PINC, 3
	rjmp	KEY1
	ldi	R16, 0		;pressed key 0
	rjmp	KEYRET
KEY1:
	cbi 	PORTD, 0	;log. 0 to the row with 1, 2, 3, A
	sbi 	PORTD, 1	;log. 1 on another three
	sbi 	PORTD, 2
	sbi 	PORTD, 3	
	sbic	PINC, 2
	rjmp	KEY2
	ldi	R16, 1		;pressed key 1
	rjmp	KEYRET
KEY2:
	sbic	PINC, 3
	rjmp	KEY3
	ldi	R16, 2
	rjmp	KEYRET
KEY3:
	sbic	PINC, 4
	rjmp	KEY4
	ldi	R16, 3
	rjmp	KEYRET

KEY4:
	sbi 	PORTD, 0
	cbi 	PORTD, 1	;log. 0 to the row with 4, 5, 6, B
	sbi 	PORTD, 2
	sbi 	PORTD, 3	
	sbic	PINC, 2
	rjmp	KEY5
	ldi	R16, 4		;pressed key 4
	rjmp	KEYRET
KEY5:
	sbic	PINC, 3
	rjmp	KEY6
	ldi	R16, 5
	rjmp	KEYRET
KEY6:
	sbic	PINC, 4
	rjmp	KEY7
	ldi	R16, 6
	rjmp	KEYRET

KEY7:
	sbi 	PORTD, 0
	sbi 	PORTD, 1
	cbi 	PORTD, 2	;log. 0 to the row with 7, 8, 9, C
	sbi 	PORTD, 3	
	sbic	PINC, 2
	rjmp	KEY8
	ldi	R16, 7		;pressed key 7
	rjmp	KEYRET
KEY8:
	sbic	PINC, 3
	rjmp	KEY9
	ldi	R16, 8
	rjmp	KEYRET
KEY9:
	sbic	PINC, 4
	rjmp	KEYRET
	ldi	R16, 9

KEYRET:
	cbi PORTD, 0	; log. 0 on all rows for next key press catch
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3
	ret

[editovat] PWM citac

; 
; example fan program for ATmega168 with Timer controlled PWM&Interrupt&Sleep
;
; Rotation speed  is controlled by keyboard, 
; keys 0-9 represent the speed between 0 and 100 %
;
; Fan starts to rotate with the first valid key press
;
; To do: *** Catch only the key press, not key release
;
; To do: *** Set higher value of PWM (=higher fan rpm) for 
; a few first periods to start the fan reliably
;
;
; P4 CPU fan Ucc pin is supposed to be connected 
; to +15 V, GND pin is supposed to be connected 
; to NMOS Drain,, Source on GND, Gate on 
; pin 11 (OC0B, PD5). Fan runs when pin 11 is high.


.INCLUDE "m168def.inc"

.EQU PWM_PULSES = 36	; value for 27.8 kHz PWM
;.EQU PWM_PULSES = 45	; value for 22.2 kHz PWM


.ORG 0x0000 
	jmp Main ; Reset Handler

.ORG 0x0008 
	jmp isr1 ; PCINT1 Handler



; Main program start

Main: 

; Stack pointer init:
	ldi r16,high(RAMEND); Main program start
	out SPH,r16 ; Set Stack Pointer to top of RAM
	ldi r16,low(RAMEND)
	out SPL,r16


; Hardware initialization

; Keyboard init:
	cbi DDRC, 2 ; set inputs for keyboard (COL1-3)
	cbi DDRC, 3
	cbi DDRC, 4

	sbi PORTC, 2 ; set internal Pull-Ups for keyboard
	sbi PORTC, 3
	sbi PORTC, 4

	sbi DDRD, 0 ; set driving outputs for keyboard
	sbi DDRD, 1 ; (ROW1-ROW4)
	sbi DDRD, 2
	sbi DDRD, 3

	cbi PORTD, 0	; log. 0 on all rows
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3


; Timer controlled PWM init:
;
; There are registers TCCR0A and TCCR0B for config, DDRD for output bit
; enabling, OCR0A for counter lenght and OCR0A for pulse "high" lenght.
; Register TIMSK0 controlls interrupts - not used, 0x00 by default 

PWM_INIT:
	ldi R17, 0b00100011	; Fast PWM Mode, out on OC0B, non Inverting
	out TCCR0A, R17			; 
	ldi R17, 0b00001001	; WGM2:1 (Fast PWM), CS2..0:001 (internal clock, prescale=1)
	out TCCR0B, R17
	ldi R17, PWM_PULSES	; load number of clock pulses for 1 PWM period
	out OCR0A, R17   

	sbi DDRD, 5	; set pin 11 as PWM output OC0B (PD5 pin)


; Keyboard interrupt setup
;
; Activation of pin change interrupt - PROBLEM!!! PCICR and PCIMSK are 
; extended I/O registers (0x68 and 0x6C), and must be handled as 
; a memory location

	ldi r26, PCICR ; load address of PCICR in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00000010 ; activate PCINT1
	st X, r16 ; store new PCINT1

	ldi r26, PCMSK1 ; load address of PCMSK1 in Y low
	clr r27 ; load high byte with 0
	ldi r16,0b00011100 ; allow pin change interrupt on portC bits 2,3,4
	st X, r16 ; store new PCMSK1

	sei ; Enable interrupts


; Set sleep mode of the CPU
; SMCR: 0,0,0,0,SM2,SM1,SM0,SE   SM2..0: Sleep Mode Select Bits, SE: Sleep enabled)

	ldi r16,0b00000001 ; Idle mode 
	out SMCR,r16 ; Sleep mode set


; Sleep loop, wake up by the Interrupt, return with RETI back to sleep loop

loop:
	sleep ; now AVR sleeps
	nop ; return from Interrupt to this instruction
	rjmp loop ; and sleep again
isr1:
	rcall KEYPRESS
        ldi R17, 0b00100011	; Fast PWM Mode, out on OC0B, non Inverting
	out TCCR0A, R17	
	cpi R16,0
	breq off
        mov R17, R16
	lsl R17
	lsl R17	; multiply key number by 4 for 10 steps in 40 clock pulses of PWM
	out OCR0B, R17  ; output pulse "high" lenght to PWM compare unit 
	reti ; return from Interrupt

off:
	ldi R17, 0b00000011	; Fast PWM Mode, out on OC0B, non Inverting
	out TCCR0A, R17
	cbi PORTD, 5
	reti
; Keyboard decoding:

KEYPRESS:
KEY0:
	sbi 	PORTD, 0
	sbi 	PORTD, 1
	sbi 	PORTD, 2
	cbi 	PORTD, 3	;log. 0 to the row with *, 0, #, D	
	sbic	PINC, 3
	rjmp	KEY1
	ldi	R16, 0		;pressed key 0
	rjmp	KEYRET
KEY1:
	cbi 	PORTD, 0	;log. 0 to the row with 1, 2, 3, A
	sbi 	PORTD, 1	;log. 1 on another three
	sbi 	PORTD, 2
	sbi 	PORTD, 3	
	sbic	PINC, 2
	rjmp	KEY2
	ldi	R16, 1		;pressed key 1
	rjmp	KEYRET
KEY2:
	sbic	PINC, 3
	rjmp	KEY3
	ldi	R16, 2
	rjmp	KEYRET
KEY3:
	sbic	PINC, 4
	rjmp	KEY4
	ldi	R16, 3
	rjmp	KEYRET

KEY4:
	sbi 	PORTD, 0
	cbi 	PORTD, 1	;log. 0 to the row with 4, 5, 6, B
	sbi 	PORTD, 2
	sbi 	PORTD, 3	
	sbic	PINC, 2
	rjmp	KEY5
	ldi	R16, 4		;pressed key 4
	rjmp	KEYRET
KEY5:
	sbic	PINC, 3
	rjmp	KEY6
	ldi	R16, 5
	rjmp	KEYRET
KEY6:
	sbic	PINC, 4
	rjmp	KEY7
	ldi	R16, 6
	rjmp	KEYRET

KEY7:
	sbi 	PORTD, 0
	sbi 	PORTD, 1
	cbi 	PORTD, 2	;log. 0 to the row with 7, 8, 9, C
	sbi 	PORTD, 3	
	sbic	PINC, 2
	rjmp	KEY8
	ldi	R16, 7		;pressed key 7
	rjmp	KEYRET
KEY8:
	sbic	PINC, 3
	rjmp	KEY9
	ldi	R16, 8
	rjmp	KEYRET
KEY9:
	sbic	PINC, 4
	rjmp	KEYRET
	ldi	R16, 9

KEYRET:
	cbi PORTD, 0	; log. 0 on all rows for next key press catch
	cbi PORTD, 1
	cbi PORTD, 2
	cbi PORTD, 3
	ret

[editovat] segment


cbi DDRB,2 			
sbi PORTB, 2 		; set internal Pull-Ups


sbi DDRB, 3  		; nastaveni serioveho vystupu
cbi PORTB, 3

sbi DDRB, 4			;nastaveni vypinani
cbi PORTB, 4



MAIN:
SBIS PORTB,2

RJMP POSLI

RJMP MAIN

POSLI:
SBI PORTB,4

CBI PORTB,4
CBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
CBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
CBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
CBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
CBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
CBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
SBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
SBI  PORTB,3
SBI PORTB,4

CBI PORTB,4
CBI  PORTB,3
SBI PORTB,4

RET
Osobní nástroje