rng.c
00001
00002
00003
00004 #include "rng.h"
00005 #include <avr/interrupt.h>
00006 #include <avr/io.h>
00007 #include <util/delay.h>
00008 #include "contiki.h"
00009
00010 #ifndef RNG_CONF_USE_ADC
00011 #define RNG_CONF_USE_ADC (!RNG_CONF_USE_RADIO_CLOCK && defined(ADMUX) && defined(ADCSRA) && defined(ADCSRB) && defined(ADSC) && defined(ADEN))
00012 #endif
00013
00014 #ifndef RNG_CONF_USE_RADIO_CLOCK
00015 #define RNG_CONF_USE_RADIO_CLOCK ((!RNG_CONF_USE_ADC) && RF230BB)
00016 #endif
00017
00018
00019
00020
00021 #define TEMPORAL_AGITATION() do { static uint8_t agitator; agitator*=97; agitator+=101; _delay_loop_1(agitator>>1); } while (0);
00022
00023
00024
00025 #if RNG_CONF_USE_ADC
00026
00027
00028
00029
00030
00031
00032
00033 #define BITS_TO_SHIFT 9
00034
00035 #define ADC_CHAN_ADC1 ((0<<MUX4)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(1<<MUX0))
00036 #define ADC_CHAN_BAND_GAP ((1<<MUX4)|(1<<MUX3)|(1<<MUX2)|(1<<MUX1)|(0<<MUX0))
00037 #define ADC_REF_AREF ((0<<REFS1)|(0<<REFS0))
00038 #define ADC_REF_AVCC ((0<<REFS1)|(1<<REFS0))
00039 #define ADC_REF_INT ((1<<REFS1)|(1<<REFS0))
00040 #define ADC_TRIG_FREE_RUN ((0<<ADTS2)|(0<<ADTS1)|(0<<ADTS0))
00041 #define ADC_PS_128 ((1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0))
00042 #define ADC_PS_2 ((0<<ADPS2)|(0<<ADPS1)|(1<<ADPS0))
00043
00044 #ifndef CONTIKI_CONF_RNG_ADC_CHANNEL
00045 #define CONTIKI_CONF_RNG_ADC_CHANNEL ADC_CHAN_BAND_GAP
00046 #endif
00047
00048 #ifndef CONTIKI_CONF_RNG_ADC_REF
00049 #define CONTIKI_CONF_RNG_ADC_REF ADC_REF_INT
00050 #endif
00051
00052 static uint8_t
00053 extract_random_bit_() {
00054 uint8_t ret = 0;
00055
00056
00057 uint8_t sreg = SREG;
00058 uint8_t adcsra = ADCSRA;
00059 uint8_t admux = ADMUX;
00060 uint8_t adcsrb = ADCSRB;
00061 #ifdef PRR
00062 uint8_t prr = PRR;
00063 #endif
00064
00065
00066 cli();
00067
00068 #ifdef PRR
00069
00070 PRR &= ~(1 << PRADC);
00071 #endif
00072
00073
00074
00075 while(ADCSRA & (1<<ADSC));
00076
00077
00078 ADCSRA = (1<<ADEN)|ADC_PS_128;
00079 ADMUX = (uint8_t)CONTIKI_CONF_RNG_ADC_REF|(uint8_t)CONTIKI_CONF_RNG_ADC_CHANNEL;
00080 ADCSRB = ADC_TRIG_FREE_RUN;
00081
00082
00083
00084
00085
00086 do {
00087
00088 ADCSRA |= (1<<ADSC);
00089
00090 while(ADCSRA & (1<<ADSC));
00091 ret = (ADC&1);
00092 ret <<= 1;
00093
00094
00095 ADCSRA |= (1<<ADSC);
00096
00097 while(ADCSRA & (1<<ADSC));
00098 ret |= (ADC&1);
00099
00100
00101
00102 ADMUX^=(1<<REFS1);
00103
00104
00105
00106
00107 } while((ret==0)||(ret==3));
00108
00109
00110 ret &= 1;
00111
00112 ADCSRA=0;
00113
00114
00115 ADCSRB = adcsrb;
00116 ADMUX = admux;
00117 ADCSRA = adcsra;
00118 #ifdef PRR
00119 PRR = prr;
00120 #endif
00121 SREG = sreg;
00122
00123 return ret;
00124 }
00125
00126
00127 #elif RNG_CONF_USE_RADIO_CLOCK
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 #define BITS_TO_SHIFT 8
00147
00148 #include "radio/rf230bb/hal.h"
00149 #include "radio/rf230bb/at86rf230_registermap.h"
00150
00151 #ifndef TRX_CTRL_0
00152 #define TRX_CTRL_0 0x03
00153 #endif
00154
00155 static uint8_t
00156 extract_random_bit_() {
00157 uint8_t ret;
00158 uint8_t trx_ctrl_0 = hal_register_read(TRX_CTRL_0);
00159
00160
00161 hal_register_write(TRX_CTRL_0,0x8|5);
00162
00163 do {
00164 TEMPORAL_AGITATION();
00165
00166 ret = !!(PIND&(1<<6));
00167 ret <<= 1;
00168 ret |= !!(PIND&(1<<6));
00169 } while((ret==0)||(ret==3));
00170
00171
00172 ret &= 1;
00173
00174
00175 hal_register_write(TRX_CTRL_0,trx_ctrl_0);
00176
00177 return ret;
00178 }
00179
00180 #endif
00181
00182
00183
00184 static uint8_t
00185 extract_random_bit() {
00186 uint8_t ret;
00187
00188
00189
00190
00191
00192
00193 while(extract_random_bit_()==1);
00194 while(extract_random_bit_()==0);
00195
00196 do {
00197 ret = extract_random_bit_();
00198 ret <<= 1;
00199 ret |= extract_random_bit_();
00200 } while((ret==0)||(ret==3));
00201
00202
00203 ret &= 1;
00204
00205 return ret;
00206 }
00207
00208 uint8_t
00209 rng_get_uint8() {
00210 uint8_t ret = 0, i;
00211 for(i=0;i<BITS_TO_SHIFT;i++) {
00212
00213 ret <<= 1;
00214
00215
00216 ret |= extract_random_bit();
00217 }
00218 return ret;
00219 }
00220