Pages: 1 [2]   Go Down
Author Topic: Il quiz per ratto  (Read 1068 times)
0 Members and 1 Guest are viewing this topic.
Parma
Offline Offline
Edison Member
*
Karma: 19
Posts: 2314
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In questi casi bisogna fare così: si spezzetta l'istruzione il più possibile e poi si fa debug passo passo con il simulatore di AVR Studio

Ciao
Logged

Monselice PD Italy
Offline Offline
Faraday Member
**
Karma: 25
Posts: 5480
фон Крыса
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Mi sto studiando la sintassi  smiley-grin
Recupero Recupero  smiley-cool
Logged

Se corri veloce come un fulmine, ti schianterai come un tuono.

Padova
Offline Offline
Jr. Member
**
Karma: 4
Posts: 87
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

In pratica a me serviva ottimizzare codice, e volevo risparmiare una if per impostare o pulire un bit, normalmente dobbiamo fare:
PORTA = 0
PORTA |= 1<<5
PORTA ora vale 32

Se volgiamo pulire il bit 5 impostato prima dobbiamo cambiare operatore ed invertire il risultato di 1<<5:
PORTA &= ~(1<<5)

Invece con quel codice è sempre lo stesso sia per impostare un bit che per pulirlo.

Una cosa del genere potrebbe andare?

Code:
#define set_pin_a(bit, value) PORTA = (PORTA & ~(1<<bit)) | value<<bit

ho fatto delle prove e parrebbe funzionare smiley
Logged

0
Offline Offline
Shannon Member
****
Karma: 117
Posts: 10106
:(){:|:&};: TOX id: fcb8e918bef08581e23f6ddf9d4dba77697c25b217bf372736ed959a95fde36df5b8c5b90fbb
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bhe quello che fà è
1. (PORTA & ~(1<<bit)): spegne il bit
2. | value<<bit: riaccende il bit se necessario

cmq
Quote
In the end, benchmarking is the best way to determine whether one method is really faster than another, so consider the techniques below as possibilities to test on your target architecture.

quindi mi aspetto di vedere il bamchmark per chi è più veloce :-)
Logged

my Arduino code: https://github.com/lestofante/arduinoSketch
sei nuovo? non sai da dove partire? leggi qui: http://playground.arduino.cc/Italiano/Newbie

Padova
Offline Offline
Jr. Member
**
Karma: 4
Posts: 87
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

bhe quello che fà è
1. (PORTA & ~(1<<bit)): spegne il bit
2. | value<<bit: riaccende il bit se necessario

lo so, me la sono scritta per un progetto smiley-wink
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Cmq questi usi di metodi raw sono interessantissimi, siamo quasi a livello di assembly, veramente  smiley-wink
Logged


0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@dancol90
Io quella li la capisco, quella che ho postato no.
Probabilmente non riesco a risolverla manualmente perchè quel "-" mi manda in confusione.
La velocità di esecuzione dovrebbe essere la stessa con avr-gcc ma sulle architetture moderne usate nei pc, gcc usa codice asm che non capisco, %exp, movimento in memoria con mov e un solo operatore xor.
Per avr-gcc non ho osservato il corrispondente codice asm generato dal compilatore, lo farò in seguito dopo che riposo un pò, poi posto l'asm così vediamo di capirci qualcosa.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Padova
Offline Offline
Jr. Member
**
Karma: 4
Posts: 87
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Credo che quel "-" sia proprio il complemento a due...usando la formula del tuo #define, cioè

Code:
toData ^= (-bitValue ^ toData) & (1 << nbit)

e ponendo per esempio

Code:
toData   = B01010101
nbit     = 4

Ottengo, usando bitValue = 0 (quindi voglio settare a 0 il quarto bit della variabile) :

Code:
(-00000000 ^ 01010101) & 00010000 = (00000000 ^ 01010101) & 00010000 = 01010101 & 00010000 = 00010000 => toData = toData ^ 00010000 = 01010101 ^ 00010000 = 01000101

Riapplico la formula sul nuovo valore di toData, usando questa volta bitValue = 1 (dovrei riottenere il valore originale)

Code:
(-00000001 ^ 01000101) & 00010000 = (11111111 ^ 01000101) & 00010000 = 10111010 & 00010000 = 00010000 => toData = 01000101 ^ 00010000 = 01010101

Nemmeno io riesco ad afferrare la logica che c'è dietro però, è mezz'ora che cerco di capire come funziona smiley-grin
Logged

Global Moderator
Italy
Offline Offline
Brattain Member
*****
Karma: 313
Posts: 21624
Logic is my way
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Allora, funziona così.

Codice:
Code:
uint8_t reg = 0;
uint8_t bitValue = 1;
uint8_t nBit = 4;
reg ^= (-bitValue ^ reg) & (1 << nBit);

viene fatto il complemento a 2 di bitValue. Essendo bitValue un byte che dovrebbe assumere, in quella formula, solo 0 o 1, con 1 il suo complemento diventa 0b11111111 e con 0 diventa 0b00000000. Facendo lo XOR con il valore di reg in pratica si usa bitValue come una maschera per ottenere l'opposto del valore dei bit di reg. Ricordo che lo XOR restituisce 1 solo se uno dei dur bit in causa è 1, altrimenti restituisce 0. Fatto ciò, fa un AND logico con nBit, una maschera che rappresenta il bit da modificare.

Facciamo un esempio.
reg=45 --> che in binario è 00101101
nBit = 6 --> bit che vogliamo modificare (il 7°)
bitValue = 1 --> valore che vogliamo assegnare

il risultato è 109.
Vediamo come ci arrivo.
-bitValue restituisce 0b11111111
0b11111111 XOR 00101101 restituisce 11010010
11010010 AND 010000000 restituisce 01000000 perché il bit è già a 1.
A questo punto lo XOR alla fine riassegna a reg il valore finale perché un altro XOR riporta i bit alterati al loro valore iniziale TRANNE per il bit che è stato modificato dalla funzione nel caso abbia cambiato valore.


Difatti facciamo l'esempio di cambio di stato.
reg=45 --> che in binario è 00101101
nBit = 5 --> bit che vogliamo modificare (il 6°)
bitValue = 0 --> valore che vogliamo assegnare

Come sopra, ma questa volta pongo il bit a 0.
reg ^= (-bitValue ^ reg) & (1 << nBit

-bitValue restituisce 00000000
00000000 XOR 00101101 restituisce 00101101
00101101 AND 00100000 restituisce 00100000
00101101 XOR 00100000 restituisce 00001101
00001101 è 13 in decimale
Logged


0
Offline Offline
Faraday Member
**
Karma: 23
Posts: 2792
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Cacchio, sbagliavo il complemento a 2, si deve aggiungere 1 il lo dimenticavo.

Il complemento a due si ottinene invertendo ogni singolo bit e poi aggiungere 1, quindi -.1 è 255 e 0 non può essere negativo e rimane tale.

A quel link ci sono tantissime altre cose interessanti che meritano di essere capite, per adesso io passo, giornata pesante e il caldo mi tormenta.

Grazie.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Pages: 1 [2]   Go Up
Jump to: