maca.c

00001 /*
00002  * Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
00003  * to the MC1322x project (http://mc1322x.devl.org)
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the Institute nor the names of its contributors
00015  *    may be used to endorse or promote products derived from this software
00016  *    without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
00019  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
00022  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00023  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00024  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00025  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00026  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00027  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * This file is part of libmc1322x: see http://mc1322x.devl.org
00031  * for details. 
00032  *
00033  *
00034  */
00035 
00036 #include <mc1322x.h>
00037 #include <stdio.h>
00038 
00039 #ifndef DEBUG_MACA 
00040 #define DEBUG_MACA 0
00041 #endif
00042 #if (DEBUG_MACA == 0)
00043 #define PRINTF(...) 
00044 #else
00045 #define PRINTF(...) printf(__VA_ARGS__)
00046 #endif
00047 
00048 #ifndef MACA_BOUND_CHECK
00049 #define MACA_BOUND_CHECK 0
00050 #endif
00051 #if (MACA_BOUND_CHECK == 0)
00052 #define BOUND_CHECK(x)
00053 #else
00054 #define BOUND_CHECK(x) bound_check(x)
00055 #endif
00056 
00057 #ifndef NUM_PACKETS
00058 #define NUM_PACKETS 32
00059 #endif
00060 
00061 /* for 250kHz clock */
00062 #define MACA_CLOCK_DIV 95
00063 /* (32 chips/sym) * (sym/4bits) * (8bits/byte) = (64 chips/byte)  */
00064 /* (8 chips/clk) * (byte/64 chips) = byte/8clks */
00065 #define CLK_PER_BYTE 8 
00066 
00067 #ifndef RECV_SOFTIMEOUT
00068 #define RECV_SOFTIMEOUT (1024*128*CLK_PER_BYTE) 
00069 #endif
00070 
00071 #ifndef CPL_TIMEOUT
00072 #define CPL_TIMEOUT (2*128*CLK_PER_BYTE) 
00073 #endif
00074 
00075 #define reg(x) (*(volatile uint32_t *)(x))
00076 
00077 int count_packets(void);
00078 void Print_Packets(char *s);
00079 
00080 static volatile packet_t packet_pool[NUM_PACKETS];
00081 static volatile packet_t *free_head, *rx_end, *tx_end, *dma_tx, *dma_rx;
00082 
00083 /* rx_head and tx_head are visible to the outside */
00084 /* so you can peek at it and see if there is data */
00085 /* waiting for you, or data still to be sent */
00086 volatile packet_t *rx_head, *tx_head;
00087 
00088 /* used for ack recpetion if the packet_pool goes empty */
00089 /* doesn't go back into the pool when freed */
00090 static volatile packet_t dummy_ack;
00091 
00092 /* incremented on every maca entry */
00093 /* you can use this to detect that the receive loop is still running */
00094 volatile uint32_t maca_entry = 0;
00095 
00096 enum posts {
00097         NO_POST = 0,
00098         TX_POST,
00099         RX_POST,
00100         MAX_POST,
00101 };
00102 static volatile uint8_t last_post = NO_POST;
00103 
00104 volatile uint8_t fcs_mode = USE_FCS; 
00105 volatile uint8_t prm_mode = PROMISC;
00106 
00107 /* call periodically to */
00108 /* check that maca_entry is changing */
00109 /* if it is not, it will do a manual call to maca_isr which should */
00110 /* get the ball rolling again */
00111 /* also checks that the clock is running --- if it isn't then */
00112 /* it calls redoes the maca intialization but _DOES NOT_ free all packets */ 
00113 
00114 void check_maca(void) {
00115         safe_irq_disable(MACA);
00116         static volatile uint32_t last_time;
00117         static volatile uint32_t last_entry;
00118         volatile uint32_t i;
00119 #if DEBUG_MACA
00120         volatile uint32_t count;
00121 #endif 
00122         
00123 
00124         /* if *MACA_CLK == last_time */
00125         /* try waiting for one clock period */
00126         /* since maybe check_maca is getting called quickly */  
00127         for(i=0; (i < 1024) && (*MACA_CLK == last_time); i++) { continue; }
00128 
00129         if(*MACA_CLK == last_time) {
00130                 PRINTF("check maca: maca_clk stopped, restarting\n");
00131                 /* clock isn't running */
00132                 ResumeMACASync();
00133                 *INTFRC = (1<<INT_NUM_MACA);
00134         } else {
00135                 if((last_time > (*MACA_SFTCLK + RECV_SOFTIMEOUT)) &&
00136                    (last_time > (*MACA_CPLCLK + CPL_TIMEOUT))) {
00137                         PRINTF("check maca: complete clocks expired\n");
00138                         /* all complete clocks have expired */
00139                         /* check that maca entry is changing */
00140                         /* if not, do call the isr to restart the cycle */
00141                         if(last_entry == maca_entry) {
00142                                 PRINTF("check maca: forcing isr\n");
00143                                 *INTFRC = (1<<INT_NUM_MACA);
00144                         }
00145                 }
00146         }
00147                 
00148         last_entry = maca_entry;
00149         last_time = *MACA_CLK;
00150 
00151 #if DEBUG_MACA
00152         if((count = count_packets()) != NUM_PACKETS) {
00153                 PRINTF("check maca: count_packets %d\n", (int)count);
00154                 Print_Packets("check_maca");
00155 #if PACKET_STATS
00156                 for(i=0; i<NUM_PACKETS; i++) {
00157                         printf("packet 0x%lx seen %d post_tx %d get_free %d rxd %d\n", 
00158                                (uint32_t) &packet_pool[i], 
00159                                packet_pool[i].seen, 
00160                                packet_pool[i].post_tx, 
00161                                packet_pool[i].get_free, 
00162                                packet_pool[i].rxd);
00163                 }
00164 #endif
00165                 if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00166         }
00167 #endif /* DEBUG_MACA */
00168         irq_restore();
00169 }
00170 
00171 void maca_init(void) {
00172         reset_maca();
00173         radio_init();
00174         flyback_init();
00175         init_phy();
00176         free_head = 0; tx_head = 0; rx_head = 0; rx_end = 0; tx_end = 0; dma_tx = 0; dma_rx = 0;
00177         free_all_packets();
00178 
00179         #if DEBUG_MACA
00180         Print_Packets("maca_init");
00181         #endif
00182         
00183         /* initial radio command */
00184         /* nop, promiscuous, no cca */
00185         *MACA_CONTROL =
00186                 (prm_mode << PRM) |
00187                 (NO_CCA << MACA_MODE);
00188         
00189         enable_irq(MACA);
00190         *INTFRC = (1 << INT_NUM_MACA);
00191 }
00192 
00193 #define print_packets(x) Print_Packets(x)
00194 void Print_Packets(char *s) {
00195         volatile packet_t *p;
00196 
00197         printf("packet pool after %s:\n\r",s);
00198         p = free_head;  
00199         printf("free_head: 0x%lx ", (uint32_t) free_head);
00200         while(p != 0) {
00201                 p = p->left;
00202                 printf("->0x%lx", (uint32_t) p);
00203         }
00204         printf("\n\r");
00205 
00206         p = tx_head;
00207         printf("tx_head: 0x%lx ", (uint32_t) tx_head);
00208         while(p != 0) {
00209                 p = p->left;
00210                 printf("->0x%lx", (uint32_t) p);
00211         }
00212         printf("\n\r");
00213 
00214         p = rx_head;
00215         printf("rx_head: 0x%lx ", (uint32_t) rx_head);
00216         while(p != 0) {
00217                 p = p->left;
00218                 printf("->0x%lx", (uint32_t) p);
00219         }
00220         printf("\n\r");
00221 
00222         printf("dma_rx: 0x%lx\n", (uint32_t) dma_rx);
00223         printf("dma_tx: 0x%lx\n", (uint32_t) dma_tx);
00224 
00225 }
00226 
00227 inline void bad_packet_bounds(void) {
00228         PRINTF("bad packet bounds! Halting.\n");
00229         while(1) { continue; }
00230 }
00231 
00232 int count_packets(void) {
00233         volatile int8_t total = -1;
00234 
00235 #if PACKET_STATS
00236         volatile packet_t *pk;
00237         volatile uint8_t tx, rx, free;
00238         volatile int i;
00239 
00240         for(i = 0; i < NUM_PACKETS; i++) {
00241                 packet_pool[i].seen = 0;
00242         }
00243 
00244         pk = tx_head; tx = 0;
00245         while( pk != 0 ) {
00246                 if(pk->seen == 0) { tx++; }
00247                 pk->seen++;
00248                 pk = pk->left;
00249         }
00250         pk = rx_head; rx = 0;
00251         while( pk != 0 ) {
00252                 if(pk->seen == 0) { rx++; }
00253                 pk->seen++;
00254                 pk = pk->left;
00255         }
00256         pk = free_head; free = 0;
00257         while( pk != 0 ) {
00258                 if(pk->seen == 0) { free++; }
00259                 pk->seen++;
00260                 pk = pk->left;
00261         }
00262 
00263         total = free + rx + tx;
00264         if(dma_rx && (dma_rx->seen == 0)) { dma_rx->seen++; total++; }
00265         if(dma_tx && (dma_tx->seen == 0)) { dma_tx->seen++; total++; }
00266 #endif /* PACKET_STATS */
00267 
00268         return total;
00269 }       
00270 
00271 void bound_check(volatile packet_t *p) {
00272         volatile int i;
00273 
00274         if((p == 0) ||
00275            (p == &dummy_ack)) { return; }
00276         for(i=0; i < NUM_PACKETS; i++) {
00277                 if(p == &packet_pool[i]) { return; }
00278         }
00279 
00280         bad_packet_bounds();
00281 }
00282 
00283 
00284 /* public packet routines */
00285 /* heads are to the right */
00286 /* ends are to the left */
00287 void free_packet(volatile packet_t *p) {
00288         safe_irq_disable(MACA);
00289 
00290         BOUND_CHECK(p);
00291 
00292         if(!p) {  PRINTF("free_packet passed packet 0\n\r"); return; }
00293         if(p == &dummy_ack) { return; }
00294 
00295         BOUND_CHECK(free_head);
00296 
00297         p->length = 0; p->offset = 0;
00298         p->left = free_head; p->right = 0;
00299 #if PACKET_STATS
00300         p->seen = 0; 
00301         p->post_tx = 0;
00302         p->get_free = 0;
00303         p->rxd = 0;
00304 #endif
00305 
00306         free_head = p;
00307 
00308         BOUND_CHECK(free_head);
00309 
00310         irq_restore();
00311         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00312 
00313         return;
00314 }
00315 
00316 volatile packet_t* get_free_packet(void) {
00317         volatile packet_t *p;
00318 
00319         safe_irq_disable(MACA);
00320         
00321         BOUND_CHECK(free_head);
00322 
00323         p = free_head;
00324         if( p != 0 ) {          
00325                 free_head = p->left;
00326                 free_head->right = 0;
00327         }
00328 
00329         BOUND_CHECK(free_head);
00330 
00331 #if PACKET_STATS
00332         p->get_free++;
00333 #endif
00334 
00335 //      print_packets("get_free_packet");
00336         irq_restore();
00337         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00338 
00339         return p;
00340 }
00341 
00342 void post_receive(void) {
00343         last_post = RX_POST;
00344         /* this sets the rxlen field */
00345         /* this is undocumented but very important */
00346         /* you will not receive anything without setting it */
00347         *MACA_TXLEN = (MAX_PACKET_SIZE << 16);
00348         if(dma_rx == 0) {
00349                 dma_rx = get_free_packet();
00350                 if (dma_rx == 0) {
00351                         PRINTF("trying to fill MACA_DMARX in post_receieve but out of packet buffers\n\r");             
00352                         /* set the sftclock so that we return to the maca_isr */
00353                         *MACA_SFTCLK = *MACA_CLK + RECV_SOFTIMEOUT; /* soft timeout */ 
00354                         *MACA_TMREN = (1 << maca_tmren_sft);
00355                         /* no free buffers, so don't start a reception */
00356                         enable_irq(MACA);
00357                         return;
00358                 }
00359         }
00360         BOUND_CHECK(dma_rx);
00361         BOUND_CHECK(dma_tx);
00362         *MACA_DMARX = (uint32_t)&(dma_rx->data[0]);
00363         /* with timeout */              
00364         *MACA_SFTCLK = *MACA_CLK + RECV_SOFTIMEOUT; /* soft timeout */ 
00365         *MACA_TMREN = (1 << maca_tmren_sft);
00366         /* start the receive sequence */
00367         *MACA_CONTROL = ( (1 << maca_ctrl_asap) | 
00368                           ( 4 << PRECOUNT) |
00369                           ( fcs_mode << NOFC ) |
00370                           ( prm_mode << PRM) |
00371 #if 0 //dak says removing ctrl auto fixes the autoack checksum error --- doesn't cause a performance issue either
00372                           (1 << maca_ctrl_auto) |
00373 #endif
00374                           (maca_ctrl_seq_rx));
00375         /* status bit 10 is set immediately */
00376         /* then 11, 10, and 9 get set */ 
00377         /* they are cleared once we get back to maca_isr */ 
00378 }
00379 
00380 
00381 volatile packet_t* rx_packet(void) {
00382         volatile packet_t *p;
00383         safe_irq_disable(MACA);
00384 
00385         BOUND_CHECK(rx_head);
00386 
00387         p = rx_head;
00388         if( p != 0 ) {
00389                 rx_head = p->left;
00390                 rx_head->right = 0;
00391         }
00392 
00393 #if PACKET_STATS
00394         p->rxd++;
00395 #endif
00396 
00397 //      print_packets("rx_packet");
00398         irq_restore();
00399         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00400 
00401         return p;
00402 }
00403 
00404 void post_tx(void) {
00405         /* set dma tx pointer to the payload */
00406         /* and set the tx len */
00407         disable_irq(MACA);
00408         last_post = TX_POST;
00409         dma_tx = tx_head; 
00410 #if PACKET_STATS
00411         dma_tx->post_tx++;
00412 #endif
00413         *MACA_TXSEQNR = dma_tx->data[2];
00414         *MACA_TXLEN = (uint32_t)((dma_tx->length) + 2) | (3 << 16); /* set rx len to ACK length */
00415         *MACA_DMATX = (uint32_t)&(dma_tx->data[ 0 + dma_tx->offset]);
00416         if(dma_rx == 0) {
00417                 dma_rx = get_free_packet();
00418                 if (dma_rx == 0) { 
00419                         dma_rx = &dummy_ack;
00420                         PRINTF("trying to fill MACA_DMARX on post_tx but out of packet buffers\n\r");
00421                 }
00422                 
00423         }       
00424         BOUND_CHECK(dma_rx);
00425         BOUND_CHECK(dma_tx);
00426         *MACA_DMARX = (uint32_t)&(dma_rx->data[0]);
00427         /* disable soft timeout clock */
00428         /* disable start clock */
00429         *MACA_TMRDIS = (1 << maca_tmren_sft) | ( 1<< maca_tmren_cpl) | ( 1 << maca_tmren_strt ) ;
00430         
00431         /* set complete clock to long value */
00432         /* acts like a watchdog in case the MACA locks up */
00433         *MACA_CPLCLK = *MACA_CLK + CPL_TIMEOUT;
00434         /* enable complete clock */
00435         *MACA_TMREN = (1 << maca_tmren_cpl);
00436         
00437         enable_irq(MACA);
00438         *MACA_CONTROL = ( ( 4 << PRECOUNT) |
00439                           ( prm_mode << PRM) |
00440                           (maca_ctrl_mode_no_cca << maca_ctrl_mode) |
00441                           (1 << maca_ctrl_asap) |
00442                           (maca_ctrl_seq_tx));  
00443         /* status bit 10 is set immediately */
00444         /* then 11, 10, and 9 get set */ 
00445         /* they are cleared once we get back to maca_isr */ 
00446 }
00447 
00448 void tx_packet(volatile packet_t *p) {
00449         safe_irq_disable(MACA);
00450 
00451         BOUND_CHECK(p);
00452 
00453         if(!p) {  PRINTF("tx_packet passed packet 0\n\r"); return; }
00454         if(tx_head == 0) {
00455                 /* start a new queue if empty */
00456                 tx_end = p;
00457                 tx_end->left = 0; tx_end->right = 0;
00458                 tx_head = tx_end; 
00459         } else {
00460                 /* add p to the end of the queue */
00461                 tx_end->left = p;
00462                 p->right = tx_end;
00463                 /* move the queue */
00464                 tx_end = p; tx_end->left = 0;
00465         }
00466 //      print_packets("tx packet");
00467         irq_restore();
00468         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); } 
00469         if(last_post == NO_POST) { *INTFRC = (1<<INT_NUM_MACA); }
00470         /* if we are in a reception cycle, advance the softclock timeout to now */
00471         if(last_post == RX_POST) { *MACA_SFTCLK = *MACA_CLK + CLK_PER_BYTE; }
00472         return;
00473 }
00474 
00475 void free_all_packets(void) {
00476         volatile int i;
00477         safe_irq_disable(MACA);
00478 
00479         free_head = 0;
00480         for(i=0; i<NUM_PACKETS; i++) {
00481                 free_packet((volatile packet_t *)&(packet_pool[i]));            
00482         }
00483         rx_head = 0; rx_end = 0;
00484         tx_head = 0; tx_end = 0;
00485 
00486         irq_restore();
00487         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00488 
00489         return;
00490 }
00491 
00492 /* private routines used by driver */
00493                 
00494 void free_tx_head(void) {
00495         volatile packet_t *p;
00496         safe_irq_disable(MACA);
00497 
00498         BOUND_CHECK(tx_head);
00499 
00500         p = tx_head;
00501         tx_head = tx_head->left;
00502         if(tx_head == 0) { tx_end = 0; }
00503         free_packet(p);
00504         
00505 //      print_packets("free tx head");
00506         irq_restore();
00507         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00508 
00509         return;
00510 }
00511 
00512 void add_to_rx(volatile packet_t *p) {
00513         safe_irq_disable(MACA);
00514 
00515         BOUND_CHECK(p);
00516         
00517         if(!p) {  PRINTF("add_to_rx passed packet 0\n\r"); return; }
00518         p->offset = 1; /* first byte is the length */
00519         if(rx_head == 0) {
00520                 /* start a new queue if empty */
00521                 rx_end = p;
00522                 rx_end->left = 0; rx_end->right = 0;
00523                 rx_head = rx_end; 
00524         } else {
00525                 rx_end->left = p;
00526                 p->right = rx_end;
00527                 rx_end = p; rx_end->left = 0;
00528         }
00529         
00530 //      print_packets("add to rx");
00531         irq_restore();
00532         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
00533 
00534         return;
00535 }
00536 
00537 void decode_status(void) {
00538         volatile uint32_t code;
00539         
00540         code = get_field(*MACA_STATUS,CODE);
00541         /* PRINTF("status code 0x%x\n\r",code); */
00542         
00543         switch(code)
00544         {
00545         case ABORTED:
00546         {
00547                 PRINTF("maca: aborted\n\r");
00548                 ResumeMACASync();
00549                 break;
00550                 
00551         }
00552         case NOT_COMPLETED:
00553         {
00554                 PRINTF("maca: not completed\n\r");
00555                 ResumeMACASync();
00556                 break;
00557                 
00558         }
00559         case CODE_TIMEOUT:
00560         {
00561                 PRINTF("maca: timeout\n\r");
00562                 ResumeMACASync();
00563                 break;
00564                 
00565         }
00566         case NO_ACK:
00567         {
00568                 PRINTF("maca: no ack\n\r");
00569                 ResumeMACASync();
00570                 break;
00571                 
00572         }
00573         case EXT_TIMEOUT:
00574         {
00575                 PRINTF("maca: ext timeout\n\r");
00576                 ResumeMACASync();
00577                 break;
00578                 
00579         }
00580         case EXT_PND_TIMEOUT:
00581         {
00582                 PRINTF("maca: ext pnd timeout\n\r");
00583                 ResumeMACASync();
00584                 break;
00585         }
00586         case SUCCESS:
00587         {
00588                 //PRINTF("maca: success\n\r");
00589                 ResumeMACASync();
00590                 break;                          
00591         }
00592         default:
00593         {
00594                 PRINTF("status: %x", (unsigned int)*MACA_STATUS);
00595                 ResumeMACASync();
00596                 
00597         }
00598         }
00599 }
00600 
00601 void maca_isr(void) {
00602 
00603 //      print_packets("maca_isr");
00604 
00605         maca_entry++;
00606 
00607         if (bit_is_set(*MACA_STATUS, maca_status_ovr))
00608         { PRINTF("maca overrun\n\r"); }
00609         if (bit_is_set(*MACA_STATUS, maca_status_busy))
00610         { PRINTF("maca busy\n\r"); } 
00611         if (bit_is_set(*MACA_STATUS, maca_status_crc))
00612         { PRINTF("maca crc error\n\r"); }
00613         if (bit_is_set(*MACA_STATUS, maca_status_to))
00614         { PRINTF("maca timeout\n\r"); }
00615 
00616         if (data_indication_irq()) {
00617                 *MACA_CLRIRQ = (1 << maca_irq_di);
00618                 dma_rx->length = *MACA_GETRXLVL - 2; /* packet length does not include FCS */
00619                 dma_rx->lqi = get_lqi();
00620                 dma_rx->rx_time = *MACA_TIMESTAMP;
00621 
00622                 /* check if received packet needs an ack */
00623                 if(dma_rx->data[1] & 0x20) {
00624                         /* this wait is necessary to auto-ack */
00625                         volatile uint32_t wait_clk;
00626                         wait_clk = *MACA_CLK + 200;
00627                         while(*MACA_CLK < wait_clk) { continue; }
00628                 }
00629 
00630                 if(maca_rx_callback != 0) { maca_rx_callback(dma_rx); }
00631 
00632                 add_to_rx(dma_rx);
00633                 dma_rx = 0;
00634         }
00635         if (filter_failed_irq()) {
00636                 PRINTF("maca filter failed\n\r");
00637                 ResumeMACASync();
00638                 *MACA_CLRIRQ = (1 << maca_irq_flt);
00639         }
00640         if (checksum_failed_irq()) {
00641                 PRINTF("maca checksum failed\n\r");
00642                 ResumeMACASync();
00643                 *MACA_CLRIRQ = (1 << maca_irq_crc);
00644         }
00645         if (softclock_irq()) {
00646                 *MACA_CLRIRQ = (1 << maca_irq_sftclk);
00647         }
00648         if (poll_irq()) {               
00649                 *MACA_CLRIRQ = (1 << maca_irq_poll);
00650         }
00651         if(action_complete_irq()) {
00652                 /* PRINTF("maca action complete %d\n\r", get_field(*MACA_CONTROL,SEQUENCE)); */
00653                 if(last_post == TX_POST) {
00654                         tx_head->status = get_field(*MACA_STATUS,CODE);
00655                         if(maca_tx_callback != 0) { maca_tx_callback(tx_head); }
00656                         dma_tx = 0;
00657                         free_tx_head();
00658                         last_post = NO_POST;
00659                 }
00660                 ResumeMACASync();
00661                 *MACA_CLRIRQ = (1 << maca_irq_acpl);            
00662         }
00663 
00664         decode_status();
00665 
00666         if (*MACA_IRQ != 0)
00667         { PRINTF("*MACA_IRQ %x\n\r", (unsigned int)*MACA_IRQ); }
00668 
00669         if(tx_head != 0) {
00670                 post_tx();
00671         } else {
00672                 post_receive();
00673         } 
00674 }
00675 
00676 
00677 static uint8_t ram_values[4];
00678 
00679 
00680 void init_phy(void)
00681 {
00682 //  *MACA_TMREN = (1 << maca_tmren_strt) | (1 << maca_tmren_cpl);
00683         *MACA_CLKDIV = MACA_CLOCK_DIV;
00684         *MACA_WARMUP = 0x00180012;
00685         *MACA_EOFDELAY = 0x00000004;
00686         *MACA_CCADELAY = 0x001a0022;
00687         *MACA_TXCCADELAY = 0x00000025;
00688         *MACA_FRAMESYNC0 = 0x000000A7;
00689         *MACA_CLK = 0x00000008;
00690         *MACA_RXACKDELAY = 30;
00691         *MACA_RXEND = 180;
00692         *MACA_TXACKDELAY = 68; 
00693         *MACA_MASKIRQ = ((1 << maca_irq_rst)    | 
00694                          (1 << maca_irq_acpl)   | 
00695                          (1 << maca_irq_cm)     |
00696                          (1 << maca_irq_flt)    | 
00697                          (1 << maca_irq_crc)    | 
00698                          (1 << maca_irq_di)     |
00699                          (1 << maca_irq_sftclk)
00700                 );
00701         *MACA_SLOTOFFSET = 0x00350000;  
00702 }
00703 
00704 void reset_maca(void)
00705 {
00706         volatile uint32_t cnt;
00707         
00708         *MACA_RESET = (1 << maca_reset_rst);
00709         
00710         for(cnt = 0; cnt < 100; cnt++) {};
00711         
00712         *MACA_RESET = (1 << maca_reset_clkon);
00713         
00714         *MACA_CONTROL = maca_ctrl_seq_nop;
00715         
00716         for(cnt = 0; cnt < 400000; cnt++) {};
00717         
00718         /* Clear all interrupts. */
00719         *MACA_CLRIRQ = 0xffff;
00720 }
00721 
00722 
00723 /*
00724         004030c4 <SMAC_InitFlybackSettings>:
00725         4030c4:       4806            ldr     r0, [pc, #24]   (4030e0 <SMAC_InitFlybackSettings+0x1c>) // r0 gets base 0x80009a00
00726                 4030c6:       6881            ldr     r1, [r0, #8]                                             // r1 gets *(0x80009a08)
00727                 4030c8:       4806            ldr     r0, [pc, #24]   (4030e4 <SMAC_InitFlybackSettings+0x20>) // r0 gets 0x0000f7df
00728                 4030ca:       4308            orrs    r0, r1                                                   // or them, r0 has it
00729                 4030cc:       4904            ldr     r1, [pc, #16]   (4030e0 <SMAC_InitFlybackSettings+0x1c>) // r1 gets base 0x80009a00
00730                 4030ce:       6088            str     r0, [r1, #8]     // put r0 into 0x80009a08
00731                 4030d0:       0008            lsls    r0, r1, #0       // r0 gets r1, r0 is the base now
00732                 4030d2:       4905            ldr     r1, [pc, #20]   (4030e8 <SMAC_InitFlybackSettings+0x24>) // r1 gets 0x00ffffff
00733                 4030d4:       60c1            str     r1, [r0, #12]   // put 0x00ffffff into base+12
00734                 4030d6:       0b09            lsrs    r1, r1, #12     // r1 = 0x00ffffff >> 12
00735                 4030d8:       6101            str     r1, [r0, #16]   // put r1 base+16
00736                 4030da:       2110            movs    r1, #16         // r1 gets 16
00737                 4030dc:       6001            str     r1, [r0, #0]    // put r1 in the base
00738                 4030de:       4770            bx      lr              // return
00739                 4030e0:       80009a00        .word   0x80009a00
00740                 4030e4:       0000f7df        .word   0x0000f7df
00741                 4030e8:       00ffffff        .word   0x00ffffff
00742 */
00743 
00744 /* tested and is good */
00745 #define RF_BASE 0x80009a00
00746 void flyback_init(void) {
00747         uint32_t val8, or;
00748         
00749         val8 = *(volatile uint32_t *)(RF_BASE+8);
00750         or = val8 | 0x0000f7df;
00751         *(volatile uint32_t *)(RF_BASE+8) = or;
00752         *(volatile uint32_t *)(RF_BASE+12) = 0x00ffffff;
00753         *(volatile uint32_t *)(RF_BASE+16) = (((uint32_t)0x00ffffff)>>12);
00754         *(volatile uint32_t *)(RF_BASE) = 16;
00755         /* good luck and godspeed */
00756 }
00757 
00758 #define MAX_SEQ1 2
00759 const uint32_t addr_seq1[MAX_SEQ1] = {
00760         0x80003048,      
00761         0x8000304c,
00762 };
00763 
00764 const uint32_t data_seq1[MAX_SEQ1] = {
00765         0x00000f78,     
00766         0x00607707,
00767 };
00768 
00769 
00770 #define MAX_SEQ2 2
00771 const uint32_t addr_seq2[MAX_SEQ2] = {
00772         0x8000a050,      
00773         0x8000a054,      
00774 };
00775 
00776 const uint32_t data_seq2[MAX_SEQ2] = {
00777         0x0000047b,
00778         0x0000007b, 
00779 };
00780 
00781 #define MAX_CAL3_SEQ1 3
00782 const uint32_t addr_cal3_seq1[MAX_CAL3_SEQ1] = { 0x80009400,0x80009a04,0x80009a00, };
00783 const uint32_t data_cal3_seq1[MAX_CAL3_SEQ1] = {0x00020017,0x8185a0a4,0x8c900025, };
00784 
00785 #define MAX_CAL3_SEQ2 2
00786 const uint32_t addr_cal3_seq2[MAX_CAL3_SEQ2] = { 0x80009a00,0x80009a00,};
00787 const uint32_t data_cal3_seq2[MAX_CAL3_SEQ2] = { 0x8c900021,0x8c900027,};
00788 
00789 #define MAX_CAL3_SEQ3 1
00790 const uint32_t addr_cal3_seq3[MAX_CAL3_SEQ3] = { 0x80009a00 };
00791 const uint32_t data_cal3_seq3[MAX_CAL3_SEQ3] = { 0x8c900000 };
00792 
00793 #define MAX_CAL5 4
00794 const uint32_t addr_cal5[MAX_CAL5] = { 
00795         0x80009400,  
00796         0x8000a050,       
00797         0x8000a054,  
00798         0x80003048,
00799 };
00800 const uint32_t data_cal5[MAX_CAL5] = {
00801         0x00000017,
00802         0x00000000,            
00803         0x00000000,
00804         0x00000f00,
00805 };
00806 
00807 #define MAX_DATA 43
00808 const uint32_t addr_reg_rep[MAX_DATA] = { 0x80004118,0x80009204,0x80009208,0x8000920c,0x80009210,0x80009300,0x80009304,0x80009308,0x8000930c,0x80009310,0x80009314,0x80009318,0x80009380,0x80009384,0x80009388,0x8000938c,0x80009390,0x80009394,0x8000a008,0x8000a018,0x8000a01c,0x80009424,0x80009434,0x80009438,0x8000943c,0x80009440,0x80009444,0x80009448,0x8000944c,0x80009450,0x80009460,0x80009464,0x8000947c,0x800094e0,0x800094e4,0x800094e8,0x800094ec,0x800094f0,0x800094f4,0x800094f8,0x80009470,0x8000981c,0x80009828 };
00809 
00810 const uint32_t data_reg_rep[MAX_DATA] = { 0x00180012,0x00000605,0x00000504,0x00001111,0x0fc40000,0x20046000,0x4005580c,0x40075801,0x4005d801,0x5a45d800,0x4a45d800,0x40044000,0x00106000,0x00083806,0x00093807,0x0009b804,0x000db800,0x00093802,0x00000015,0x00000002,0x0000000f,0x0000aaa0,0x01002020,0x016800fe,0x8e578248,0x000000dd,0x00000946,0x0000035a,0x00100010,0x00000515,0x00397feb,0x00180358,0x00000455,0x00000001,0x00020003,0x00040014,0x00240034,0x00440144,0x02440344,0x04440544,0x0ee7fc00,0x00000082,0x0000002a };
00811 
00812 void maca_off(void) {
00813         disable_irq(MACA);
00814         /* turn off the radio regulators */
00815         reg(0x80003048) =  0x00000f00;
00816         /* hold the maca in reset */
00817         maca_reset = maca_reset_rst;  
00818 }
00819 
00820 void maca_on(void) {
00821         /* turn the radio regulators back on */
00822         reg(0x80003048) =  0x00000f78; 
00823         /* reinitialize the phy */
00824         reset_maca();
00825         init_phy();
00826         
00827         enable_irq(MACA);
00828         *INTFRC = (1 << INT_NUM_MACA);
00829 }
00830 
00831 /* initialized with 0x4c */
00832 uint8_t ctov[16] = {
00833         0x0b,
00834         0x0b,
00835         0x0b,
00836         0x0a,
00837         0x0d,
00838         0x0d,
00839         0x0c,
00840         0x0c,
00841         0x0f,
00842         0x0e,
00843         0x0e,
00844         0x0e,
00845         0x11,
00846         0x10,
00847         0x10,
00848         0x0f,
00849 };
00850 
00851 /* get_ctov thanks to Umberto */
00852 
00853 #define _INIT_CTOV_WORD_1       0x00dfbe77
00854 #define _INIT_CTOV_WORD_2       0x023126e9
00855 uint8_t get_ctov( uint32_t r0, uint32_t r1 )
00856 {
00857 
00858         r0 = r0 * _INIT_CTOV_WORD_1;
00859         r0 += ( r1 << 22 );
00860         r0 += _INIT_CTOV_WORD_2;
00861 
00862         r0 = (uint32_t)(((int32_t)r0) >> 25);
00863 
00864         return (uint8_t)r0;
00865 }
00866 
00867 
00868 /* radio_init has been tested to be good */
00869 void radio_init(void) {
00870         volatile uint32_t i;
00871         /* sequence 1 */
00872         for(i=0; i<MAX_SEQ1; i++) {
00873                 *(volatile uint32_t *)(addr_seq1[i]) = data_seq1[i];
00874         }
00875         /* seq 1 delay */
00876         for(i=0; i<0x161a8; i++) { continue; }
00877         /* sequence 2 */
00878         for(i=0; i<MAX_SEQ2; i++) {
00879                 *(volatile uint32_t *)(addr_seq2[i]) = data_seq2[i];
00880         }
00881         /* modem val */
00882         *(volatile uint32_t *)0x80009000 = 0x80050100;
00883         /* cal 3 seq 1*/
00884         for(i=0; i<MAX_CAL3_SEQ1; i++) {
00885                 *(volatile uint32_t *)(addr_cal3_seq1[i]) = data_cal3_seq1[i];
00886         }
00887         /* cal 3 delay */
00888         for(i=0; i<0x11194; i++) { continue; }
00889         /* cal 3 seq 2*/
00890         for(i=0; i<MAX_CAL3_SEQ2; i++) {
00891                 *(volatile uint32_t *)(addr_cal3_seq2[i]) = data_cal3_seq2[i];
00892         }
00893         /* cal 3 delay */
00894         for(i=0; i<0x11194; i++) { continue; }
00895         /* cal 3 seq 3*/
00896         for(i=0; i<MAX_CAL3_SEQ3; i++) {
00897                 *(volatile uint32_t *)(addr_cal3_seq3[i]) = data_cal3_seq3[i];
00898         }
00899         /* cal 5 */
00900         for(i=0; i<MAX_CAL5; i++) {
00901                 *(volatile uint32_t *)(addr_cal5[i]) = data_cal5[i];
00902         }
00903         /*reg replacment */
00904         for(i=0; i<MAX_DATA; i++) {
00905                 *(volatile uint32_t *)(addr_reg_rep[i]) = data_reg_rep[i];
00906         }
00907         
00908         PRINTF("initfromflash\n\r");
00909 
00910         *(volatile uint32_t *)(0x80003048) = 0x00000f04; /* bypass the buck */
00911         for(i=0; i<0x161a8; i++) { continue; } /* wait for the bypass to take */
00912 //      while((((*(volatile uint32_t *)(0x80003018))>>17) & 1) !=1) { continue; } /* wait for the bypass to take */
00913         *(volatile uint32_t *)(0x80003048) = 0x00000fa4; /* start the regulators */
00914         for(i=0; i<0x161a8; i++) { continue; } /* wait for the bypass to take */
00915 
00916         init_from_flash(0x1F000);
00917 
00918         PRINTF("ram_values:\n\r");
00919         for(i=0; i<4; i++) {
00920                 PRINTF("  0x%02x\n\r",ram_values[i]);
00921         }
00922 
00923         PRINTF("radio_init: ctov parameter 0x%02x\n\r",ram_values[3]);
00924         for(i=0; i<16; i++) {
00925                 ctov[i] = get_ctov(i,ram_values[3]);
00926                 PRINTF("radio_init: ctov[%d] = 0x%02x\n\r",(int)i,ctov[i]);
00927         }
00928 
00929 
00930 }
00931 
00932 const uint32_t PSMVAL[19] = {
00933         0x0000080f,
00934         0x0000080f,
00935         0x0000080f,
00936         0x0000080f,
00937         0x0000081f,
00938         0x0000081f,
00939         0x0000081f,
00940         0x0000080f,
00941         0x0000080f,
00942         0x0000080f,
00943         0x0000001f,
00944         0x0000000f,
00945         0x0000000f,
00946         0x00000816,
00947         0x0000001b,
00948         0x0000000b,
00949         0x00000802,
00950         0x00000817,
00951         0x00000003,
00952 };
00953 
00954 const uint32_t PAVAL[19] = {
00955         0x000022c0,
00956         0x000022c0,
00957         0x000022c0,
00958         0x00002280,
00959         0x00002303,
00960         0x000023c0,
00961         0x00002880,
00962         0x000029f0,
00963         0x000029f0,
00964         0x000029f0,
00965         0x000029c0,
00966         0x00002bf0,
00967         0x000029f0,
00968         0x000028a0,
00969         0x00002800,
00970         0x00002ac0,
00971         0x00002880,
00972         0x00002a00,
00973         0x00002b00,
00974 };
00975 
00976 const uint32_t AIMVAL[19] = {
00977         0x000123a0,
00978         0x000163a0,
00979         0x0001a3a0,
00980         0x0001e3a0,
00981         0x000223a0,
00982         0x000263a0,
00983         0x0002a3a0,
00984         0x0002e3a0,
00985         0x000323a0,
00986         0x000363a0,
00987         0x0003a3a0,
00988         0x0003a3a0,
00989         0x0003e3a0,
00990         0x000423a0,
00991         0x000523a0,
00992         0x000423a0,
00993         0x0004e3a0,
00994         0x0004e3a0,
00995         0x0004e3a0,
00996 };
00997 
00998 #define RF_REG 0x80009400
00999 void set_demodulator_type(uint8_t demod) {
01000         uint32_t val = reg(RF_REG);
01001         if(demod == DEMOD_NCD) {
01002                 val = (val & ~1);
01003         } else {
01004                 val = (val | 1);
01005         }
01006         reg(RF_REG) = val;
01007 }
01008 
01009 /* tested and seems to be good */
01010 #define ADDR_POW1 0x8000a014
01011 #define ADDR_POW2 ADDR_POW1 + 12
01012 #define ADDR_POW3 ADDR_POW1 + 64
01013 void set_power(uint8_t power) {
01014         safe_irq_disable(MACA);
01015 
01016         reg(ADDR_POW1) = PSMVAL[power];
01017 
01018 /* see http://devl.org/pipermail/mc1322x/2009-October/000065.html */
01019 /*      reg(ADDR_POW2) = (ADDR_POW1>>18) | PAVAL[power]; */
01020 #ifdef USE_PA
01021         reg(ADDR_POW2) = 0xffffdfff & PAVAL[power]; /* single port */
01022 #else
01023         reg(ADDR_POW2) = 0x00002000 | PAVAL[power]; /* dual port */
01024 #endif
01025 
01026         reg(ADDR_POW3) = AIMVAL[power];
01027         
01028         irq_restore();
01029         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
01030 
01031 }
01032 
01033 const uint8_t VCODivI[16] = {
01034         0x2f,
01035         0x2f,
01036         0x2f,
01037         0x2f,
01038         0x2f,
01039         0x2f,
01040         0x2f,
01041         0x2f,
01042         0x30,
01043         0x30,
01044         0x30,
01045         0x2f,
01046         0x30,
01047         0x30,
01048         0x30,
01049         0x30,
01050 };
01051 
01052 const uint32_t VCODivF[16] = {
01053         0x00355555,
01054         0x006aaaaa,
01055         0x00a00000,
01056         0x00d55555,
01057         0x010aaaaa,
01058         0x01400000,
01059         0x01755555,
01060         0x01aaaaaa,
01061         0x01e00000,
01062         0x00155555,
01063         0x004aaaaa,
01064         0x00800000,
01065         0x00b55555,
01066         0x00eaaaaa,
01067         0x01200000,
01068         0x01555555,             
01069 };
01070 
01071 /* tested good */
01072 #define ADDR_CHAN1 0x80009800
01073 #define ADDR_CHAN2 (ADDR_CHAN1+12)
01074 #define ADDR_CHAN3 (ADDR_CHAN1+16)
01075 #define ADDR_CHAN4 (ADDR_CHAN1+48)
01076 void set_channel(uint8_t chan) {
01077         volatile uint32_t tmp;
01078         safe_irq_disable(MACA);
01079 
01080         tmp = reg(ADDR_CHAN1);
01081         tmp = tmp & 0xbfffffff;
01082         reg(ADDR_CHAN1) = tmp;
01083 
01084         reg(ADDR_CHAN2) = VCODivI[chan];
01085         reg(ADDR_CHAN3) = VCODivF[chan];
01086 
01087         tmp = reg(ADDR_CHAN4);
01088         tmp = tmp | 2;
01089         reg(ADDR_CHAN4) = tmp;
01090 
01091         tmp = reg(ADDR_CHAN4);
01092         tmp = tmp | 4;
01093         reg(ADDR_CHAN4) = tmp;
01094 
01095         tmp = tmp & 0xffffe0ff;
01096         tmp = tmp | (((ctov[chan])<<8)&0x1F00);
01097         reg(ADDR_CHAN4) = tmp;
01098         /* duh! */
01099         irq_restore();
01100         if(bit_is_set(*NIPEND, INT_NUM_MACA)) { *INTFRC = (1 << INT_NUM_MACA); }
01101 }
01102 
01103 uint8_t (*get_lqi)(void) = (void *) 0x0000e04d;
01104 
01105 #define ROM_END 0x0013ffff
01106 #define ENTRY_EOF 0x00000e0f
01107 /* processes up to 4 words of initialization entries */
01108 /* returns the number of words processed */
01109 uint32_t exec_init_entry(volatile uint32_t *entries, uint8_t *valbuf) 
01110 {
01111         volatile uint32_t i;
01112         if(entries[0] <= ROM_END) {
01113                 if (entries[0] == 0) {
01114                         /* do delay command*/
01115                         PRINTF("init_entry: delay 0x%08x\n\r", (unsigned int)entries[1]);
01116                         for(i=0; i<entries[1]; i++) { continue; }
01117                         return 2;
01118                 } else if (entries[0] == 1) {
01119                         /* do bit set/clear command*/
01120                         PRINTF("init_entry: bit set clear 0x%08x 0x%08x 0x%08x\n\r", (unsigned int)entries[1], (unsigned int)entries[2], (unsigned int)entries[3]);
01121                         reg(entries[2]) = (reg(entries[2]) & ~entries[1]) | (entries[3] & entries[1]);
01122                         return 4;
01123                 } else if ((entries[0] >= 16) &&
01124                            (entries[0] < 0xfff1)) {
01125                         /* store bytes in valbuf */
01126                         PRINTF("init_entry: store in valbuf 0x%02x position %d\n\r", 
01127                                (unsigned int)entries[1],
01128                                (unsigned int)(entries[0]>>4)-1);
01129                         valbuf[(entries[0]>>4)-1] = entries[1];
01130                         return 2;
01131                 } else if (entries[0] == ENTRY_EOF) {
01132                         PRINTF("init_entry: eof ");
01133                         return 0;
01134                 } else {
01135                         /* invalid command code */
01136                         PRINTF("init_entry: invaild code 0x%08x\n\r",(unsigned int)entries[0]);
01137                         return 0;
01138                 }
01139         } else { /* address isn't in ROM space */   
01140                  /* do store value in address command  */
01141                 PRINTF("init_entry: address value pair - *0x%08x = 0x%08x\n\r",
01142                        (unsigned int)entries[0],
01143                        (unsigned int)entries[1]);
01144                 reg(entries[0]) = entries[1];
01145                 return 2;
01146         }
01147 }
01148 
01149 
01150 #define FLASH_INIT_MAGIC 0x00000abc
01151 uint32_t init_from_flash(uint32_t addr) {
01152         nvmType_t type=0;
01153         nvmErr_t err;   
01154         volatile uint32_t buf[8];
01155         volatile uint32_t len;
01156         volatile uint32_t i=0,j;
01157 
01158         err = nvm_detect(gNvmInternalInterface_c, &type);
01159         PRINTF("nvm_detect returned type 0x%08x err 0x%02x\n\r", type, err);
01160                 
01161         nvm_setsvar(0);
01162         err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, addr, 8);
01163         i+=8;
01164         PRINTF("nvm_read returned: 0x%02x\n\r",err);
01165         
01166         for(j=0; j<4; j++) {
01167                 PRINTF("0x%08x\n\r",(unsigned int)buf[j]);
01168         }
01169 
01170         if(buf[0] == FLASH_INIT_MAGIC) {
01171                 len = buf[1] & 0x0000ffff;
01172                 while(i < (len-4)) {
01173                         err = nvm_read(gNvmInternalInterface_c, type, (uint8_t *)buf, addr+i, 32);
01174                         i += 4*exec_init_entry(buf, ram_values);
01175                 }
01176                 return i;
01177         } else {
01178                 return 0;
01179         }
01180         
01181 }
01182 
01183 /* 
01184  * Do the ABORT-Wait-NOP-Wait sequence in order to prevent MACA malfunctioning.
01185  * This seqeunce is synchronous and no interrupts should be triggered when it is done.
01186  */
01187 void ResumeMACASync(void)
01188 { 
01189   volatile uint32_t clk, TsmRxSteps, LastWarmupStep, LastWarmupData, LastWarmdownStep, LastWarmdownData;
01190 //  bool_t tmpIsrStatus;
01191   volatile uint32_t i;
01192   safe_irq_disable(MACA);
01193 
01194 //  ITC_DisableInterrupt(gMacaInt_c);  
01195 //  AppInterrupts_ProtectFromMACAIrq(tmpIsrStatus); <- Original from MAC code, but not sure how is it implemented
01196 
01197   /* Manual TSM modem shutdown */
01198 
01199   /* read TSM_RX_STEPS */
01200   TsmRxSteps = (*((volatile uint32_t *)(0x80009204)));
01201  
01202   /* isolate the RX_WU_STEPS */
01203   /* shift left to align with 32-bit addressing */
01204   LastWarmupStep = (TsmRxSteps & 0x1f) << 2;
01205   /* Read "current" TSM step and save this value for later */
01206   LastWarmupData = (*((volatile uint32_t *)(0x80009300 + LastWarmupStep)));
01207 
01208   /* isolate the RX_WD_STEPS */
01209   /* right-shift bits down to bit 0 position */
01210   /* left-shift to align with 32-bit addressing */
01211   LastWarmdownStep = ((TsmRxSteps & 0x1f00) >> 8) << 2;
01212   /* write "last warmdown data" to current TSM step to shutdown rx */
01213   LastWarmdownData = (*((volatile uint32_t *)(0x80009300 + LastWarmdownStep)));
01214   (*((volatile uint32_t *)(0x80009300 + LastWarmupStep))) = LastWarmdownData;
01215 
01216   /* Abort */
01217   MACA_WRITE(maca_control, 1);
01218   
01219   /* Wait ~8us */
01220   for (clk = maca_clk, i = 0; maca_clk - clk < 3 && i < 300; i++)
01221     ;
01222  
01223   /* NOP */
01224   MACA_WRITE(maca_control, 0);  
01225   
01226   /* Wait ~8us */  
01227   for (clk = maca_clk, i = 0; maca_clk - clk < 3 && i < 300; i++)
01228     ;
01229    
01230 
01231   /* restore original "last warmup step" data to TSM (VERY IMPORTANT!!!) */
01232   (*((volatile uint32_t *)(0x80009300 + LastWarmupStep))) = LastWarmupData;
01233 
01234   
01235   
01236   /* Clear all MACA interrupts - we should have gotten the ABORT IRQ */
01237   MACA_WRITE(maca_clrirq, 0xFFFF);
01238 
01239 //  AppInterrupts_UnprotectFromMACAIrq(tmpIsrStatus);  <- Original from MAC code, but not sure how is it implemented
01240 //  ITC_EnableInterrupt(gMacaInt_c);
01241 //  enable_irq(MACA);
01242   irq_restore();
01243 
01244 }

Generated on Mon Apr 11 14:23:38 2011 for Contiki 2.5 by  doxygen 1.6.1