diff --git a/Makefile b/Makefile index 14e0590f12511d3318b4b345a0527c88a3d9a462..0917053776a396a24e32409978d9f9ce6fa84375 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ PROJECT=bioloid_exp ######################################################## # afegir tots els fitxers que s'han de compilar aquà ######################################################## -SOURCES=src/main.c src/dyn_slave_se.c src/dyn_slave_diff.c src/mem.c src/dyn_common.c src/ports.c +SOURCES=src/main.c src/dyn_slave_se.c src/dyn_slave_diff.c src/mem.c src/dyn_common.c src/ports.c src/adc.c OBJS=$(SOURCES:.c=.o) SRC_DIR=./src/ INCLUDE_DIR=./include/ diff --git a/include/adc.h b/include/adc.h new file mode 100644 index 0000000000000000000000000000000000000000..e09a9ecc3d09d66bc62e24e1c58a77f9c52a168a --- /dev/null +++ b/include/adc.h @@ -0,0 +1,12 @@ +#ifndef _ADC_H +#define _ADC_H + +#include <avr/io.h> +#include <avr/interrupt.h> + +void adc_init(void); +void adc_start(void); +void adc_stop(void); +void adc_set_num_samples(unsigned char num); + +#endif diff --git a/include/memory_map.h b/include/memory_map.h index 6378a4d0befda1def7708d662ade01f1d17887ed..bd471084d4aafed05e74c6e1d3ce970c982eed4a 100644 --- a/include/memory_map.h +++ b/include/memory_map.h @@ -7,48 +7,145 @@ #define Version_Firmware 0X02 //2 - 0X00 R - Information on the version of firmware #define ID 0X03 //3 - 0X03 R/W - ID of Dynamixel #define Baud_Rate 0X04 //4 - 0X01 R/W - Baud Rate of Dynamixel -#define Return_Delay_Time 0X05 //5 - 0XFA R/W - Return Delay Time -#define Status_Return_Level 0X10 +#define Return_Delay_Time 0X05 //5 - 0XFA R/W - Return Delay Time (value*2us) currently not implemented +#define Status_Return_Level 0X10 //16 - 0x10 R/W - Level os reply information +// EEPROM end at 0x1F +// RAM starts at 0x20 +#define ADC_CONTROL 0x20 //32 - 0x20 R/W ADC control bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // running enable +#define ADC_NUM_SAMPLES 0x21 //33 - 0x21 R/W Number of sample to average +#define GPIO0_config 0x30 //48 - 0x30 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO0_data 0x31 //49 - 0x31 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO1_config 0x32 //50 - 0x32 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO1_data 0x33 //51 - 0x33 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO2_config 0x34 //52 - 0x34 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO2_data 0x35 //53 - 0x35 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO3_config 0x36 //54 - 0x36 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO3_data 0x37 //55 - 0x37 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO4_config 0x38 //56 - 0x38 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO4_data 0x39 //57 - 0x39 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO5_config 0x3A //58 - 0x3A R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO5_data 0x3B //59 - 0x3B R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO6_config 0x3C //60 - 0x3C R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO6_data 0x3D //61 - 0x3D R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO7_config 0x3E //62 - 0x3E R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO7_data 0x3F //63 - 0x3F R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO8_config 0x40 //64 - 0x40 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO8_data 0x41 //65 - 0x41 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO9_config 0x41 //66 - 0x42 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO9_data 0x43 //67 - 0x43 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO10_config 0x44 //68 - 0x44 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO10_data 0x45 //69 - 0x45 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO11_config 0x46 //70 - 0x46 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO11_data 0x47 //71 - 0x47 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO12_config 0x48 //72 - 0x48 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO12_data 0x49 //73 - 0x49 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO13_config 0x4A //74 - 0x4A R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO13_data 0x4B //75 - 0x4B R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO14_config 0x4C //76 - 0x4C R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO14_data 0x4D //77 - 0x4D R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO15_config 0x4E //78 - 0x4E R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO15_data 0x4F //79 - 0x4F R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO16_config 0x50 //80 - 0x50 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO16_data 0x51 //81 - 0x51 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO17_config 0x52 //82 - 0x52 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO17_data 0x53 //83 - 0x53 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define GPIO18_config 0x54 //84 - 0x54 R/W GPIO 0 configuration bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // mode (0 -> input, 1 -> output) +#define GPIO18_data 0x55 //85 - 0x55 R/W GPIO 0 data bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current input value (input mode) + // output value (output mode) +#define LED 0x56 //86 - 0x56 R/W Auxiliary LED bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current value +#define SWITCHES 0x57 //87 - 0x57 R Auxiliary Switches bit 7 | bit 6 | bit 5 | bit 4 | bit 3 | bit 2 | bit 1 | bit 0 + // current switches value +#define ADC_CHANNEL0_L 0x58 +#define ADC_CHANNEL0_H 0x59 +#define ADC_CHANNEL1_L 0x5A +#define ADC_CHANNEL1_H 0x5B +#define ADC_CHANNEL2_L 0x5C +#define ADC_CHANNEL2_H 0x5D +#define ADC_CHANNEL3_L 0x5E +#define ADC_CHANNEL3_H 0x5F +#define ADC_CHANNEL4_L 0x60 +#define ADC_CHANNEL4_H 0x61 +#define ADC_CHANNEL5_L 0x62 +#define ADC_CHANNEL5_H 0x63 +#define ADC_CHANNEL6_L 0x64 +#define ADC_CHANNEL6_H 0x65 +#define ADC_CHANNEL7_L 0x66 +#define ADC_CHANNEL7_H 0x67 +#define ADC_AVG_CHANNEL0_L 0x68 +#define ADC_AVG_CHANNEL0_H 0x69 +#define ADC_AVG_CHANNEL1_L 0x6A +#define ADC_AVG_CHANNEL1_H 0x6B +#define ADC_AVG_CHANNEL2_L 0x6C +#define ADC_AVG_CHANNEL2_H 0x6D +#define ADC_AVG_CHANNEL3_L 0x6E +#define ADC_AVG_CHANNEL3_H 0x6F +#define ADC_AVG_CHANNEL4_L 0x70 +#define ADC_AVG_CHANNEL4_H 0x71 +#define ADC_AVG_CHANNEL5_L 0x72 +#define ADC_AVG_CHANNEL5_H 0x73 +#define ADC_AVG_CHANNEL6_L 0x74 +#define ADC_AVG_CHANNEL6_H 0x75 +#define ADC_AVG_CHANNEL7_L 0x76 +#define ADC_AVG_CHANNEL7_H 0x77 -#define GPIO0_config 0x30 // R/W GPIO 0 configuration -#define GPIO0_data 0x31 // R/W GPIO 0 data -#define GPIO1_config 0x32 // R/W GPIO 1 configuration -#define GPIO1_data 0x33 // R/W GPIO 1 data -#define GPIO2_config 0x34 // R/W GPIO 2 configuration -#define GPIO2_data 0x35 // R/W GPIO 2 data -#define GPIO3_config 0x36 // R/W GPIO 3 configuration -#define GPIO3_data 0x37 // R/W GPIO 3 data -#define GPIO4_config 0x38 // R/W GPIO 4 configuration -#define GPIO4_data 0x39 // R/W GPIO 4 data -#define GPIO5_config 0x3A // R/W GPIO 5 configuration -#define GPIO5_data 0x3B // R/W GPIO 5 data -#define GPIO6_config 0x3C // R/W GPIO 6 configuration -#define GPIO6_data 0x3D // R/W GPIO 6 data -#define GPIO7_config 0x3E // R/W GPIO 7 configuration -#define GPIO7_data 0x3F // R/W GPIO 7 data -#define GPIO8_config 0x40 // R/W GPIO 8 configuration -#define GPIO8_data 0x41 // R/W GPIO 8 data -#define GPIO9_config 0x41 // R/W GPIO 9 configuration -#define GPIO9_data 0x43 // R/W GPIO 9 data -#define GPIO10_config 0x44 // R/W GPIO 10 configuration -#define GPIO10_data 0x45 // R/W GPIO 10 data -#define GPIO11_config 0x46 // R/W GPIO 11 configuration -#define GPIO11_data 0x47 // R/W GPIO 11 data -#define GPIO12_config 0x48 // R/W GPIO 12 configuration -#define GPIO12_data 0x49 // R/W GPIO 12 data -#define GPIO13_config 0x4A // R/W GPIO 13 configuration -#define GPIO13_data 0x4B // R/W GPIO 13 data -#define GPIO14_config 0x4C // R/W GPIO 14 configuration -#define GPIO14_data 0x4D // R/W GPIO 14 data -#define GPIO15_config 0x4E // R/W GPIO 15 configuration -#define GPIO15_data 0x4F // R/W GPIO 15 data -#define GPIO16_config 0x50 // R/W GPIO 16 configuration -#define GPIO16_data 0x51 // R/W GPIO 16 data -#define GPIO17_config 0x52 // R/W GPIO 17 configuration -#define GPIO17_data 0x53 // R/W GPIO 17 data -#define GPIO18_config 0x54 // R/W GPIO 18 configuration -#define GPIO18_data 0x55 // R/W GPIO 18 data - -#define RAM_SIZE 86 +#define RAM_SIZE 120 #endif diff --git a/include/ports.h b/include/ports.h index bc7ae7ae9c39e841ec452fc92bda69ca0b06dddc..16b6773576d21fe9b6301a6fbde2c7c5b6037e20 100644 --- a/include/ports.h +++ b/include/ports.h @@ -22,6 +22,7 @@ void clear_port(unsigned char port_id); unsigned char read_port(unsigned char port_id); void set_led(void); void clear_led(void); +void toggle_led(void); unsigned char get_selector_value(void); #endif diff --git a/src/adc.c b/src/adc.c new file mode 100644 index 0000000000000000000000000000000000000000..92958d0d601f1fa5e4474e5efe2ffc6bdc731847 --- /dev/null +++ b/src/adc.c @@ -0,0 +1,115 @@ +#include "adc.h" +#include "mem.h" +#include "ports.h" + +// number of channels to convert +#define NUM_CH 8 +// number of samples to average +#define MAX_NUM_SAMPLES 16 + +// private variables +// current channel +volatile unsigned char current_ch; +// list of channels to convert +const unsigned char list_ch[NUM_CH]={0,1,2,3,4,5,6,7}; +// channel data +volatile short int adc_data[NUM_CH]; +// averaged channel data +volatile short int ch_data[NUM_CH][MAX_NUM_SAMPLES]; +volatile unsigned char current_sample; +volatile unsigned char num_samples; + +/* private functions */ +void adc_set_channel(unsigned char ch_id) +{ + ADMUX&=0xF8; + ADMUX|= (ch_id&0x07); +} + +void adc_start_conv(void) +{ + ADCSRA|=(1<<ADSC); +} + +/* interrupt handling functions */ +ISR(ADC_vect) +{ + unsigned char i; + unsigned short int data; + + data=(ADCL | (ADCH<<8)); + ram_data[ADC_CHANNEL0_L+current_ch*2]=data%256; + ram_data[ADC_CHANNEL0_H+current_ch*2]=data/256; + ch_data[current_ch][current_sample]=data; + /* compute the average for the current channel */ + data=0; + for(i=0;i<num_samples;i++) + data+=ch_data[current_ch][i]; + data=data/num_samples; + ram_data[ADC_AVG_CHANNEL0_L+current_ch*2]=data%256; + ram_data[ADC_AVG_CHANNEL0_H+current_ch*2]=data/256; + if(current_ch==NUM_CH-1)// last channel + current_sample=(current_sample+1)%num_samples; + current_ch=(current_ch+1)%NUM_CH; +} + +ISR(TIMER2_COMP_vect) +{ + // start a new conversion + adc_set_channel(current_ch); + adc_start_conv(); +} + +/* public functions */ +void adc_init(void) +{ + // configure the analog inputs + DDRF = 0x00; + PORTF = 0x00; + + ADMUX = (1<<REFS0);// use AVCC as reference, Right justified, channel 0 + ADCSRA = (1<<ADIE) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // free running mode disabled, interrupts enabled, prescaler to 128 + + // clear any pending interrupt + ADCSRA|=(1<<ADIF); + + // set the initial channel to convert + current_ch=0; + current_sample=0; + num_samples=MAX_NUM_SAMPLES; + ram_data[ADC_NUM_SAMPLES]=MAX_NUM_SAMPLES; + + // configure the timer 2 to perform periodic conversions (1 ms period) + TCCR2=(1<<WGM21)|(1<<CS21)|(1<<CS20);// CTC mode, no output, prescaler to 64 + TCNT2=0x00;// start from 0 + OCR2=249;//1 ms period time; +} + +void adc_start(void) +{ + // enable the ADC + ADCSRA|=(1<<ADEN); + // enable the timer 2 interrupts + TCNT2=0x00;// start from 0 + TIMSK|=(1<<OCIE2);// the timer ISR will start the ADC conversion + ram_data[ADC_CONTROL]|=0x02; +} + +void adc_stop(void) +{ + // disable the timer 2 + TIMSK&=~(1<<OCIE2); + // disable the ADC + ADCSRA&=~(1<<ADEN); + ram_data[ADC_CONTROL]&=0xFD; +} + +void adc_set_num_samples(unsigned char num) +{ + if(num>MAX_NUM_SAMPLES) + num_samples=MAX_NUM_SAMPLES; + else + num_samples=num; + if(current_sample>num) + current_sample=0; +} diff --git a/src/dyn_common.c b/src/dyn_common.c index 193ea952a667f68cf09eb090ab155ca86d773a2a..23ace637763ac54c7ea7d34e8d022999d7cb5608 100644 --- a/src/dyn_common.c +++ b/src/dyn_common.c @@ -2,6 +2,7 @@ #include "dyn_slave_se.h" #include "mem.h" #include "ports.h" +#include "adc.h" void do_write(unsigned char address,unsigned char length,unsigned char *data) { @@ -25,6 +26,23 @@ void do_write(unsigned char address,unsigned char length,unsigned char *data) set_port((i-GPIO0_data)>>1); } } + else if(i==LED) + { + if(data[num]==0x00) + clear_led(); + else + set_led(); + } + else if(i==ADC_CONTROL) + { + if(data[num]==0x00) + adc_stop(); + else + adc_start(); + } + else if(i==ADC_NUM_SAMPLES) + adc_set_num_samples(data[num]); + num++; } } @@ -41,6 +59,8 @@ unsigned char do_read(unsigned char address,unsigned char length,unsigned char * if((i%2)!=0) // data register read_port((i-GPIO0_config)>>1); } + else if(i==SWITCHES) + get_selector_value(); } return ram_read(address,length,data); } diff --git a/src/main.c b/src/main.c index e2caa4f1c0d6c211b38c497ad5290347b7d8ce6e..71783275b6bb370487ab43914422aec2760d9c8a 100755 --- a/src/main.c +++ b/src/main.c @@ -5,6 +5,7 @@ #include "dyn_slave_diff.h" #include "mem.h" #include "ports.h" +#include "adc.h" int16_t main(void) { @@ -12,9 +13,9 @@ int16_t main(void) dyn_slave_se_init(ram_data[Baud_Rate],ram_data[ID]); dyn_slave_diff_init(ram_data[Baud_Rate],ram_data[ID]); init_ports(); + adc_init(); sei(); - set_led(); while (1) { dyn_slave_se_loop(); diff --git a/src/ports.c b/src/ports.c index a2ed47358c9c58237081c4bb64ec0f557c3e918d..2a0615378fe8892d23ecd3f50b5c2c93ceb4cb3f 100644 --- a/src/ports.c +++ b/src/ports.c @@ -26,6 +26,7 @@ void init_ports(void) { //auxiliar LED DDRE|=0x04; + clear_led(); // general purpose input/output // all inputs by default @@ -42,15 +43,9 @@ void config_port(unsigned char port_id,unsigned char dir) if(port_id>=0 && port_id<NUM_GPIO) { if(dir==OUTPUT)// configure as an output - { *(gpio_bits[port_id].dir_reg)|=0x01<<gpio_bits[port_id].bit; - ram_data[GPIO0_config+port_id]=OUTPUT; - } else// configure as an input - { *(gpio_bits[port_id].dir_reg)&=~(0x01<<gpio_bits[port_id].bit); - ram_data[GPIO0_config+port_id]=INPUT; - } } } @@ -73,19 +68,13 @@ unsigned char get_port_config(unsigned char port_id) void set_port(unsigned char port_id) { if(port_id>=0 && port_id<NUM_GPIO) - { *(gpio_bits[port_id].write_reg)|=0x01<<gpio_bits[port_id].bit; - ram_data[GPIO0_data+port_id]=0x01; - } } void clear_port(unsigned char port_id) { if(port_id>=0 && port_id<NUM_GPIO) - { *(gpio_bits[port_id].write_reg)&=~(0x01<<gpio_bits[port_id].bit); - ram_data[GPIO0_data+port_id]=0x00; - } } unsigned char read_port(unsigned char port_id) @@ -119,8 +108,14 @@ void clear_led(void) PORTE|=0x04; } +void toggle_led(void) +{ + PORTE^=0x04; +} + unsigned char get_selector_value(void) { + ram_data[SWITCHES]=(PING&0x18)>>3; return ((PING&0x18)>>3); }