Skip to content

Commit fa4bfbd

Browse files
committed
AVR PROGMEM support.
1 parent 2b29ab0 commit fa4bfbd

File tree

3 files changed

+305
-37
lines changed

3 files changed

+305
-37
lines changed

src/Commander-API.cpp

Lines changed: 256 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,20 @@ void Commander::attachTreeFunction( API_t *API_tree_p, uint32_t API_tree_size_p
4242
API_tree = API_tree_p;
4343
API_tree_size = API_tree_size_p;
4444

45+
#if defined( ARDUINO ) && defined( __AVR__ )
46+
47+
dbgResponse -> print( F( "API tree attached with " ) );
48+
dbgResponse -> print( API_tree_size );
49+
dbgResponse -> println( F( " commands." ) );
50+
51+
#else
52+
4553
dbgResponse -> print( (const char*)"API tree attached with " );
4654
dbgResponse -> print( API_tree_size );
4755
dbgResponse -> println( " commands." );
4856

57+
#endif
58+
4959
}
5060

5161
void Commander::init(){
@@ -57,15 +67,44 @@ void Commander::init(){
5767
// Temporary variable, used to flip elements.
5868
API_t temp;
5969

70+
#ifdef __AVR__
71+
72+
if( API_tree[ 0 ].name == NULL ){
73+
74+
memoryType = MEMORY_PROGMEM;
75+
commander_strcmp = &Commander::commander_strcmp_progmem;
76+
commander_strcmp_tree_ram = &Commander::commander_strcmp_tree_ram_progmem;
77+
78+
}
79+
80+
#endif
81+
82+
#if defined( ARDUINO ) && defined( __AVR__ )
83+
84+
dbgResponse -> println( F( "Commander init start" ) );
85+
86+
#else
87+
6088
dbgResponse -> println( (const char*)"Commander init start" );
6189

90+
#endif
91+
6292
// Make the tree ordered by alphabet.
63-
dbgResponse -> print( (const char*)"\tCreating alphabetical order... " );
93+
#if defined( ARDUINO ) && defined( __AVR__ )
94+
95+
dbgResponse -> print( F( "\tCreating alphabetical order... " ) );
96+
97+
#else
98+
99+
dbgResponse -> print( (const char*)"\tCreating alphabetical order... " );
100+
101+
#endif
102+
64103
for( i = 0; i < API_tree_size; i++ ){
65104

66105
for( j = i + 1; j < API_tree_size; j++ ){
67106

68-
if( strcmp( API_tree[ i ].name, API_tree[ j ].name ) > 0 ){
107+
if( ( this ->* commander_strcmp )( &API_tree[ i ], &API_tree[ j ] ) > 0 ){
69108

70109
temp = API_tree[ i ];
71110
API_tree[ i ] = API_tree[ j ];
@@ -84,17 +123,44 @@ void Commander::init(){
84123
API_tree[ i ].place = i;
85124

86125
}
126+
127+
#if defined( ARDUINO ) && defined( __AVR__ )
128+
129+
dbgResponse -> println( F( "[ OK ]" ) );
130+
131+
#else
132+
87133
dbgResponse -> println( (const char*)"[ OK ]" );
88134

135+
#endif
136+
137+
89138
// Optimize the tree to make it balanced.
90139
// It is necessary to speed up the command
91140
// search phase.
141+
#if defined( ARDUINO ) && defined( __AVR__ )
142+
143+
dbgResponse -> print( F( "\tCreate balanced binary structure... " ) );
144+
145+
#else
146+
92147
dbgResponse -> print( (const char*)"\tCreate balanced binary structure... " );
148+
149+
#endif
93150
optimize_api_tree();
94-
dbgResponse -> println( (const char*)"[ OK ]" );
95151

152+
#if defined( ARDUINO ) && defined( __AVR__ )
153+
154+
dbgResponse -> println( F( "[ OK ]" ) );
155+
dbgResponse -> println( F( "Commander init finished!" ) );
156+
157+
#else
158+
159+
dbgResponse -> println( (const char*)"[ OK ]" );
96160
dbgResponse -> println( (const char*)"Commander init finished!" );
97161

162+
#endif
163+
98164
}
99165

100166
uint16_t Commander::find_api_index_by_place( uint16_t place ){
@@ -170,14 +236,15 @@ void Commander::optimize_api_tree(){
170236
for( i = 1; i < API_tree_size; i++ ){
171237

172238
prev = &API_tree[ 0 ];
173-
comp_res = strcmp( prev -> name, API_tree[ i ].name );
239+
240+
comp_res = ( this ->* commander_strcmp )( prev, &API_tree[ i ] );
174241

175242
(comp_res > 0) ? (next = (prev->left)) : ( next = (prev->right));
176243

177244
while( next != NULL ){
178245

179246
prev = next;
180-
comp_res = strcmp( prev -> name, API_tree[ i ].name );
247+
comp_res = ( this ->* commander_strcmp )( prev, &API_tree[ i ] );
181248
(comp_res > 0) ? (next = (prev->left)) : ( next = (prev->right));
182249

183250
}
@@ -295,10 +362,29 @@ void Commander::executeCommand( char *cmd ){
295362
// If show_description flag is set, than we have to print the description.
296363
if( show_description ){
297364

298-
// Print the description text to the output channel.
299-
response -> print( commandData_ptr -> name );
300-
response -> print( ": " );
301-
response -> println( commandData_ptr -> desc );
365+
if( memoryType == MEMORY_REGULAR ){
366+
367+
// Print the description text to the output channel.
368+
response -> print( commandData_ptr -> name );
369+
response -> print( ':' );
370+
response -> print( ' ' );
371+
response -> println( commandData_ptr -> desc );
372+
373+
}
374+
375+
#ifdef __AVR__
376+
377+
else if( memoryType == MEMORY_PROGMEM ){
378+
379+
// Print the description text to the output channel.
380+
response -> print( commandData_ptr -> name_P );
381+
response -> print( ':' );
382+
response -> print( ' ' );
383+
response -> println( commandData_ptr -> desc_P );
384+
385+
}
386+
387+
#endif
302388

303389

304390
}
@@ -344,9 +430,19 @@ void Commander::executeCommand( char *cmd ){
344430

345431
// If we went through the whole tree and we did not found the command in it,
346432
// we have to notice the user abut the problem. Maybe a Type-O
433+
#if defined( ARDUINO ) && defined( __AVR__ )
434+
435+
response -> print( F( "Command \'" ) );
436+
response -> print( tempBuff );
437+
response -> println( F( "\' not found!" ) );
438+
439+
#else
440+
347441
response -> print( (const char*)"Command \'" );
348442
response -> print( tempBuff );
349-
response -> println( "\' not found!" );
443+
response -> println( (const char*)"\' not found!" );
444+
445+
#endif
350446

351447
}
352448

@@ -437,7 +533,7 @@ Commander::API_t* Commander::operator [] ( char* name ){
437533

438534
prev = &API_tree[ 0 ];
439535

440-
comp_res = strcmp( prev -> name, name );
536+
comp_res = ( this ->* commander_strcmp_tree_ram )( prev, name );
441537

442538
(comp_res > 0) ? (next = (prev->left)) : ( next = (prev->right));
443539

@@ -446,7 +542,7 @@ Commander::API_t* Commander::operator [] ( char* name ){
446542
while( ( comp_res !=0 ) && ( next != NULL ) ){
447543

448544
prev = next;
449-
comp_res = strcmp( prev -> name, name );
545+
comp_res = ( this ->* commander_strcmp_tree_ram )( prev, name );
450546
(comp_res > 0) ? (next = (prev->left)) : ( next = (prev->right));
451547

452548
}
@@ -472,30 +568,135 @@ Commander::API_t* Commander::operator [] ( const char* name ){
472568

473569
void Commander::helpFunction( bool description ){
474570

571+
helpFunction( description, response );
572+
573+
}
574+
575+
void Commander::helpFunction( bool description, Stream* out, bool style ){
576+
475577
uint32_t i;
476578
uint32_t j;
477579

478-
response -> println( (const char*)"---- Available commands ----" );
580+
if( style ){
581+
582+
#if defined( ARDUINO ) && defined( __AVR__ )
583+
584+
out -> println( F( "\033[1;31m----\033[1;32m Available commands \033[1;31m----\033[0;37m\r\n" ) );
585+
586+
#else
587+
588+
out -> println( (const char*)"\033[1;31m----\033[1;32m Available commands \033[1;31m----\033[0;37m\r\n" );
589+
590+
#endif
591+
592+
}
593+
594+
else{
595+
596+
#if defined( ARDUINO ) && defined( __AVR__ )
597+
598+
out -> println( F( "---- Available commands ----\r\n" ) );
599+
600+
#else
601+
602+
out -> println( (const char*)"---- Available commands ----\r\n" );
603+
604+
#endif
605+
606+
}
607+
479608
for( i = 0; i < API_tree_size; i++ ){
480609

481610
for( j = 0; j < API_tree_size; j++ ){
482611

483612
if( API_tree[ j ].place == i ){
484613

614+
// Check if the description is required to print.
485615
if( description ){
486616

487-
response -> print( API_tree[ j ].name );
488-
response -> println( ':' );
489-
response -> print( '\t' );
490-
response -> print( API_tree[ j ].desc );
491-
response -> println();
492-
response -> println();
617+
// Check if style is enabled.
618+
if( style ){
619+
620+
if( memoryType == MEMORY_REGULAR ){
621+
622+
out -> print( (const char*)"\033[1;32m" );
623+
out -> print( API_tree[ j ].name );
624+
out -> print( (const char*)"\033[0;37m" );
625+
out -> print( ':' );
626+
out -> print( ' ' );
627+
out -> print( API_tree[ j ].desc );
628+
out -> println();
629+
630+
}
631+
632+
#ifdef __AVR__
633+
634+
else if( memoryType == MEMORY_PROGMEM ){
635+
636+
out -> print( F( "\033[1;32m" ) );
637+
out -> print( API_tree[ j ].name_P );
638+
out -> print( F( "\033[0;37m" ) );
639+
out -> print( ':' );
640+
out -> print( ' ' );
641+
out -> print( API_tree[ j ].desc_P );
642+
out -> println();
643+
out -> println();
644+
645+
}
646+
647+
#endif
648+
649+
}
650+
651+
else{
652+
653+
if( memoryType == MEMORY_REGULAR ){
654+
655+
out -> print( API_tree[ j ].name );
656+
out -> println( ':' );
657+
out -> print( '\t' );
658+
out -> print( API_tree[ j ].desc );
659+
out -> println();
660+
out -> println();
661+
662+
}
663+
664+
#ifdef __AVR__
665+
666+
else if( memoryType == MEMORY_PROGMEM ){
667+
668+
out -> print( API_tree[ j ].name_P );
669+
out -> println( ':' );
670+
out -> print( '\t' );
671+
out -> print( API_tree[ j ].desc_P );
672+
out -> println();
673+
out -> println();
674+
675+
}
676+
677+
#endif
678+
679+
}
493680

494681
}
495682

496683
else{
497684

498-
response -> println( API_tree[ j ].name );
685+
if( memoryType == MEMORY_REGULAR ){
686+
687+
out -> println( API_tree[ j ].name );
688+
689+
}
690+
691+
#ifdef __AVR__
692+
693+
else if( memoryType == MEMORY_PROGMEM ){
694+
695+
out -> println( API_tree[ j ].name_P );
696+
697+
}
698+
699+
#endif
499700

500701
}
501702

@@ -528,3 +729,38 @@ int32_t Commander::hasChar( char* str, char c ){
528729
return -1;
529730

530731
}
732+
733+
void Commander::printHelp( Stream* out ){
734+
735+
helpFunction( true, out, true );
736+
737+
}
738+
739+
int Commander::commander_strcmp_regular( API_t* element1, API_t* element2 ){
740+
741+
return strcmp( element1 -> name, element2 -> name );
742+
743+
}
744+
745+
int Commander::commander_strcmp_tree_ram_regular( API_t* element1, char* element2 ){
746+
747+
return strcmp( element1 -> name, element2 );
748+
749+
}
750+
751+
#ifdef __AVR__
752+
753+
int Commander::commander_strcmp_progmem( API_t* element1, API_t* element2 ){
754+
755+
strncpy_P( progmemBuffer, ( PGM_P ) element1 -> name_P, COMMANDER_MAX_COMMAND_SIZE );
756+
return strcmp_P( progmemBuffer, ( PGM_P )element2 -> name_P );
757+
758+
}
759+
760+
int Commander::commander_strcmp_tree_ram_progmem( API_t* element1, char* element2 ){
761+
762+
return strcmp_P( element2, (PGM_P)element1 -> name_P ) * -1;
763+
764+
}
765+
766+
#endif

0 commit comments

Comments
 (0)