removed uneeded files.
This commit is contained in:
parent
1f17f8dcdf
commit
32a3dcad12
25 changed files with 6911 additions and 20039 deletions
|
|
@ -1,7 +0,0 @@
|
||||||
add_library(attic STATIC
|
|
||||||
temp_transition_helper.c
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(attic PUBLIC
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}
|
|
||||||
)
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,226 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
const char * yes[] = { "SENTINEL_WILL_BE_REPLACED_BY_CMDLINE" }; // "CH32X03x", etc. element 0 is filled in by command-line
|
|
||||||
const char * no[] = { "CH32V10x", "CH32V30x", "CH32V20x", "CH32X03x", "CH32V003" };
|
|
||||||
|
|
||||||
char * WhitePull( const char ** sti )
|
|
||||||
{
|
|
||||||
const char * st = *sti;
|
|
||||||
int len = 0;
|
|
||||||
while( ( *st == ' ' || *st == '\t' || *st == '(' ) && *st ) { st++; }
|
|
||||||
const char * sts = st;
|
|
||||||
while( *st != ' ' && *st != '\t' && *st != '\n' && *st != ')' && *st != '(' && *st != 0 ) { st++; len++; }
|
|
||||||
if( *st == ')' ) { st++; }
|
|
||||||
char * ret = malloc( len + 1 );
|
|
||||||
memcpy( ret, sts, len );
|
|
||||||
ret[len] = 0;
|
|
||||||
*sti = st;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NYI( const char * s )
|
|
||||||
{
|
|
||||||
int ret = 2;
|
|
||||||
char * wp = WhitePull( &s );
|
|
||||||
int i;
|
|
||||||
for( i = 0; i < sizeof(yes)/sizeof(yes[0]); i++ )
|
|
||||||
if( strcmp( yes[i], wp ) == 0 ) ret = 1;
|
|
||||||
if( ret != 1 )
|
|
||||||
for( i = 0; i < sizeof(no)/sizeof(no[0]); i++ )
|
|
||||||
if( strcmp( no[i], wp ) == 0 ) ret = 0;
|
|
||||||
free( wp );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int EvalSpec( const char * spl )
|
|
||||||
{
|
|
||||||
int rsofar = 0;
|
|
||||||
int i;
|
|
||||||
int lastv = 0;
|
|
||||||
int lasto = -1;
|
|
||||||
int ret = 0;
|
|
||||||
cont:
|
|
||||||
char * wp = WhitePull( &spl );
|
|
||||||
int def = -1;
|
|
||||||
if( strcmp( wp, "defined" ) == 0 ) def = 1;
|
|
||||||
if( strcmp( wp, "!defined" ) == 0 ) def = 2;
|
|
||||||
if( def < 0 ) return 2;
|
|
||||||
char * wpn = WhitePull( &spl );
|
|
||||||
i = NYI( wpn );
|
|
||||||
//printf( "SPIN: %s/%s/%d/%d/%d\n", wp, wpn, i, def, lasto );
|
|
||||||
if( i == 2 ) return 2;
|
|
||||||
|
|
||||||
if( def == 2 ) i = !i;
|
|
||||||
|
|
||||||
if( lasto == 1 )
|
|
||||||
{
|
|
||||||
ret = lastv || i;
|
|
||||||
}
|
|
||||||
else if( lasto == 2 )
|
|
||||||
ret = lastv && i;
|
|
||||||
else
|
|
||||||
ret = i;
|
|
||||||
|
|
||||||
char * wpa = WhitePull( &spl );
|
|
||||||
//printf( "WPA: \"%s\"\n", wpa );
|
|
||||||
lastv = ret;
|
|
||||||
lasto = -1;
|
|
||||||
//printf( "RET: %d\n", ret );
|
|
||||||
if( strcmp( wpa, "||" ) == 0 ) { lasto = 1; goto cont; }
|
|
||||||
else if( strcmp( wpa, "&&" ) == 0 ) { lasto = 2; goto cont; }
|
|
||||||
else return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0 for no
|
|
||||||
// 1 for yes
|
|
||||||
// 2 for indeterminate
|
|
||||||
int NoYesInd( const char * preprocc )
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
int ofs = 0;
|
|
||||||
if( strncmp( preprocc, "#if ", 4 ) == 0 ) ofs = 4;
|
|
||||||
if( strncmp( preprocc, "#elif ", 6 ) == 0 ) ofs = 6;
|
|
||||||
if( ofs )
|
|
||||||
{
|
|
||||||
ret = EvalSpec( preprocc + ofs );
|
|
||||||
//printf( "SPEC: %d\n", ret );
|
|
||||||
}
|
|
||||||
else if( strncmp( preprocc, "#ifdef ", 7 ) == 0 )
|
|
||||||
{
|
|
||||||
const char * ep = preprocc + 6;
|
|
||||||
char * wp = WhitePull( &ep );
|
|
||||||
ret = NYI( wp );
|
|
||||||
free( wp );
|
|
||||||
}
|
|
||||||
else if( strncmp( preprocc, "#ifndef ", 8 ) == 0 )
|
|
||||||
{
|
|
||||||
const char * ep = preprocc + 6;
|
|
||||||
char * wp = WhitePull( &ep );
|
|
||||||
ret = NYI( wp );
|
|
||||||
if( ret < 2 ) ret = !ret;
|
|
||||||
free( wp );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ret = 2;
|
|
||||||
//printf( "%d-> %s\n", ret, preprocc );
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char * sslineis( const char * line, const char * match )
|
|
||||||
{
|
|
||||||
while( *line == ' ' || *line == '\t' ) line++;
|
|
||||||
const char * linestart = line;
|
|
||||||
while( *line && *match == *line ) { line++; match++; }
|
|
||||||
if( *match == 0 )
|
|
||||||
return linestart;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main( int argc, char ** argv )
|
|
||||||
{
|
|
||||||
if( argc != 3 )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Syntax: transition [#define to trigger on] [file to convert]\nNo'd architectures:\n" );
|
|
||||||
int i;
|
|
||||||
for( i = 0; i < sizeof(no)/sizeof(no[0]); i++ )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "\t%s\n", no[i] );
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
yes[0] = argv[1];
|
|
||||||
|
|
||||||
FILE * f = fopen( argv[2], "r" );
|
|
||||||
if( !f )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "Error: Could not open \"%s\"\n", argv[2] );
|
|
||||||
return -2;
|
|
||||||
}
|
|
||||||
char line[1024];
|
|
||||||
char * l;
|
|
||||||
|
|
||||||
|
|
||||||
int depth = 0;
|
|
||||||
|
|
||||||
// 0 = no
|
|
||||||
// 1 = yes
|
|
||||||
// 2 = indeterminate
|
|
||||||
// 3 = super no. (I.e. after a true #if clause)
|
|
||||||
int yesnoind[1024];
|
|
||||||
yesnoind[0] = 1;
|
|
||||||
|
|
||||||
while( l = fgets( line, sizeof(line)-1, f ) )
|
|
||||||
{
|
|
||||||
const char * ss = 0;
|
|
||||||
int nyi = yesnoind[depth];
|
|
||||||
int waspre = 0;
|
|
||||||
|
|
||||||
if( (ss = sslineis( line, "#if " ) ) || (ss = sslineis( line, "#ifdef " ) ) || (ss = sslineis( line, "#ifndef " ) ) )
|
|
||||||
{
|
|
||||||
waspre = 1;
|
|
||||||
//printf( "CHECK: %d/%s\n", depth, l );
|
|
||||||
nyi = NoYesInd( ss );
|
|
||||||
depth++;
|
|
||||||
yesnoind[depth] = nyi;
|
|
||||||
}
|
|
||||||
else if( (ss = sslineis( line, "#elif " ) ) )
|
|
||||||
{
|
|
||||||
if( nyi != 2 )
|
|
||||||
{
|
|
||||||
waspre = 1;
|
|
||||||
if( nyi == 1 )
|
|
||||||
{
|
|
||||||
nyi = 3;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
nyi = NoYesInd( ss );
|
|
||||||
}
|
|
||||||
//printf( "ELIF check: %s %d\n", ss, nyi );
|
|
||||||
yesnoind[depth] = nyi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( (ss = sslineis( line, "#else" ) ) )
|
|
||||||
{
|
|
||||||
if( nyi != 2 )
|
|
||||||
{
|
|
||||||
waspre = 1;
|
|
||||||
if( yesnoind[depth] == 1 )
|
|
||||||
nyi = 3;
|
|
||||||
else
|
|
||||||
nyi = !yesnoind[depth];
|
|
||||||
yesnoind[depth] = nyi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if( (ss = sslineis( line, "#endif" ) ) )
|
|
||||||
{
|
|
||||||
waspre = 1;
|
|
||||||
depth--;
|
|
||||||
if( depth < 0 )
|
|
||||||
{
|
|
||||||
fprintf( stderr, "UNTERMD IF\n" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int thisv = nyi;
|
|
||||||
int i;
|
|
||||||
for( i = 0; i <= depth; i++ )
|
|
||||||
{
|
|
||||||
//printf( "%d", yesnoind[i] );
|
|
||||||
if( yesnoind[i] == 0 || yesnoind[i] == 3 ) thisv = 0;
|
|
||||||
}
|
|
||||||
//printf( ">>%s", l );
|
|
||||||
|
|
||||||
if( thisv != 0 && thisv != 3 && ( thisv != 1 || !waspre ) )
|
|
||||||
{
|
|
||||||
printf( "%s", l );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
5
src/extralibs/.clang-format
Normal file
5
src/extralibs/.clang-format
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"DisableFormat": true,
|
||||||
|
"SortIncludes": "Never"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,16 +1,14 @@
|
||||||
// 2023-06-26 recallmenot
|
// 2023-06-26 recallmenot
|
||||||
|
|
||||||
//######## necessities
|
// ######## necessities
|
||||||
|
|
||||||
// include guards
|
// include guards
|
||||||
#ifndef CH32V003_GPIO_BR_H
|
#ifndef CH32V003_GPIO_BR_H
|
||||||
#define CH32V003_GPIO_BR_H
|
#define CH32V003_GPIO_BR_H
|
||||||
|
|
||||||
// includes
|
// includes
|
||||||
#include <stdint.h> //uintN_t support
|
|
||||||
#include "../ch32fun/ch32fun.h"
|
#include "../ch32fun/ch32fun.h"
|
||||||
|
#include <stdint.h> //uintN_t support
|
||||||
|
|
||||||
|
|
||||||
/*######## library description
|
/*######## library description
|
||||||
This is a speedy and light GPIO library due to
|
This is a speedy and light GPIO library due to
|
||||||
|
|
@ -19,8 +17,6 @@ This is a speedy and light GPIO library due to
|
||||||
branchless where it counts
|
branchless where it counts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*######## library usage and configuration
|
/*######## library usage and configuration
|
||||||
|
|
||||||
first, enable the desired port.
|
first, enable the desired port.
|
||||||
|
|
@ -98,19 +94,19 @@ Writing `TIMx->SWEVGR |= TIM_UG` will immediately update the shadow register and
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ######## ports, pins and states: use these for the functions below!
|
||||||
|
|
||||||
|
#define GPIOv_from_PORT_PIN(GPIO_port_n, pin)
|
||||||
|
|
||||||
//######## ports, pins and states: use these for the functions below!
|
enum GPIO_port_n
|
||||||
|
{
|
||||||
#define GPIOv_from_PORT_PIN( GPIO_port_n, pin )
|
|
||||||
|
|
||||||
enum GPIO_port_n {
|
|
||||||
GPIO_port_A = 0b00,
|
GPIO_port_A = 0b00,
|
||||||
GPIO_port_C = 0b10,
|
GPIO_port_C = 0b10,
|
||||||
GPIO_port_D = 0b11,
|
GPIO_port_D = 0b11,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GPIO_pinModes {
|
enum GPIO_pinModes
|
||||||
|
{
|
||||||
GPIO_pinMode_I_floating,
|
GPIO_pinMode_I_floating,
|
||||||
GPIO_pinMode_I_pullUp,
|
GPIO_pinMode_I_pullUp,
|
||||||
GPIO_pinMode_I_pullDown,
|
GPIO_pinMode_I_pullDown,
|
||||||
|
|
@ -121,13 +117,15 @@ enum GPIO_pinModes {
|
||||||
GPIO_pinMode_O_openDrainMux,
|
GPIO_pinMode_O_openDrainMux,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum lowhigh {
|
enum lowhigh
|
||||||
|
{
|
||||||
low,
|
low,
|
||||||
high,
|
high,
|
||||||
};
|
};
|
||||||
|
|
||||||
// analog inputs
|
// analog inputs
|
||||||
enum GPIO_analog_inputs {
|
enum GPIO_analog_inputs
|
||||||
|
{
|
||||||
GPIO_Ain0_A2,
|
GPIO_Ain0_A2,
|
||||||
GPIO_Ain1_A1,
|
GPIO_Ain1_A1,
|
||||||
GPIO_Ain2_C4,
|
GPIO_Ain2_C4,
|
||||||
|
|
@ -141,7 +139,8 @@ enum GPIO_analog_inputs {
|
||||||
};
|
};
|
||||||
|
|
||||||
// how many cycles the ADC shall sample the input for (speed vs precision)
|
// how many cycles the ADC shall sample the input for (speed vs precision)
|
||||||
enum GPIO_ADC_sampletimes {
|
enum GPIO_ADC_sampletimes
|
||||||
|
{
|
||||||
GPIO_ADC_sampletime_3cy,
|
GPIO_ADC_sampletime_3cy,
|
||||||
GPIO_ADC_sampletime_9cy,
|
GPIO_ADC_sampletime_9cy,
|
||||||
GPIO_ADC_sampletime_15cy,
|
GPIO_ADC_sampletime_15cy,
|
||||||
|
|
@ -152,23 +151,23 @@ enum GPIO_ADC_sampletimes {
|
||||||
GPIO_ADC_sampletime_241cy_default,
|
GPIO_ADC_sampletime_241cy_default,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GPIO_tim1_output_sets {
|
enum GPIO_tim1_output_sets
|
||||||
|
{
|
||||||
GPIO_tim1_output_set_0__D2_A1_C3_C4__D0_A2_D1,
|
GPIO_tim1_output_set_0__D2_A1_C3_C4__D0_A2_D1,
|
||||||
GPIO_tim1_output_set_1__C6_C7_C0_D3__C3_C4_D1,
|
GPIO_tim1_output_set_1__C6_C7_C0_D3__C3_C4_D1,
|
||||||
GPIO_tim1_output_set_2__D2_A1_C3_C4__D0_A2_D1,
|
GPIO_tim1_output_set_2__D2_A1_C3_C4__D0_A2_D1,
|
||||||
GPIO_tim1_output_set_3__C4_C7_C5_D4__C3_D2_C6,
|
GPIO_tim1_output_set_3__C4_C7_C5_D4__C3_D2_C6,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum GPIO_tim2_output_sets {
|
enum GPIO_tim2_output_sets
|
||||||
|
{
|
||||||
GPIO_tim2_output_set_0__D4_D3_C0_D7,
|
GPIO_tim2_output_set_0__D4_D3_C0_D7,
|
||||||
GPIO_tim2_output_set_1__C5_C2_D2_C1,
|
GPIO_tim2_output_set_1__C5_C2_D2_C1,
|
||||||
GPIO_tim2_output_set_2__C1_D3_C0_D7,
|
GPIO_tim2_output_set_2__C1_D3_C0_D7,
|
||||||
GPIO_tim2_output_set_3__C1_C7_D6_D5,
|
GPIO_tim2_output_set_3__C1_C7_D6_D5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ######## interface function overview: use these!
|
||||||
|
|
||||||
//######## interface function overview: use these!
|
|
||||||
// most functions have been reduced to function-like macros, actual definitions downstairs
|
// most functions have been reduced to function-like macros, actual definitions downstairs
|
||||||
|
|
||||||
// setup
|
// setup
|
||||||
|
|
@ -202,26 +201,20 @@ static inline void GPIO_tim2_init();
|
||||||
#define GPIO_tim1_analogWrite(channel, value)
|
#define GPIO_tim1_analogWrite(channel, value)
|
||||||
#define GPIO_tim2_analogWrite(channel, value)
|
#define GPIO_tim2_analogWrite(channel, value)
|
||||||
|
|
||||||
|
// ######## internal function declarations
|
||||||
|
|
||||||
|
// ######## internal variables
|
||||||
|
|
||||||
//######## internal function declarations
|
// ######## preprocessor macros
|
||||||
|
|
||||||
|
#define CONCAT(a, b) a##b
|
||||||
|
|
||||||
//######## internal variables
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//######## preprocessor macros
|
|
||||||
|
|
||||||
#define CONCAT(a, b) a ## b
|
|
||||||
#define CONCAT_INDIRECT(a, b) CONCAT(a, b)
|
#define CONCAT_INDIRECT(a, b) CONCAT(a, b)
|
||||||
|
|
||||||
#undef GPIOv_from_PORT_PIN
|
#undef GPIOv_from_PORT_PIN
|
||||||
#define GPIOv_from_PORT_PIN( GPIO_port_n, pin ) ((GPIO_port_n << 4 ) | (pin))
|
#define GPIOv_from_PORT_PIN(GPIO_port_n, pin) ((GPIO_port_n << 4) | (pin))
|
||||||
#define GPIOv_to_PORT( GPIOv ) (GPIOv >> 4 )
|
#define GPIOv_to_PORT(GPIOv) (GPIOv >> 4)
|
||||||
#define GPIOv_to_PIN( GPIOv ) (GPIOv & 0b1111)
|
#define GPIOv_to_PIN(GPIOv) (GPIOv & 0b1111)
|
||||||
#define GPIOv_to_GPIObase( GPIOv ) ((GPIO_TypeDef*)(uintptr_t)((GPIOA_BASE + (0x400 * (GPIOv >> 4)))))
|
#define GPIOv_to_GPIObase(GPIOv) ((GPIO_TypeDef *)(uintptr_t)((GPIOA_BASE + (0x400 * (GPIOv >> 4)))))
|
||||||
|
|
||||||
#define GPIOx_to_port_n2(GPIOx) GPIOx_to_port_n_##GPIOx
|
#define GPIOx_to_port_n2(GPIOx) GPIOx_to_port_n_##GPIOx
|
||||||
#define GPIOx_to_port_n(GPIOx) GPIOx_to_port_n2(GPIOx)
|
#define GPIOx_to_port_n(GPIOx) GPIOx_to_port_n2(GPIOx)
|
||||||
|
|
@ -290,12 +283,9 @@ static inline void GPIO_tim2_init();
|
||||||
#define GPIO_timer_prescaler TIM_CKD_DIV2 // APB_CLOCK / 1024 / 2 = 23.4kHz
|
#define GPIO_timer_prescaler TIM_CKD_DIV2 // APB_CLOCK / 1024 / 2 = 23.4kHz
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//######## define requirements / maintenance defines
|
// ######## define requirements / maintenance defines
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//######## small function definitions, static inline
|
|
||||||
|
|
||||||
|
// ######## small function definitions, static inline
|
||||||
|
|
||||||
#undef GPIO_port_enable
|
#undef GPIO_port_enable
|
||||||
#define GPIO_port_enable(GPIO_port_n) RCC->APB2PCENR |= GPIO_port_n_to_RCC_APB2Periph(GPIO_port_n);
|
#define GPIO_port_enable(GPIO_port_n) RCC->APB2PCENR |= GPIO_port_n_to_RCC_APB2Periph(GPIO_port_n);
|
||||||
|
|
@ -354,24 +344,10 @@ static inline void GPIO_tim2_init();
|
||||||
#define GPIO_ADC_set_sampletimes_all(GPIO_ADC_sampletime) ({ \
|
#define GPIO_ADC_set_sampletimes_all(GPIO_ADC_sampletime) ({ \
|
||||||
ADC1->SAMPTR2 &= 0; \
|
ADC1->SAMPTR2 &= 0; \
|
||||||
ADC1->SAMPTR2 |= \
|
ADC1->SAMPTR2 |= \
|
||||||
GPIO_ADC_sampletime << (0 * 3) \
|
GPIO_ADC_sampletime << (0 * 3) | GPIO_ADC_sampletime << (1 * 3) | GPIO_ADC_sampletime << (2 * 3) | GPIO_ADC_sampletime << (3 * 3) | GPIO_ADC_sampletime << (4 * 3) | GPIO_ADC_sampletime << (5 * 3) | GPIO_ADC_sampletime << (6 * 3) | GPIO_ADC_sampletime << (7 * 3) | GPIO_ADC_sampletime << (8 * 3) | GPIO_ADC_sampletime << (9 * 3); \
|
||||||
| GPIO_ADC_sampletime << (1 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (2 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (3 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (4 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (5 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (6 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (7 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (8 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (9 * 3); \
|
|
||||||
ADC1->SAMPTR1 &= 0; \
|
ADC1->SAMPTR1 &= 0; \
|
||||||
ADC1->SAMPTR1 |= \
|
ADC1->SAMPTR1 |= \
|
||||||
GPIO_ADC_sampletime << (0 * 3) \
|
GPIO_ADC_sampletime << (0 * 3) | GPIO_ADC_sampletime << (1 * 3) | GPIO_ADC_sampletime << (2 * 3) | GPIO_ADC_sampletime << (3 * 3) | GPIO_ADC_sampletime << (4 * 3) | GPIO_ADC_sampletime << (5 * 3); \
|
||||||
| GPIO_ADC_sampletime << (1 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (2 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (3 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (4 * 3) \
|
|
||||||
| GPIO_ADC_sampletime << (5 * 3); \
|
|
||||||
})
|
})
|
||||||
|
|
||||||
#undef GPIO_ADC_set_power
|
#undef GPIO_ADC_set_power
|
||||||
|
|
@ -383,16 +359,19 @@ static inline void GPIO_tim2_init();
|
||||||
#undef GPIO_ADC_calibrate
|
#undef GPIO_ADC_calibrate
|
||||||
#define GPIO_ADC_calibrate() ({ \
|
#define GPIO_ADC_calibrate() ({ \
|
||||||
ADC1->CTLR2 |= ADC_RSTCAL; \
|
ADC1->CTLR2 |= ADC_RSTCAL; \
|
||||||
while(ADC1->CTLR2 & ADC_RSTCAL); \
|
while (ADC1->CTLR2 & ADC_RSTCAL) \
|
||||||
|
; \
|
||||||
ADC1->CTLR2 |= ADC_CAL; \
|
ADC1->CTLR2 |= ADC_CAL; \
|
||||||
while(ADC1->CTLR2 & ADC_CAL); \
|
while (ADC1->CTLR2 & ADC_CAL) \
|
||||||
|
; \
|
||||||
})
|
})
|
||||||
|
|
||||||
// large but will likely only ever be called once
|
// large but will likely only ever be called once
|
||||||
static inline void GPIO_ADCinit() {
|
static inline void GPIO_ADCinit()
|
||||||
|
{
|
||||||
// select ADC clock source
|
// select ADC clock source
|
||||||
// ADCCLK = 24 MHz => RCC_ADCPRE = 0: divide by 2
|
// ADCCLK = 24 MHz => RCC_ADCPRE = 0: divide by 2
|
||||||
RCC->CFGR0 &= ~(0x1F<<11);
|
RCC->CFGR0 &= ~(0x1F << 11);
|
||||||
|
|
||||||
// enable clock to the ADC
|
// enable clock to the ADC
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_ADC1;
|
RCC->APB2PCENR |= RCC_APB2Periph_ADC1;
|
||||||
|
|
@ -417,7 +396,8 @@ static inline void GPIO_ADCinit() {
|
||||||
GPIO_ADC_calibrate();
|
GPIO_ADC_calibrate();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint16_t GPIO_analogRead(enum GPIO_analog_inputs input) {
|
static inline uint16_t GPIO_analogRead(enum GPIO_analog_inputs input)
|
||||||
|
{
|
||||||
// set mux to selected input
|
// set mux to selected input
|
||||||
ADC1->RSQR3 = input;
|
ADC1->RSQR3 = input;
|
||||||
// allow everything to precharge
|
// allow everything to precharge
|
||||||
|
|
@ -425,13 +405,11 @@ static inline uint16_t GPIO_analogRead(enum GPIO_analog_inputs input) {
|
||||||
// start sw conversion (auto clears)
|
// start sw conversion (auto clears)
|
||||||
ADC1->CTLR2 |= ADC_SWSTART;
|
ADC1->CTLR2 |= ADC_SWSTART;
|
||||||
// wait for conversion complete
|
// wait for conversion complete
|
||||||
while(!(ADC1->STATR & ADC_EOC)) {}
|
while (!(ADC1->STATR & ADC_EOC)) {}
|
||||||
// get result
|
// get result
|
||||||
return ADC1->RDATAR;
|
return ADC1->RDATAR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#undef GPIO_tim1_map
|
#undef GPIO_tim1_map
|
||||||
#define GPIO_tim1_map(GPIO_tim1_output_set) ({ \
|
#define GPIO_tim1_map(GPIO_tim1_output_set) ({ \
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_AFIO; \
|
RCC->APB2PCENR |= RCC_APB2Periph_AFIO; \
|
||||||
|
|
@ -444,7 +422,8 @@ static inline uint16_t GPIO_analogRead(enum GPIO_analog_inputs input) {
|
||||||
AFIO->PCFR1 |= ((GPIO_tim2_output_set & 0b11) << 8); \
|
AFIO->PCFR1 |= ((GPIO_tim2_output_set & 0b11) << 8); \
|
||||||
})
|
})
|
||||||
|
|
||||||
static inline void GPIO_tim1_init() {
|
static inline void GPIO_tim1_init()
|
||||||
|
{
|
||||||
// enable TIM1
|
// enable TIM1
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_TIM1;
|
RCC->APB2PCENR |= RCC_APB2Periph_TIM1;
|
||||||
// reset TIM1 to init all regs
|
// reset TIM1 to init all regs
|
||||||
|
|
@ -465,7 +444,8 @@ static inline void GPIO_tim1_init() {
|
||||||
// Enable TIM1
|
// Enable TIM1
|
||||||
TIM1->CTLR1 |= TIM_CEN;
|
TIM1->CTLR1 |= TIM_CEN;
|
||||||
}
|
}
|
||||||
static inline void GPIO_tim2_init() {
|
static inline void GPIO_tim2_init()
|
||||||
|
{
|
||||||
// enable TIM2
|
// enable TIM2
|
||||||
RCC->APB1PCENR |= RCC_APB1Periph_TIM2;
|
RCC->APB1PCENR |= RCC_APB1Periph_TIM2;
|
||||||
// reset TIM2 to init all regs
|
// reset TIM2 to init all regs
|
||||||
|
|
@ -500,7 +480,7 @@ static inline void GPIO_tim2_init() {
|
||||||
#undef GPIO_tim2_enableCH
|
#undef GPIO_tim2_enableCH
|
||||||
#define GPIO_tim2_enableCH(channel) ({ \
|
#define GPIO_tim2_enableCH(channel) ({ \
|
||||||
GPIO_timer_channel_set(TIM2, channel); \
|
GPIO_timer_channel_set(TIM2, channel); \
|
||||||
TIM2->CCER |= (TIM_OutputState_Enable ) << (4 * (channel - 1)); \
|
TIM2->CCER |= (TIM_OutputState_Enable) << (4 * (channel - 1)); \
|
||||||
})
|
})
|
||||||
|
|
||||||
#define GPIO_timer_CVR(channel) CONCAT_INDIRECT(CH, CONCAT_INDIRECT(channel, CVR))
|
#define GPIO_timer_CVR(channel) CONCAT_INDIRECT(CH, CONCAT_INDIRECT(channel, CVR))
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
//######## necessities
|
// ######## necessities
|
||||||
|
|
||||||
// include guards
|
// include guards
|
||||||
#ifndef CH32V003_SPI_H
|
#ifndef CH32V003_SPI_H
|
||||||
#define CH32V003_SPI_H
|
#define CH32V003_SPI_H
|
||||||
|
|
||||||
// includes
|
// includes
|
||||||
#include<stdint.h> //uintN_t support
|
|
||||||
#include "ch32fun.h"
|
#include "ch32fun.h"
|
||||||
|
#include <stdint.h> //uintN_t support
|
||||||
|
|
||||||
#ifndef APB_CLOCK
|
#ifndef APB_CLOCK
|
||||||
#define APB_CLOCK FUNCONF_SYSTEM_CORE_CLOCK
|
#define APB_CLOCK FUNCONF_SYSTEM_CORE_CLOCK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*######## library usage and configuration
|
/*######## library usage and configuration
|
||||||
|
|
@ -47,9 +47,7 @@ then pick the desired setting of each group:
|
||||||
#define CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL // toggle manually!
|
#define CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL // toggle manually!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// ######## function overview (declarations): use these!
|
||||||
|
|
||||||
//######## function overview (declarations): use these!
|
|
||||||
// initialize and configure the SPI peripheral
|
// initialize and configure the SPI peripheral
|
||||||
static inline void SPI_init();
|
static inline void SPI_init();
|
||||||
|
|
||||||
|
|
@ -87,31 +85,25 @@ static inline void SPI_poweron();
|
||||||
static inline void kill_interrrupts();
|
static inline void kill_interrrupts();
|
||||||
static inline void restore_interrupts();
|
static inline void restore_interrupts();
|
||||||
|
|
||||||
|
// ######## internal function declarations
|
||||||
|
|
||||||
//######## internal function declarations
|
|
||||||
static inline void SPI_wait_TX_complete();
|
static inline void SPI_wait_TX_complete();
|
||||||
static inline uint8_t SPI_is_RX_empty();
|
static inline uint8_t SPI_is_RX_empty();
|
||||||
static inline void SPI_wait_RX_available();
|
static inline void SPI_wait_RX_available();
|
||||||
|
|
||||||
|
// ######## internal variables
|
||||||
|
|
||||||
//######## internal variables
|
|
||||||
static uint16_t EXT1_INTENR_backup;
|
static uint16_t EXT1_INTENR_backup;
|
||||||
|
|
||||||
|
// ######## preprocessor macros
|
||||||
|
|
||||||
//######## preprocessor macros
|
|
||||||
// min and max helper macros
|
// min and max helper macros
|
||||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||||
#define MAX(a,b) (((a)>(b))?(a):(b))
|
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
// stringify for displaying what #defines evaluated to at preprocessor stage
|
// stringify for displaying what #defines evaluated to at preprocessor stage
|
||||||
#define VALUE_TO_STRING(x) #x
|
#define VALUE_TO_STRING(x) #x
|
||||||
#define VALUE(x) VALUE_TO_STRING(x)
|
#define VALUE(x) VALUE_TO_STRING(x)
|
||||||
#define VAR_NAME_VALUE(var) #var "=" VALUE(var)
|
#define VAR_NAME_VALUE(var) #var "=" VALUE(var)
|
||||||
|
|
||||||
//compile-time log2
|
// compile-time log2
|
||||||
#define LOG2(x) ((x) == 0 ? -1 : __builtin_ctz(x))
|
#define LOG2(x) ((x) == 0 ? -1 : __builtin_ctz(x))
|
||||||
|
|
||||||
// compile-time clock prescaler calculation: log2(APB_CLOCK/SPEED_BUS)
|
// compile-time clock prescaler calculation: log2(APB_CLOCK/SPEED_BUS)
|
||||||
|
|
@ -120,30 +112,28 @@ static uint16_t EXT1_INTENR_backup;
|
||||||
|
|
||||||
// ensure that CLOCK_PRESCALER_VALUE is within the range of 0..7
|
// ensure that CLOCK_PRESCALER_VALUE is within the range of 0..7
|
||||||
_Static_assert(SPI_CLK_PRESCALER >= 0 && SPI_CLK_PRESCALER <= 7, "SPI_CLK_PRESCALER is out of range (0..7). Please set a different SPI bus speed. prescaler = log2(f_CPU/f_SPI)");
|
_Static_assert(SPI_CLK_PRESCALER >= 0 && SPI_CLK_PRESCALER <= 7, "SPI_CLK_PRESCALER is out of range (0..7). Please set a different SPI bus speed. prescaler = log2(f_CPU/f_SPI)");
|
||||||
//#pragma message(VAR_NAME_VALUE(SPI_CLK_PRESCALER))
|
// #pragma message(VAR_NAME_VALUE(SPI_CLK_PRESCALER))
|
||||||
|
|
||||||
|
// ######## preprocessor #define requirements
|
||||||
|
|
||||||
//######## preprocessor #define requirements
|
|
||||||
|
|
||||||
#if !defined(CH32V003_SPI_DIRECTION_2LINE_TXRX) && !defined(CH32V003_SPI_DIRECTION_1LINE_TX)
|
#if !defined(CH32V003_SPI_DIRECTION_2LINE_TXRX) && !defined(CH32V003_SPI_DIRECTION_1LINE_TX)
|
||||||
#warning "none of the CH32V003_SPI_DIRECTION_ options were defined!"
|
#warning "none of the CH32V003_SPI_DIRECTION_ options were defined!"
|
||||||
#endif
|
#endif
|
||||||
#if defined(CH32V003_SPI_DIRECTION_2LINE_TXRX) && defined(CH32V003_SPI_DIRECTION_1LINE_TX)
|
#if defined(CH32V003_SPI_DIRECTION_2LINE_TXRX) && defined(CH32V003_SPI_DIRECTION_1LINE_TX)
|
||||||
#warning "both CH32V003_SPI_DIRECTION_ options were defined!"
|
#warning "both CH32V003_SPI_DIRECTION_ options were defined!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((defined(CH32V003_SPI_CLK_MODE_POL0_PHA0) ? 1 : 0) + \
|
#if ((defined(CH32V003_SPI_CLK_MODE_POL0_PHA0) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_CLK_MODE_POL0_PHA1) ? 1 : 0) + \
|
(defined(CH32V003_SPI_CLK_MODE_POL0_PHA1) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA0) ? 1 : 0) + \
|
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA0) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA1) ? 1 : 0)) > 1
|
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA1) ? 1 : 0)) > 1
|
||||||
#warning "more than one of the CH32V003_SPI_CLK_MODE_ options were defined!"
|
#warning "more than one of the CH32V003_SPI_CLK_MODE_ options were defined!"
|
||||||
#endif
|
#endif
|
||||||
#if ((defined(CH32V003_SPI_CLK_MODE_POL0_PHA0) ? 1 : 0) + \
|
#if ((defined(CH32V003_SPI_CLK_MODE_POL0_PHA0) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_CLK_MODE_POL0_PHA1) ? 1 : 0) + \
|
(defined(CH32V003_SPI_CLK_MODE_POL0_PHA1) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA0) ? 1 : 0) + \
|
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA0) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA1) ? 1 : 0)) == 0
|
(defined(CH32V003_SPI_CLK_MODE_POL1_PHA1) ? 1 : 0)) == 0
|
||||||
#warning "none of the CH32V003_SPI_CLK_MODE_ options were defined!"
|
#warning "none of the CH32V003_SPI_CLK_MODE_ options were defined!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if ((defined(CH32V003_SPI_NSS_HARDWARE_PC0) ? 1 : 0) + \
|
#if ((defined(CH32V003_SPI_NSS_HARDWARE_PC0) ? 1 : 0) + \
|
||||||
|
|
@ -151,202 +141,220 @@ _Static_assert(SPI_CLK_PRESCALER >= 0 && SPI_CLK_PRESCALER <= 7, "SPI_CLK_PRESCA
|
||||||
(defined(CH32V003_SPI_NSS_SOFTWARE_PC3) ? 1 : 0) + \
|
(defined(CH32V003_SPI_NSS_SOFTWARE_PC3) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_NSS_SOFTWARE_PC4) ? 1 : 0) + \
|
(defined(CH32V003_SPI_NSS_SOFTWARE_PC4) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL) ? 1 : 0)) > 1
|
(defined(CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL) ? 1 : 0)) > 1
|
||||||
#warning "more than one of the CH32V003_SPI_NSS_ options were defined!"
|
#warning "more than one of the CH32V003_SPI_NSS_ options were defined!"
|
||||||
#endif
|
#endif
|
||||||
#if ((defined(CH32V003_SPI_NSS_HARDWARE_PC0) ? 1 : 0) + \
|
#if ((defined(CH32V003_SPI_NSS_HARDWARE_PC0) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_NSS_HARDWARE_PC1) ? 1 : 0) + \
|
(defined(CH32V003_SPI_NSS_HARDWARE_PC1) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_NSS_SOFTWARE_PC3) ? 1 : 0) + \
|
(defined(CH32V003_SPI_NSS_SOFTWARE_PC3) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_NSS_SOFTWARE_PC4) ? 1 : 0) + \
|
(defined(CH32V003_SPI_NSS_SOFTWARE_PC4) ? 1 : 0) + \
|
||||||
(defined(CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL) ? 1 : 0)) == 0
|
(defined(CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL) ? 1 : 0)) == 0
|
||||||
#warning "none of the CH32V003_SPI_NSS_ options were defined!"
|
#warning "none of the CH32V003_SPI_NSS_ options were defined!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// ######## small function definitions, static inline
|
||||||
|
static inline void SPI_init()
|
||||||
//######## small function definitions, static inline
|
{
|
||||||
static inline void SPI_init() {
|
|
||||||
SPI_poweron();
|
SPI_poweron();
|
||||||
|
|
||||||
// reset control register
|
// reset control register
|
||||||
SPI1->CTLR1 = 0;
|
SPI1->CTLR1 = 0;
|
||||||
|
|
||||||
// set prescaler
|
// set prescaler
|
||||||
SPI1->CTLR1 |= SPI_CTLR1_BR & (SPI_CLK_PRESCALER<<3);
|
SPI1->CTLR1 |= SPI_CTLR1_BR & (SPI_CLK_PRESCALER << 3);
|
||||||
|
|
||||||
// set clock polarity and phase
|
// set clock polarity and phase
|
||||||
#if defined(CH32V003_SPI_CLK_MODE_POL0_PHA0)
|
#if defined(CH32V003_SPI_CLK_MODE_POL0_PHA0)
|
||||||
SPI1->CTLR1 |= (SPI_CPOL_Low | SPI_CPHA_1Edge);
|
SPI1->CTLR1 |= (SPI_CPOL_Low | SPI_CPHA_1Edge);
|
||||||
#elif defined (CH32V003_SPI_CLK_MODE_POL0_PHA1)
|
#elif defined(CH32V003_SPI_CLK_MODE_POL0_PHA1)
|
||||||
SPI1->CTLR1 |= (SPI_CPOL_Low | SPI_CPHA_2Edge);
|
SPI1->CTLR1 |= (SPI_CPOL_Low | SPI_CPHA_2Edge);
|
||||||
#elif defined (CH32V003_SPI_CLK_MODE_POL1_PHA0)
|
#elif defined(CH32V003_SPI_CLK_MODE_POL1_PHA0)
|
||||||
SPI1->CTLR1 |= (SPI_CPOL_High | SPI_CPHA_1Edge);
|
SPI1->CTLR1 |= (SPI_CPOL_High | SPI_CPHA_1Edge);
|
||||||
#elif defined (CH32V003_SPI_CLK_MODE_POL1_PHA1)
|
#elif defined(CH32V003_SPI_CLK_MODE_POL1_PHA1)
|
||||||
SPI1->CTLR1 |= (SPI_CPOL_High | SPI_CPHA_2Edge);
|
SPI1->CTLR1 |= (SPI_CPOL_High | SPI_CPHA_2Edge);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// configure NSS pin, master mode
|
// configure NSS pin, master mode
|
||||||
#if defined(CH32V003_SPI_NSS_HARDWARE_PC0)
|
#if defined(CH32V003_SPI_NSS_HARDWARE_PC0)
|
||||||
// _NSS (negative slave select) on PC0, 10MHz Output, alt func, push-pull1
|
// _NSS (negative slave select) on PC0, 10MHz Output, alt func, push-pull1
|
||||||
SPI1->CTLR1 |= SPI_NSS_Hard; // NSS hardware control mode
|
SPI1->CTLR1 |= SPI_NSS_Hard; // NSS hardware control mode
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*0));
|
GPIOC->CFGLR &= ~(0xf << (4 * 0));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*0);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 0);
|
||||||
AFIO->PCFR1 |= GPIO_Remap_SPI1; // remap NSS (C1) to _NSS (C0)
|
AFIO->PCFR1 |= GPIO_Remap_SPI1; // remap NSS (C1) to _NSS (C0)
|
||||||
SPI1->CTLR2 |= SPI_CTLR2_SSOE; // pull _NSS high
|
SPI1->CTLR2 |= SPI_CTLR2_SSOE; // pull _NSS high
|
||||||
#elif defined(CH32V003_SPI_NSS_HARDWARE_PC1)
|
#elif defined(CH32V003_SPI_NSS_HARDWARE_PC1)
|
||||||
// NSS (negative slave select) on PC1, 10MHz Output, alt func, push-pull1
|
// NSS (negative slave select) on PC1, 10MHz Output, alt func, push-pull1
|
||||||
SPI1->CTLR1 |= SPI_NSS_Hard; // NSS hardware control mode
|
SPI1->CTLR1 |= SPI_NSS_Hard; // NSS hardware control mode
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*1));
|
GPIOC->CFGLR &= ~(0xf << (4 * 1));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*1);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 1);
|
||||||
SPI1->CTLR2 |= SPI_CTLR2_SSOE; // pull _NSS high
|
SPI1->CTLR2 |= SPI_CTLR2_SSOE; // pull _NSS high
|
||||||
#elif defined(CH32V003_SPI_NSS_SOFTWARE_PC3)
|
#elif defined(CH32V003_SPI_NSS_SOFTWARE_PC3)
|
||||||
SPI1->CTLR1 |= SPI_NSS_Soft; // SSM NSS software control mode
|
SPI1->CTLR1 |= SPI_NSS_Soft; // SSM NSS software control mode
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*3));
|
GPIOC->CFGLR &= ~(0xf << (4 * 3));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*3);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 3);
|
||||||
#elif defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
#elif defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
||||||
SPI1->CTLR1 |= SPI_NSS_Soft; // SSM NSS software control mode
|
SPI1->CTLR1 |= SPI_NSS_Soft; // SSM NSS software control mode
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*4));
|
GPIOC->CFGLR &= ~(0xf << (4 * 4));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*4);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 4);
|
||||||
#elif defined(CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL)
|
#elif defined(CH32V003_SPI_NSS_SOFTWARE_ANY_MANUAL)
|
||||||
SPI1->CTLR1 |= SPI_NSS_Soft; // SSM NSS software control mode
|
SPI1->CTLR1 |= SPI_NSS_Soft; // SSM NSS software control mode
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// SCK on PC5, 10MHz Output, alt func, push-pull
|
// SCK on PC5, 10MHz Output, alt func, push-pull
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*5));
|
GPIOC->CFGLR &= ~(0xf << (4 * 5));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF)<<(4*5);
|
GPIOC->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 5);
|
||||||
|
|
||||||
// CH32V003 is master
|
// CH32V003 is master
|
||||||
SPI1->CTLR1 |= SPI_Mode_Master;
|
SPI1->CTLR1 |= SPI_Mode_Master;
|
||||||
|
|
||||||
// set data direction and configure data pins
|
// set data direction and configure data pins
|
||||||
#if defined(CH32V003_SPI_DIRECTION_2LINE_TXRX)
|
#if defined(CH32V003_SPI_DIRECTION_2LINE_TXRX)
|
||||||
SPI1->CTLR1 |= SPI_Direction_2Lines_FullDuplex;
|
SPI1->CTLR1 |= SPI_Direction_2Lines_FullDuplex;
|
||||||
|
|
||||||
// MOSI on PC6, 10MHz Output, alt func, push-pull
|
// MOSI on PC6, 10MHz Output, alt func, push-pull
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*6));
|
GPIOC->CFGLR &= ~(0xf << (4 * 6));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF)<<(4*6);
|
GPIOC->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 6);
|
||||||
|
|
||||||
// MISO on PC7, 10MHz input, floating
|
// MISO on PC7, 10MHz input, floating
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*7));
|
GPIOC->CFGLR &= ~(0xf << (4 * 7));
|
||||||
GPIOC->CFGLR |= GPIO_CNF_IN_FLOATING<<(4*7);
|
GPIOC->CFGLR |= GPIO_CNF_IN_FLOATING << (4 * 7);
|
||||||
#elif defined(CH32V003_SPI_DIRECTION_1LINE_TX)
|
#elif defined(CH32V003_SPI_DIRECTION_1LINE_TX)
|
||||||
SPI1->CTLR1 |= SPI_Direction_1Line_Tx;
|
SPI1->CTLR1 |= SPI_Direction_1Line_Tx;
|
||||||
|
|
||||||
// MOSI on PC6, 10MHz Output, alt func, push-pull
|
// MOSI on PC6, 10MHz Output, alt func, push-pull
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*6));
|
GPIOC->CFGLR &= ~(0xf << (4 * 6));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF)<<(4*6);
|
GPIOC->CFGLR |= (GPIO_Speed_50MHz | GPIO_CNF_OUT_PP_AF) << (4 * 6);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SPI_begin_8() {
|
static inline void SPI_begin_8()
|
||||||
|
{
|
||||||
SPI1->CTLR1 &= ~(SPI_CTLR1_DFF); // DFF 16bit data-length enable, writable only when SPE is 0
|
SPI1->CTLR1 &= ~(SPI_CTLR1_DFF); // DFF 16bit data-length enable, writable only when SPE is 0
|
||||||
SPI1->CTLR1 |= SPI_CTLR1_SPE;
|
SPI1->CTLR1 |= SPI_CTLR1_SPE;
|
||||||
}
|
}
|
||||||
static inline void SPI_begin_16() {
|
static inline void SPI_begin_16()
|
||||||
|
{
|
||||||
SPI1->CTLR1 |= SPI_CTLR1_DFF; // DFF 16bit data-length enable, writable only when SPE is 0
|
SPI1->CTLR1 |= SPI_CTLR1_DFF; // DFF 16bit data-length enable, writable only when SPE is 0
|
||||||
SPI1->CTLR1 |= SPI_CTLR1_SPE;
|
SPI1->CTLR1 |= SPI_CTLR1_SPE;
|
||||||
}
|
}
|
||||||
static inline void SPI_end() {
|
static inline void SPI_end()
|
||||||
|
{
|
||||||
SPI1->CTLR1 &= ~(SPI_CTLR1_SPE);
|
SPI1->CTLR1 &= ~(SPI_CTLR1_SPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3)
|
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3)
|
||||||
static inline void SPI_NSS_software_high() {
|
static inline void SPI_NSS_software_high()
|
||||||
GPIOC->BSHR = (1<<3);
|
{
|
||||||
|
GPIOC->BSHR = (1 << 3);
|
||||||
}
|
}
|
||||||
static inline void SPI_NSS_software_low() {
|
static inline void SPI_NSS_software_low()
|
||||||
GPIOC->BSHR = (1<<(16+3));
|
{
|
||||||
|
GPIOC->BSHR = (1 << (16 + 3));
|
||||||
}
|
}
|
||||||
#elif defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
#elif defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
||||||
static inline void SPI_NSS_software_high() {
|
static inline void SPI_NSS_software_high()
|
||||||
GPIOC->BSHR = (1<<4);
|
{
|
||||||
|
GPIOC->BSHR = (1 << 4);
|
||||||
}
|
}
|
||||||
static inline void SPI_NSS_software_low() {
|
static inline void SPI_NSS_software_low()
|
||||||
GPIOC->BSHR = (1<<(16+4));
|
{
|
||||||
|
GPIOC->BSHR = (1 << (16 + 4));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline uint8_t SPI_read_8() {
|
static inline uint8_t SPI_read_8()
|
||||||
|
{
|
||||||
return SPI1->DATAR;
|
return SPI1->DATAR;
|
||||||
}
|
}
|
||||||
static inline uint16_t SPI_read_16() {
|
static inline uint16_t SPI_read_16()
|
||||||
|
{
|
||||||
return SPI1->DATAR;
|
return SPI1->DATAR;
|
||||||
}
|
}
|
||||||
static inline void SPI_write_8(uint8_t data) {
|
static inline void SPI_write_8(uint8_t data)
|
||||||
|
{
|
||||||
SPI1->DATAR = data;
|
SPI1->DATAR = data;
|
||||||
}
|
}
|
||||||
static inline void SPI_write_16(uint16_t data) {
|
static inline void SPI_write_16(uint16_t data)
|
||||||
|
{
|
||||||
SPI1->DATAR = data;
|
SPI1->DATAR = data;
|
||||||
}
|
}
|
||||||
static inline uint8_t SPI_transfer_8(uint8_t data) {
|
static inline uint8_t SPI_transfer_8(uint8_t data)
|
||||||
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
{
|
||||||
|
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
||||||
SPI_NSS_software_high();
|
SPI_NSS_software_high();
|
||||||
#endif
|
#endif
|
||||||
SPI_write_8(data);
|
SPI_write_8(data);
|
||||||
SPI_wait_TX_complete();
|
SPI_wait_TX_complete();
|
||||||
asm volatile("nop");
|
asm volatile("nop");
|
||||||
SPI_wait_RX_available();
|
SPI_wait_RX_available();
|
||||||
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
||||||
SPI_NSS_software_low();
|
SPI_NSS_software_low();
|
||||||
#endif
|
#endif
|
||||||
return SPI_read_8();
|
return SPI_read_8();
|
||||||
}
|
}
|
||||||
static inline uint16_t SPI_transfer_16(uint16_t data) {
|
static inline uint16_t SPI_transfer_16(uint16_t data)
|
||||||
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
{
|
||||||
|
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
||||||
SPI_NSS_software_high();
|
SPI_NSS_software_high();
|
||||||
#endif
|
#endif
|
||||||
SPI_write_16(data);
|
SPI_write_16(data);
|
||||||
SPI_wait_TX_complete();
|
SPI_wait_TX_complete();
|
||||||
asm volatile("nop");
|
asm volatile("nop");
|
||||||
SPI_wait_RX_available();
|
SPI_wait_RX_available();
|
||||||
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
#if defined(CH32V003_SPI_NSS_SOFTWARE_PC3) || defined(CH32V003_SPI_NSS_SOFTWARE_PC4)
|
||||||
SPI_NSS_software_low();
|
SPI_NSS_software_low();
|
||||||
#endif
|
#endif
|
||||||
return SPI_read_16();
|
return SPI_read_16();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void SPI_poweroff() {
|
static inline void SPI_poweroff()
|
||||||
|
{
|
||||||
SPI_end();
|
SPI_end();
|
||||||
RCC->APB2PCENR &= ~RCC_APB2Periph_SPI1;
|
RCC->APB2PCENR &= ~RCC_APB2Periph_SPI1;
|
||||||
}
|
}
|
||||||
static inline void SPI_poweron() {
|
static inline void SPI_poweron()
|
||||||
|
{
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC | RCC_APB2Periph_SPI1;
|
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC | RCC_APB2Periph_SPI1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void kill_interrrupts() {
|
static inline void kill_interrrupts()
|
||||||
|
{
|
||||||
EXT1_INTENR_backup = EXTI->INTENR;
|
EXT1_INTENR_backup = EXTI->INTENR;
|
||||||
// zero the interrupt enable register to disable all interrupts
|
// zero the interrupt enable register to disable all interrupts
|
||||||
EXTI->INTENR = 0;
|
EXTI->INTENR = 0;
|
||||||
}
|
}
|
||||||
static inline void restore_interrupts() {
|
static inline void restore_interrupts()
|
||||||
|
{
|
||||||
EXTI->INTENR = EXT1_INTENR_backup;
|
EXTI->INTENR = EXT1_INTENR_backup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ######## small internal function definitions, static inline
|
||||||
|
static inline void SPI_wait_TX_complete()
|
||||||
//######## small internal function definitions, static inline
|
{
|
||||||
static inline void SPI_wait_TX_complete() {
|
while (!(SPI1->STATR & SPI_STATR_TXE)) {}
|
||||||
while(!(SPI1->STATR & SPI_STATR_TXE)) {}
|
|
||||||
}
|
}
|
||||||
static inline uint8_t SPI_is_RX_empty() {
|
static inline uint8_t SPI_is_RX_empty()
|
||||||
|
{
|
||||||
return SPI1->STATR & SPI_STATR_RXNE;
|
return SPI1->STATR & SPI_STATR_RXNE;
|
||||||
}
|
}
|
||||||
static inline void SPI_wait_RX_available() {
|
static inline void SPI_wait_RX_available()
|
||||||
while(!(SPI1->STATR & SPI_STATR_RXNE)) {}
|
{
|
||||||
|
while (!(SPI1->STATR & SPI_STATR_RXNE)) {}
|
||||||
}
|
}
|
||||||
static inline void SPI_wait_not_busy() {
|
static inline void SPI_wait_not_busy()
|
||||||
while((SPI1->STATR & SPI_STATR_BSY) != 0) {}
|
{
|
||||||
|
while ((SPI1->STATR & SPI_STATR_BSY) != 0) {}
|
||||||
}
|
}
|
||||||
static inline void SPI_wait_transmit_finished() {
|
static inline void SPI_wait_transmit_finished()
|
||||||
|
{
|
||||||
SPI_wait_TX_complete();
|
SPI_wait_TX_complete();
|
||||||
SPI_wait_not_busy();
|
SPI_wait_not_busy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ######## implementation block
|
||||||
//######## implementation block
|
// #define CH32V003_SPI_IMPLEMENTATION //enable so LSP can give you text colors while working on the implementation block, disable for normal use of the library
|
||||||
//#define CH32V003_SPI_IMPLEMENTATION //enable so LSP can give you text colors while working on the implementation block, disable for normal use of the library
|
|
||||||
#if defined(CH32V003_SPI_IMPLEMENTATION)
|
#if defined(CH32V003_SPI_IMPLEMENTATION)
|
||||||
|
|
||||||
//no functions here because I think all of the functions are small enough to static inline
|
// no functions here because I think all of the functions are small enough to static inline
|
||||||
|
|
||||||
#endif // CH32V003_SPI_IMPLEMENTATION
|
#endif // CH32V003_SPI_IMPLEMENTATION
|
||||||
#endif // CH32V003_SPI_H
|
#endif // CH32V003_SPI_H
|
||||||
|
|
|
||||||
|
|
@ -21,8 +21,6 @@
|
||||||
sum[7] += ReadTouchPin( GPIOD, 4, 7, iterations );
|
sum[7] += ReadTouchPin( GPIOD, 4, 7, iterations );
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define TOUCH_ADC_SAMPLE_TIME 2 // Tricky: Don't change this without a lot of experimentation.
|
#define TOUCH_ADC_SAMPLE_TIME 2 // Tricky: Don't change this without a lot of experimentation.
|
||||||
|
|
||||||
// Can either be 0 or 1.
|
// Can either be 0 or 1.
|
||||||
|
|
@ -50,16 +48,13 @@
|
||||||
jalr a2, 1\n\
|
jalr a2, 1\n\
|
||||||
.long 0x00010001\n\
|
.long 0x00010001\n\
|
||||||
.long 0x00010001\n\
|
.long 0x00010001\n\
|
||||||
"\
|
" ::[cyccnt] "r"(SysTick->CNT) : "a1", "a2");
|
||||||
:: [cyccnt]"r"(SysTick->CNT) : "a1", "a2"\
|
|
||||||
);
|
|
||||||
|
|
||||||
|
static void InitTouchADC();
|
||||||
static void InitTouchADC( );
|
void InitTouchADC()
|
||||||
void InitTouchADC( )
|
|
||||||
{
|
{
|
||||||
// ADCCLK = 24 MHz => RCC_ADCPRE = 0: divide sys clock by 2
|
// ADCCLK = 24 MHz => RCC_ADCPRE = 0: divide sys clock by 2
|
||||||
RCC->CFGR0 &= ~(0x1F<<11);
|
RCC->CFGR0 &= ~(0x1F << 11);
|
||||||
|
|
||||||
// Set up single conversion on chl 2
|
// Set up single conversion on chl 2
|
||||||
ADC1->RSQR1 = 0;
|
ADC1->RSQR1 = 0;
|
||||||
|
|
@ -70,41 +65,46 @@ void InitTouchADC( )
|
||||||
|
|
||||||
// Reset calibration
|
// Reset calibration
|
||||||
ADC1->CTLR2 |= ADC_RSTCAL;
|
ADC1->CTLR2 |= ADC_RSTCAL;
|
||||||
while(ADC1->CTLR2 & ADC_RSTCAL);
|
while (ADC1->CTLR2 & ADC_RSTCAL)
|
||||||
|
;
|
||||||
|
|
||||||
// Calibrate
|
// Calibrate
|
||||||
ADC1->CTLR2 |= ADC_CAL;
|
ADC1->CTLR2 |= ADC_CAL;
|
||||||
while(ADC1->CTLR2 & ADC_CAL);
|
while (ADC1->CTLR2 & ADC_CAL)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run from RAM to get even more stable timing.
|
// Run from RAM to get even more stable timing.
|
||||||
// This function call takes about 8.1uS to execute.
|
// This function call takes about 8.1uS to execute.
|
||||||
static uint32_t ReadTouchPin( GPIO_TypeDef * io, int portpin, int adcno, int iterations ) __attribute__((noinline, section(".srodata")));
|
static uint32_t ReadTouchPin(GPIO_TypeDef *io, int portpin, int adcno, int iterations) __attribute__((noinline, section(".srodata")));
|
||||||
uint32_t ReadTouchPin( GPIO_TypeDef * io, int portpin, int adcno, int iterations )
|
uint32_t ReadTouchPin(GPIO_TypeDef *io, int portpin, int adcno, int iterations)
|
||||||
{
|
{
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
|
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
FORCEALIGNADC
|
FORCEALIGNADC
|
||||||
ADC1->RSQR3 = adcno;
|
ADC1->RSQR3 = adcno;
|
||||||
ADC1->SAMPTR2 = TOUCH_ADC_SAMPLE_TIME<<(3*adcno);
|
ADC1->SAMPTR2 = TOUCH_ADC_SAMPLE_TIME << (3 * adcno);
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
|
||||||
uint32_t CFGBASE = io->CFGLR & (~(0xf<<(4*portpin)));
|
uint32_t CFGBASE = io->CFGLR & (~(0xf << (4 * portpin)));
|
||||||
uint32_t CFGFLOAT = ((GPIO_CFGLR_IN_PUPD)<<(4*portpin)) | CFGBASE;
|
uint32_t CFGFLOAT = ((GPIO_CFGLR_IN_PUPD) << (4 * portpin)) | CFGBASE;
|
||||||
uint32_t CFGDRIVE = (GPIO_CFGLR_OUT_2Mhz_PP)<<(4*portpin) | CFGBASE;
|
uint32_t CFGDRIVE = (GPIO_CFGLR_OUT_2Mhz_PP) << (4 * portpin) | CFGBASE;
|
||||||
|
|
||||||
// If we run multiple times with slightly different wait times, we can
|
// If we run multiple times with slightly different wait times, we can
|
||||||
// reduce the impact of the ADC's DNL.
|
// reduce the impact of the ADC's DNL.
|
||||||
|
|
||||||
|
|
||||||
#if TOUCH_FLAT == 1
|
#if TOUCH_FLAT == 1
|
||||||
#define RELEASEIO io->BSHR = 1<<(portpin+16*TOUCH_SLOPE); io->CFGLR = CFGFLOAT;
|
#define RELEASEIO \
|
||||||
|
io->BSHR = 1 << (portpin + 16 * TOUCH_SLOPE); \
|
||||||
|
io->CFGLR = CFGFLOAT;
|
||||||
#else
|
#else
|
||||||
#define RELEASEIO io->CFGLR = CFGFLOAT; io->BSHR = 1<<(portpin+16*TOUCH_SLOPE);
|
#define RELEASEIO \
|
||||||
|
io->CFGLR = CFGFLOAT; \
|
||||||
|
io->BSHR = 1 << (portpin + 16 * TOUCH_SLOPE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INNER_LOOP( n ) \
|
#define INNER_LOOP(n) \
|
||||||
{ \
|
{ \
|
||||||
/* Only lock IRQ for a very narrow window. */ \
|
/* Only lock IRQ for a very narrow window. */ \
|
||||||
__disable_irq(); \
|
__disable_irq(); \
|
||||||
|
|
@ -114,28 +114,29 @@ uint32_t ReadTouchPin( GPIO_TypeDef * io, int portpin, int adcno, int iterations
|
||||||
this We are catching it onthe slope much more effectively. */ \
|
this We are catching it onthe slope much more effectively. */ \
|
||||||
ADC1->CTLR2 = ADC_SWSTART | ADC_ADON | ADC_EXTSEL; \
|
ADC1->CTLR2 = ADC_SWSTART | ADC_ADON | ADC_EXTSEL; \
|
||||||
\
|
\
|
||||||
ADD_N_NOPS( n ) \
|
ADD_N_NOPS(n) \
|
||||||
\
|
\
|
||||||
RELEASEIO \
|
RELEASEIO \
|
||||||
\
|
\
|
||||||
/* Sampling actually starts here, somewhere, so we can let other \
|
/* Sampling actually starts here, somewhere, so we can let other \
|
||||||
interrupts run */ \
|
interrupts run */ \
|
||||||
__enable_irq(); \
|
__enable_irq(); \
|
||||||
while(!(ADC1->STATR & ADC_EOC)); \
|
while (!(ADC1->STATR & ADC_EOC)) \
|
||||||
|
; \
|
||||||
io->CFGLR = CFGDRIVE; \
|
io->CFGLR = CFGDRIVE; \
|
||||||
io->BSHR = 1<<(portpin+(16*(1-TOUCH_SLOPE))); \
|
io->BSHR = 1 << (portpin + (16 * (1 - TOUCH_SLOPE))); \
|
||||||
ret += ADC1->RDATAR; \
|
ret += ADC1->RDATAR; \
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for( i = 0; i < iterations; i++ )
|
for (i = 0; i < iterations; i++)
|
||||||
{
|
{
|
||||||
// Wait a variable amount of time based on loop iteration, in order
|
// Wait a variable amount of time based on loop iteration, in order
|
||||||
// to get a variety of RC points and minimize DNL.
|
// to get a variety of RC points and minimize DNL.
|
||||||
|
|
||||||
INNER_LOOP( 0 );
|
INNER_LOOP(0);
|
||||||
INNER_LOOP( 2 );
|
INNER_LOOP(2);
|
||||||
INNER_LOOP( 4 );
|
INNER_LOOP(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
@ -143,18 +144,18 @@ uint32_t ReadTouchPin( GPIO_TypeDef * io, int portpin, int adcno, int iterations
|
||||||
|
|
||||||
// Run from RAM to get even more stable timing.
|
// Run from RAM to get even more stable timing.
|
||||||
// This function call takes about 8.1uS to execute.
|
// This function call takes about 8.1uS to execute.
|
||||||
static uint32_t ReadTouchPinSafe( GPIO_TypeDef * io, int portpin, int adcno, int iterations ) __attribute__((noinline, section(".srodata")));
|
static uint32_t ReadTouchPinSafe(GPIO_TypeDef *io, int portpin, int adcno, int iterations) __attribute__((noinline, section(".srodata")));
|
||||||
uint32_t ReadTouchPinSafe( GPIO_TypeDef * io, int portpin, int adcno, int iterations )
|
uint32_t ReadTouchPinSafe(GPIO_TypeDef *io, int portpin, int adcno, int iterations)
|
||||||
{
|
{
|
||||||
uint32_t ret = 0;
|
uint32_t ret = 0;
|
||||||
|
|
||||||
ADC1->RSQR3 = adcno;
|
ADC1->RSQR3 = adcno;
|
||||||
ADC1->SAMPTR2 = TOUCH_ADC_SAMPLE_TIME<<(3*adcno);
|
ADC1->SAMPTR2 = TOUCH_ADC_SAMPLE_TIME << (3 * adcno);
|
||||||
|
|
||||||
// If we run multiple times with slightly different wait times, we can
|
// If we run multiple times with slightly different wait times, we can
|
||||||
// reduce the impact of the ADC's DNL.
|
// reduce the impact of the ADC's DNL.
|
||||||
|
|
||||||
#define INNER_LOOP_SAFE( n ) \
|
#define INNER_LOOP_SAFE(n) \
|
||||||
{ \
|
{ \
|
||||||
/* Only lock IRQ for a very narrow window. */ \
|
/* Only lock IRQ for a very narrow window. */ \
|
||||||
__disable_irq(); \
|
__disable_irq(); \
|
||||||
|
|
@ -165,37 +166,37 @@ uint32_t ReadTouchPinSafe( GPIO_TypeDef * io, int portpin, int adcno, int iterat
|
||||||
this We are catching it onthe slope much more effectively. */ \
|
this We are catching it onthe slope much more effectively. */ \
|
||||||
ADC1->CTLR2 = ADC_SWSTART | ADC_ADON | ADC_EXTSEL; \
|
ADC1->CTLR2 = ADC_SWSTART | ADC_ADON | ADC_EXTSEL; \
|
||||||
\
|
\
|
||||||
ADD_N_NOPS( n ) \
|
ADD_N_NOPS(n) \
|
||||||
\
|
\
|
||||||
io->CFGLR = ((GPIO_CFGLR_IN_PUPD)<<(4*portpin)) | (io->CFGLR & (~(0xf<<(4*portpin)))); \
|
io->CFGLR = ((GPIO_CFGLR_IN_PUPD) << (4 * portpin)) | (io->CFGLR & (~(0xf << (4 * portpin)))); \
|
||||||
io->BSHR = 1<<(portpin+16*TOUCH_SLOPE); \
|
io->BSHR = 1 << (portpin + 16 * TOUCH_SLOPE); \
|
||||||
\
|
\
|
||||||
/* Sampling actually starts here, somewhere, so we can let other \
|
/* Sampling actually starts here, somewhere, so we can let other \
|
||||||
interrupts run */ \
|
interrupts run */ \
|
||||||
__enable_irq(); \
|
__enable_irq(); \
|
||||||
while(!(ADC1->STATR & ADC_EOC)); \
|
while (!(ADC1->STATR & ADC_EOC)) \
|
||||||
|
; \
|
||||||
__disable_irq(); \
|
__disable_irq(); \
|
||||||
io->CFGLR = (GPIO_CFGLR_OUT_2Mhz_PP)<<(4*portpin) | (io->CFGLR & (~(0xf<<(4*portpin)))); \
|
io->CFGLR = (GPIO_CFGLR_OUT_2Mhz_PP) << (4 * portpin) | (io->CFGLR & (~(0xf << (4 * portpin)))); \
|
||||||
__enable_irq(); \
|
__enable_irq(); \
|
||||||
io->BSHR = 1<<(portpin+(16*(1-TOUCH_SLOPE))); \
|
io->BSHR = 1 << (portpin + (16 * (1 - TOUCH_SLOPE))); \
|
||||||
ret += ADC1->RDATAR; \
|
ret += ADC1->RDATAR; \
|
||||||
}
|
}
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for( i = 0; i < iterations; i++ )
|
for (i = 0; i < iterations; i++)
|
||||||
{
|
{
|
||||||
// Wait a variable amount of time based on loop iteration, in order
|
// Wait a variable amount of time based on loop iteration, in order
|
||||||
// to get a variety of RC points and minimize DNL.
|
// to get a variety of RC points and minimize DNL.
|
||||||
|
|
||||||
INNER_LOOP_SAFE( 0 );
|
INNER_LOOP_SAFE(0);
|
||||||
INNER_LOOP_SAFE( 2 );
|
INNER_LOOP_SAFE(2);
|
||||||
INNER_LOOP_SAFE( 4 );
|
INNER_LOOP_SAFE(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -221,4 +222,3 @@ uint32_t ReadTouchPinSafe( GPIO_TypeDef * io, int portpin, int adcno, int iterat
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
#define _CH32V307GIGABIT_H
|
#define _CH32V307GIGABIT_H
|
||||||
|
|
||||||
/* This file is written against the RTL8211E
|
/* This file is written against the RTL8211E
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// #define CH32V307GIGABIT_MCO25 1
|
// #define CH32V307GIGABIT_MCO25 1
|
||||||
// #define CH32V307GIGABIT_PHYADDRESS 0
|
// #define CH32V307GIGABIT_PHYADDRESS 0
|
||||||
|
|
@ -42,44 +42,43 @@ typedef struct
|
||||||
|
|
||||||
// You must provide:
|
// You must provide:
|
||||||
|
|
||||||
void ch32v307ethHandleReconfig( int link, int speed, int duplex );
|
void ch32v307ethHandleReconfig(int link, int speed, int duplex);
|
||||||
|
|
||||||
// Return non-zero to suppress OWN return (for if you are still holding onto the buffer)
|
// Return non-zero to suppress OWN return (for if you are still holding onto the buffer)
|
||||||
int ch32v307ethInitHandlePacket( uint8_t * data, int frame_length, ETH_DMADESCTypeDef * dmadesc );
|
int ch32v307ethInitHandlePacket(uint8_t *data, int frame_length, ETH_DMADESCTypeDef *dmadesc);
|
||||||
|
|
||||||
void ch32v307ethInitHandleTXC( void );
|
void ch32v307ethInitHandleTXC(void);
|
||||||
|
|
||||||
// This library provides:
|
// This library provides:
|
||||||
static void ch32v307ethGetMacInUC( uint8_t * mac );
|
static void ch32v307ethGetMacInUC(uint8_t *mac);
|
||||||
static int ch32v307ethInit( void );
|
static int ch32v307ethInit(void);
|
||||||
static int ch32v307ethTransmitStatic(uint8_t * buffer, uint32_t length, int enable_txc); // Does not copy.
|
static int ch32v307ethTransmitStatic(uint8_t *buffer, uint32_t length, int enable_txc); // Does not copy.
|
||||||
static int ch32v307ethTickPhy( void );
|
static int ch32v307ethTickPhy(void);
|
||||||
|
|
||||||
// Data pursuent to ethernet.
|
// Data pursuent to ethernet.
|
||||||
uint8_t ch32v307eth_mac[6] = { 0 };
|
uint8_t ch32v307eth_mac[6] = {0};
|
||||||
uint16_t ch32v307eth_phyid = 0; // 0xc916 = RTL8211FS / 0xc915 = RTL8211E-VB
|
uint16_t ch32v307eth_phyid = 0; // 0xc916 = RTL8211FS / 0xc915 = RTL8211E-VB
|
||||||
ETH_DMADESCTypeDef ch32v307eth_DMARxDscrTab[CH32V307GIGABIT_RXBUFNB] __attribute__((aligned(4))); // MAC receive descriptor, 4-byte aligned
|
ETH_DMADESCTypeDef ch32v307eth_DMARxDscrTab[CH32V307GIGABIT_RXBUFNB] __attribute__((aligned(4))); // MAC receive descriptor, 4-byte aligned
|
||||||
ETH_DMADESCTypeDef ch32v307eth_DMATxDscrTab[CH32V307GIGABIT_TXBUFNB] __attribute__((aligned(4))); // MAC send descriptor, 4-byte aligned
|
ETH_DMADESCTypeDef ch32v307eth_DMATxDscrTab[CH32V307GIGABIT_TXBUFNB] __attribute__((aligned(4))); // MAC send descriptor, 4-byte aligned
|
||||||
uint8_t ch32v307eth_MACRxBuf[CH32V307GIGABIT_RXBUFNB*CH32V307GIGABIT_BUFFSIZE] __attribute__((aligned(4))); // MAC receive buffer, 4-byte aligned
|
uint8_t ch32v307eth_MACRxBuf[CH32V307GIGABIT_RXBUFNB * CH32V307GIGABIT_BUFFSIZE] __attribute__((aligned(4))); // MAC receive buffer, 4-byte aligned
|
||||||
ETH_DMADESCTypeDef * pDMARxGet;
|
ETH_DMADESCTypeDef *pDMARxGet;
|
||||||
ETH_DMADESCTypeDef * pDMATxSet;
|
ETH_DMADESCTypeDef *pDMATxSet;
|
||||||
|
|
||||||
|
|
||||||
// Internal functions
|
// Internal functions
|
||||||
static int ch32v307ethPHYRegWrite( uint32_t reg, uint32_t val );
|
static int ch32v307ethPHYRegWrite(uint32_t reg, uint32_t val);
|
||||||
static int ch32v307ethPHYRegAsyncRead( int reg, int * value );
|
static int ch32v307ethPHYRegAsyncRead(int reg, int *value);
|
||||||
static int ch32v307ethPHYRegRead( uint32_t reg );
|
static int ch32v307ethPHYRegRead(uint32_t reg);
|
||||||
|
|
||||||
static int ch32v307ethPHYRegAsyncRead( int reg, int * value )
|
static int ch32v307ethPHYRegAsyncRead(int reg, int *value)
|
||||||
{
|
{
|
||||||
static uint8_t reg_request_count = 0;
|
static uint8_t reg_request_count = 0;
|
||||||
|
|
||||||
uint32_t miiar = ETH->MACMIIAR;
|
uint32_t miiar = ETH->MACMIIAR;
|
||||||
if( miiar & ETH_MACMIIAR_MB )
|
if (miiar & ETH_MACMIIAR_MB)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if( ( ( miiar & ETH_MACMIIAR_MR ) >> 6 ) != reg || reg_request_count < 2 )
|
if (((miiar & ETH_MACMIIAR_MR) >> 6) != reg || reg_request_count < 2)
|
||||||
{
|
{
|
||||||
ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42 /* = 0, per 27.1.8.1.4 */ |
|
ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42 /* = 0, per 27.1.8.1.4 */ |
|
||||||
((uint32_t)CH32V307GIGABIT_PHYADDRESS << 11) | // ETH_MACMIIAR_PA
|
((uint32_t)CH32V307GIGABIT_PHYADDRESS << 11) | // ETH_MACMIIAR_PA
|
||||||
|
|
@ -99,41 +98,40 @@ static int ch32v307ethTickPhy(void)
|
||||||
int speed, linked, duplex;
|
int speed, linked, duplex;
|
||||||
const int reg = (ch32v307eth_phyid == 0xc916) ? 0x1a : 0x11; // PHYSR (different on each part)
|
const int reg = (ch32v307eth_phyid == 0xc916) ? 0x1a : 0x11; // PHYSR (different on each part)
|
||||||
int miidr;
|
int miidr;
|
||||||
if( ch32v307ethPHYRegAsyncRead( reg, &miidr ) ) return -1;
|
if (ch32v307ethPHYRegAsyncRead(reg, &miidr)) return -1;
|
||||||
|
|
||||||
printf( "REG: %02x / %04x / %04x\n", reg, miidr, ch32v307eth_phyid );
|
printf("REG: %02x / %04x / %04x\n", reg, miidr, ch32v307eth_phyid);
|
||||||
|
|
||||||
if( reg == 0x1a )
|
if (reg == 0x1a)
|
||||||
{
|
{
|
||||||
speed = ((miidr>>4)&3);
|
speed = ((miidr >> 4) & 3);
|
||||||
linked = ((miidr>>2)&1);
|
linked = ((miidr >> 2) & 1);
|
||||||
duplex = ((miidr>>3)&1);
|
duplex = ((miidr >> 3) & 1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
speed = ((miidr>>14)&3);
|
speed = ((miidr >> 14) & 3);
|
||||||
linked = ((miidr>>10)&1);
|
linked = ((miidr >> 10) & 1);
|
||||||
duplex = ((miidr>>13)&1);
|
duplex = ((miidr >> 13) & 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf( "LINK INFO: %d %d %d\n", speed, linked, duplex );
|
printf("LINK INFO: %d %d %d\n", speed, linked, duplex);
|
||||||
if( linked )
|
if (linked)
|
||||||
{
|
{
|
||||||
uint32_t oldmaccr = ETH->MACCR;
|
uint32_t oldmaccr = ETH->MACCR;
|
||||||
uint32_t newmaccr = (oldmaccr & ~( ( 1<<11 ) | (3<<14) ) ) | (speed<<14) | ( duplex<<11);
|
uint32_t newmaccr = (oldmaccr & ~((1 << 11) | (3 << 14))) | (speed << 14) | (duplex << 11);
|
||||||
if( newmaccr != oldmaccr )
|
if (newmaccr != oldmaccr)
|
||||||
{
|
{
|
||||||
ETH->MACCR = newmaccr;
|
ETH->MACCR = newmaccr;
|
||||||
ch32v307ethHandleReconfig( linked, speed, duplex );
|
ch32v307ethHandleReconfig(linked, speed, duplex);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Based on ETH_WritePHYRegister
|
// Based on ETH_WritePHYRegister
|
||||||
static int ch32v307ethPHYRegWrite( uint32_t reg, uint32_t val )
|
static int ch32v307ethPHYRegWrite(uint32_t reg, uint32_t val)
|
||||||
{
|
{
|
||||||
ETH->MACMIIDR = val;
|
ETH->MACMIIDR = val;
|
||||||
ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42 /* = 0, per 27.1.8.1.4 */ |
|
ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42 /* = 0, per 27.1.8.1.4 */ |
|
||||||
|
|
@ -142,13 +140,14 @@ static int ch32v307ethPHYRegWrite( uint32_t reg, uint32_t val )
|
||||||
ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
|
ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
|
||||||
|
|
||||||
uint32_t timeout = 0x100000;
|
uint32_t timeout = 0x100000;
|
||||||
while( ( ETH->MACMIIAR & ETH_MACMIIAR_MB ) && --timeout );
|
while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) && --timeout)
|
||||||
|
;
|
||||||
|
|
||||||
// If timeout = 0, is an error.
|
// If timeout = 0, is an error.
|
||||||
return timeout ? 0 : -1;
|
return timeout ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ch32v307ethPHYRegRead( uint32_t reg )
|
static int ch32v307ethPHYRegRead(uint32_t reg)
|
||||||
{
|
{
|
||||||
ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42 /* = 0, per 27.1.8.1.4 */ |
|
ETH->MACMIIAR = ETH_MACMIIAR_CR_Div42 /* = 0, per 27.1.8.1.4 */ |
|
||||||
((uint32_t)CH32V307GIGABIT_PHYADDRESS << 11) | // ETH_MACMIIAR_PA
|
((uint32_t)CH32V307GIGABIT_PHYADDRESS << 11) | // ETH_MACMIIAR_PA
|
||||||
|
|
@ -156,45 +155,45 @@ static int ch32v307ethPHYRegRead( uint32_t reg )
|
||||||
(0 /*!ETH_MACMIIAR_MW*/) | ETH_MACMIIAR_MB;
|
(0 /*!ETH_MACMIIAR_MW*/) | ETH_MACMIIAR_MB;
|
||||||
|
|
||||||
uint32_t timeout = 0x100000;
|
uint32_t timeout = 0x100000;
|
||||||
while( ( ETH->MACMIIAR & ETH_MACMIIAR_MB ) && --timeout );
|
while ((ETH->MACMIIAR & ETH_MACMIIAR_MB) && --timeout)
|
||||||
|
;
|
||||||
|
|
||||||
// If timeout = 0, is an error.
|
// If timeout = 0, is an error.
|
||||||
return timeout ? ETH->MACMIIDR : -1;
|
return timeout ? ETH->MACMIIDR : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ch32v307ethGetMacInUC(uint8_t *mac)
|
||||||
static void ch32v307ethGetMacInUC( uint8_t * mac )
|
|
||||||
{
|
{
|
||||||
// Mac is backwards.
|
// Mac is backwards.
|
||||||
const uint8_t *macaddr = (const uint8_t *)(ROM_CFG_USERADR_ID+5);
|
const uint8_t *macaddr = (const uint8_t *)(ROM_CFG_USERADR_ID + 5);
|
||||||
for( int i = 0; i < 6; i++ )
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
mac[i] = *(macaddr--);
|
mac[i] = *(macaddr--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ch32v307ethInit( void )
|
static int ch32v307ethInit(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef CH32V307GIGABIT_PHY_RSTB
|
#ifdef CH32V307GIGABIT_PHY_RSTB
|
||||||
funPinMode( CH32V307GIGABIT_PHY_RSTB, GPIO_CFGLR_OUT_50Mhz_PP ); //PHY_RSTB (For reset)
|
funPinMode(CH32V307GIGABIT_PHY_RSTB, GPIO_CFGLR_OUT_50Mhz_PP); // PHY_RSTB (For reset)
|
||||||
funDigitalWrite( CH32V307GIGABIT_PHY_RSTB, FUN_LOW );
|
funDigitalWrite(CH32V307GIGABIT_PHY_RSTB, FUN_LOW);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Configure strapping.
|
// Configure strapping.
|
||||||
funPinMode( PA1, GPIO_CFGLR_IN_PUPD ); // GMII_RXD3
|
funPinMode(PA1, GPIO_CFGLR_IN_PUPD); // GMII_RXD3
|
||||||
funPinMode( PA0, GPIO_CFGLR_IN_PUPD ); // GMII_RXD2
|
funPinMode(PA0, GPIO_CFGLR_IN_PUPD); // GMII_RXD2
|
||||||
funPinMode( PC3, GPIO_CFGLR_IN_PUPD ); // GMII_RXD1
|
funPinMode(PC3, GPIO_CFGLR_IN_PUPD); // GMII_RXD1
|
||||||
funPinMode( PC2, GPIO_CFGLR_IN_PUPD ); // GMII_RXD0
|
funPinMode(PC2, GPIO_CFGLR_IN_PUPD); // GMII_RXD0
|
||||||
funDigitalWrite( PA1, FUN_HIGH );
|
funDigitalWrite(PA1, FUN_HIGH);
|
||||||
funDigitalWrite( PA0, FUN_HIGH );
|
funDigitalWrite(PA0, FUN_HIGH);
|
||||||
funDigitalWrite( PC3, FUN_HIGH ); // No TX Delay
|
funDigitalWrite(PC3, FUN_HIGH); // No TX Delay
|
||||||
funDigitalWrite( PC2, FUN_HIGH );
|
funDigitalWrite(PC2, FUN_HIGH);
|
||||||
|
|
||||||
// Pull-up MDIO
|
// Pull-up MDIO
|
||||||
funPinMode( PD9, GPIO_CFGLR_OUT_50Mhz_PP ); //Pull-up control (DO NOT CHECK IN, ADD RESISTOR)
|
funPinMode(PD9, GPIO_CFGLR_OUT_50Mhz_PP); // Pull-up control (DO NOT CHECK IN, ADD RESISTOR)
|
||||||
funDigitalWrite( PD9, FUN_HIGH );
|
funDigitalWrite(PD9, FUN_HIGH);
|
||||||
|
|
||||||
// Will be required later.
|
// Will be required later.
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_AFIO;
|
RCC->APB2PCENR |= RCC_APB2Periph_AFIO;
|
||||||
|
|
@ -218,88 +217,91 @@ static int ch32v307ethInit( void )
|
||||||
|
|
||||||
// Setup clock tree.
|
// Setup clock tree.
|
||||||
RCC->CFGR2 |=
|
RCC->CFGR2 |=
|
||||||
(1<<RCC_PREDIV2_OFFSET) | // PREDIV = /2; Prediv Freq = 4MHz
|
(1 << RCC_PREDIV2_OFFSET) | // PREDIV = /2; Prediv Freq = 4MHz
|
||||||
(1<<RCC_PLL3MUL_OFFSET) | // PLL3 = x12.5 (PLL3 = 50MHz)
|
(1 << RCC_PLL3MUL_OFFSET) | // PLL3 = x12.5 (PLL3 = 50MHz)
|
||||||
(2<<RCC_ETH1GSRC_OFFSET)| // External source for RGMII
|
(2 << RCC_ETH1GSRC_OFFSET) | // External source for RGMII
|
||||||
(7<<RCC_PLL2MUL_OFFSET) | // PLL2 = x9 (PLL2 = 36MHz)
|
(7 << RCC_PLL2MUL_OFFSET) | // PLL2 = x9 (PLL2 = 36MHz)
|
||||||
(1<<RCC_PREDIV1_OFFSET) | // PREDIV1 = /2; Prediv freq = 50MHz
|
(1 << RCC_PREDIV1_OFFSET) | // PREDIV1 = /2; Prediv freq = 50MHz
|
||||||
0;
|
0;
|
||||||
|
|
||||||
// Power on PLLs
|
// Power on PLLs
|
||||||
RCC->CTLR |= RCC_PLL3ON | RCC_PLL2ON;
|
RCC->CTLR |= RCC_PLL3ON | RCC_PLL2ON;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
|
||||||
for( timeout = 10000; timeout > 0; timeout--) if (RCC->CTLR & RCC_PLL3RDY) break;
|
for (timeout = 10000; timeout > 0; timeout--)
|
||||||
if( timeout == 0 ) return -5;
|
if (RCC->CTLR & RCC_PLL3RDY) break;
|
||||||
for( timeout = 10000; timeout > 0; timeout--) if (RCC->CTLR & RCC_PLL2RDY) break;
|
if (timeout == 0) return -5;
|
||||||
if( timeout == 0 ) return -6;
|
for (timeout = 10000; timeout > 0; timeout--)
|
||||||
|
if (RCC->CTLR & RCC_PLL2RDY) break;
|
||||||
|
if (timeout == 0) return -6;
|
||||||
|
|
||||||
// PLL = x18 (0 in register)
|
// PLL = x18 (0 in register)
|
||||||
RCC->CFGR0 = ( RCC->CFGR0 & ~(0xf<<18)) | 0;
|
RCC->CFGR0 = (RCC->CFGR0 & ~(0xf << 18)) | 0;
|
||||||
RCC->CTLR |= RCC_PLLON;
|
RCC->CTLR |= RCC_PLLON;
|
||||||
|
|
||||||
for( timeout = 10000; timeout > 0; timeout--) if (RCC->CTLR & RCC_PLLRDY) break;
|
for (timeout = 10000; timeout > 0; timeout--)
|
||||||
if( timeout == 0 ) return -7;
|
if (RCC->CTLR & RCC_PLLRDY) break;
|
||||||
|
if (timeout == 0) return -7;
|
||||||
|
|
||||||
// Switch to PLL.
|
// Switch to PLL.
|
||||||
#ifdef CH32V307GIGABIT_MCO25
|
#ifdef CH32V307GIGABIT_MCO25
|
||||||
RCC->CFGR0 = (RCC->CFGR0 & ~RCC_SW) | RCC_SW_PLL | (9<<24); // And output clock on PA8
|
RCC->CFGR0 = (RCC->CFGR0 & ~RCC_SW) | RCC_SW_PLL | (9 << 24); // And output clock on PA8
|
||||||
#else
|
#else
|
||||||
RCC->CFGR0 = (RCC->CFGR0 & ~RCC_SW) | RCC_SW_PLL;
|
RCC->CFGR0 = (RCC->CFGR0 & ~RCC_SW) | RCC_SW_PLL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For clock in.
|
// For clock in.
|
||||||
funPinMode( PB1, GPIO_CFGLR_IN_FLOAT ); //GMII_CLK125
|
funPinMode(PB1, GPIO_CFGLR_IN_FLOAT); // GMII_CLK125
|
||||||
|
|
||||||
RCC->CFGR2 |= RCC_ETH1G_125M_EN; // Enable 125MHz clock.
|
RCC->CFGR2 |= RCC_ETH1G_125M_EN; // Enable 125MHz clock.
|
||||||
|
|
||||||
// Power on and reset.
|
// Power on and reset.
|
||||||
RCC->AHBPCENR |= RCC_ETHMACEN | RCC_ETHMACTXEN | RCC_ETHMACRXEN;
|
RCC->AHBPCENR |= RCC_ETHMACEN | RCC_ETHMACTXEN | RCC_ETHMACRXEN;
|
||||||
RCC->AHBRSTR |= RCC_ETHMACRST;
|
RCC->AHBRSTR |= RCC_ETHMACRST;
|
||||||
RCC->AHBRSTR &=~RCC_ETHMACRST;
|
RCC->AHBRSTR &= ~RCC_ETHMACRST;
|
||||||
|
|
||||||
ETH->DMABMR |= ETH_DMABMR_SR;
|
ETH->DMABMR |= ETH_DMABMR_SR;
|
||||||
|
|
||||||
// Wait for reset to complete.
|
// Wait for reset to complete.
|
||||||
for( timeout = 10000; timeout > 0 && (ETH->DMABMR & ETH_DMABMR_SR); timeout-- )
|
for (timeout = 10000; timeout > 0 && (ETH->DMABMR & ETH_DMABMR_SR); timeout--)
|
||||||
{
|
{
|
||||||
Delay_Us(10);
|
Delay_Us(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use RGMII
|
// Use RGMII
|
||||||
EXTEN->EXTEN_CTR |= EXTEN_ETH_RGMII_SEL; //EXTEN_ETH_RGMII_SEL;
|
EXTEN->EXTEN_CTR |= EXTEN_ETH_RGMII_SEL; // EXTEN_ETH_RGMII_SEL;
|
||||||
|
|
||||||
funPinMode( PB13, GPIO_CFGLR_OUT_50Mhz_AF_PP ); //GMII_MDIO
|
funPinMode(PB13, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_MDIO
|
||||||
funPinMode( PB12, GPIO_CFGLR_OUT_50Mhz_AF_PP ); //GMII_MDC
|
funPinMode(PB12, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_MDC
|
||||||
|
|
||||||
// For clock output to Ethernet module.
|
// For clock output to Ethernet module.
|
||||||
funPinMode( PA8, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // PHY_CKTAL
|
funPinMode(PA8, GPIO_CFGLR_OUT_50Mhz_AF_PP); // PHY_CKTAL
|
||||||
|
|
||||||
// Release PHY from reset.
|
// Release PHY from reset.
|
||||||
#ifdef CH32V307GIGABIT_PHY_RSTB
|
#ifdef CH32V307GIGABIT_PHY_RSTB
|
||||||
funDigitalWrite( CH32V307GIGABIT_PHY_RSTB, FUN_HIGH );
|
funDigitalWrite(CH32V307GIGABIT_PHY_RSTB, FUN_HIGH);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Delay_Ms(25); // Waiting for PHY to exit sleep. This is inconsistent at 23ms (But only on the RTL8211FS) None is needed on the RTL8211E
|
Delay_Ms(25); // Waiting for PHY to exit sleep. This is inconsistent at 23ms (But only on the RTL8211FS) None is needed on the RTL8211E
|
||||||
|
|
||||||
funPinMode( PB0, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // GMII_TXD3
|
funPinMode(PB0, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_TXD3
|
||||||
funPinMode( PC5, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // GMII_TXD2
|
funPinMode(PC5, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_TXD2
|
||||||
funPinMode( PC4, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // GMII_TXD1
|
funPinMode(PC4, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_TXD1
|
||||||
funPinMode( PA7, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // GMII_TXD0
|
funPinMode(PA7, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_TXD0
|
||||||
funPinMode( PA3, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // GMII_TXCTL
|
funPinMode(PA3, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_TXCTL
|
||||||
funPinMode( PA2, GPIO_CFGLR_OUT_50Mhz_AF_PP ); // GMII_TXC
|
funPinMode(PA2, GPIO_CFGLR_OUT_50Mhz_AF_PP); // GMII_TXC
|
||||||
funPinMode( PA1, GPIO_CFGLR_IN_PUPD ); // GMII_RXD3
|
funPinMode(PA1, GPIO_CFGLR_IN_PUPD); // GMII_RXD3
|
||||||
funPinMode( PA0, GPIO_CFGLR_IN_PUPD ); // GMII_RXD2
|
funPinMode(PA0, GPIO_CFGLR_IN_PUPD); // GMII_RXD2
|
||||||
funPinMode( PC3, GPIO_CFGLR_IN_PUPD ); // GMII_RXD1
|
funPinMode(PC3, GPIO_CFGLR_IN_PUPD); // GMII_RXD1
|
||||||
funPinMode( PC2, GPIO_CFGLR_IN_PUPD ); // GMII_RXD0
|
funPinMode(PC2, GPIO_CFGLR_IN_PUPD); // GMII_RXD0
|
||||||
funPinMode( PC1, GPIO_CFGLR_IN_PUPD ); // GMII_RXCTL
|
funPinMode(PC1, GPIO_CFGLR_IN_PUPD); // GMII_RXCTL
|
||||||
funPinMode( PC0, GPIO_CFGLR_IN_FLOAT ); // GMII_RXC
|
funPinMode(PC0, GPIO_CFGLR_IN_FLOAT); // GMII_RXC
|
||||||
|
|
||||||
funDigitalWrite( PA1, FUN_HIGH ); // SELGRV = 3.3V
|
funDigitalWrite(PA1, FUN_HIGH); // SELGRV = 3.3V
|
||||||
funDigitalWrite( PA0, FUN_HIGH ); // TXDelay = 1
|
funDigitalWrite(PA0, FUN_HIGH); // TXDelay = 1
|
||||||
funDigitalWrite( PC3, FUN_HIGH ); // AN[0] = 1
|
funDigitalWrite(PC3, FUN_HIGH); // AN[0] = 1
|
||||||
funDigitalWrite( PC2, FUN_HIGH ); // AN[1] = 1
|
funDigitalWrite(PC2, FUN_HIGH); // AN[1] = 1
|
||||||
funDigitalWrite( PC1, FUN_LOW ); // PHYAD[0]
|
funDigitalWrite(PC1, FUN_LOW); // PHYAD[0]
|
||||||
|
|
||||||
// Configure MDC/MDIO
|
// Configure MDC/MDIO
|
||||||
// Conflicting notes - some say /42, others don't.
|
// Conflicting notes - some say /42, others don't.
|
||||||
|
|
@ -307,48 +309,48 @@ static int ch32v307ethInit( void )
|
||||||
|
|
||||||
// Update MACCR
|
// Update MACCR
|
||||||
ETH->MACCR =
|
ETH->MACCR =
|
||||||
( CH32V307GIGABIT_CFG_CLOCK_DELAY << 29 ) | // No clock delay
|
(CH32V307GIGABIT_CFG_CLOCK_DELAY << 29) | // No clock delay
|
||||||
( 0 << 23 ) | // Max RX = 2kB (Revisit if looking into jumbo frames)
|
(0 << 23) | // Max RX = 2kB (Revisit if looking into jumbo frames)
|
||||||
( 0 << 22 ) | // Max TX = 2kB (Revisit if looking into jumbo frames)
|
(0 << 22) | // Max TX = 2kB (Revisit if looking into jumbo frames)
|
||||||
( 0 << 21 ) | // Rated Drive (instead of energy savings mode) (10M PHY only)
|
(0 << 21) | // Rated Drive (instead of energy savings mode) (10M PHY only)
|
||||||
( 1 << 20 ) | // Bizarre re-use of termination resistor terminology? (10M PHY Only)
|
(1 << 20) | // Bizarre re-use of termination resistor terminology? (10M PHY Only)
|
||||||
( 0 << 17 ) | // IFG = 0, 96-bit guard time.
|
(0 << 17) | // IFG = 0, 96-bit guard time.
|
||||||
( 0 << 14 ) | // FES = 2 = GBE, 1=100MBit/s (UNSET TO START)
|
(0 << 14) | // FES = 2 = GBE, 1=100MBit/s (UNSET TO START)
|
||||||
( 0 << 12 ) | // Self Loop = 0
|
(0 << 12) | // Self Loop = 0
|
||||||
( 0 << 11 ) | // Full-Duplex Mode (UNSET TO START)
|
(0 << 11) | // Full-Duplex Mode (UNSET TO START)
|
||||||
( 1 << 10 ) | // IPCO = 1, Check TCP, UDP, ICMP header checksums.
|
(1 << 10) | // IPCO = 1, Check TCP, UDP, ICMP header checksums.
|
||||||
( 1 << 7 ) | // APCS (automatically strip frames)
|
(1 << 7) | // APCS (automatically strip frames)
|
||||||
( 1 << 3 ) | // TE (Transmit enable!)
|
(1 << 3) | // TE (Transmit enable!)
|
||||||
( 1 << 2 ) | // RE (Receive Enable)
|
(1 << 2) | // RE (Receive Enable)
|
||||||
( CH32V307GIGABIT_CFG_CLOCK_PHASE << 1 ) | // TCF = 0 (Potentailly change if clocking is wrong)
|
(CH32V307GIGABIT_CFG_CLOCK_PHASE << 1) | // TCF = 0 (Potentailly change if clocking is wrong)
|
||||||
0;
|
0;
|
||||||
|
|
||||||
Delay_Ms(25); // Waiting for PHY to exit sleep. This is inconsistent at 19ms.
|
Delay_Ms(25); // Waiting for PHY to exit sleep. This is inconsistent at 19ms.
|
||||||
|
|
||||||
// Reset the physical layer
|
// Reset the physical layer
|
||||||
ch32v307ethPHYRegWrite( PHY_BCR,
|
ch32v307ethPHYRegWrite(PHY_BCR,
|
||||||
PHY_Reset |
|
PHY_Reset |
|
||||||
1<<12 | // Auto negotiate
|
1 << 12 | // Auto negotiate
|
||||||
1<<8 | // Duplex
|
1 << 8 | // Duplex
|
||||||
1<<6 | // Speed Bit.
|
1 << 6 | // Speed Bit.
|
||||||
0 );
|
0);
|
||||||
|
|
||||||
// De-assert reset.
|
// De-assert reset.
|
||||||
ch32v307ethPHYRegWrite( PHY_BCR,
|
ch32v307ethPHYRegWrite(PHY_BCR,
|
||||||
1<<12 | // Auto negotiate
|
1 << 12 | // Auto negotiate
|
||||||
1<<8 | // Duplex
|
1 << 8 | // Duplex
|
||||||
1<<6 | // Speed Bit.
|
1 << 6 | // Speed Bit.
|
||||||
0 );
|
0);
|
||||||
|
|
||||||
ch32v307ethPHYRegRead( 0x03 );
|
ch32v307ethPHYRegRead(0x03);
|
||||||
ch32v307eth_phyid = ch32v307ethPHYRegRead( 0x03 ); // Read twice to be safe.
|
ch32v307eth_phyid = ch32v307ethPHYRegRead(0x03); // Read twice to be safe.
|
||||||
if( ch32v307eth_phyid == 0xc916 )
|
if (ch32v307eth_phyid == 0xc916)
|
||||||
ch32v307ethPHYRegWrite( 0x1F, 0x0a43 ); // RTL8211FS needs page select.
|
ch32v307ethPHYRegWrite(0x1F, 0x0a43); // RTL8211FS needs page select.
|
||||||
|
|
||||||
ch32v307ethGetMacInUC( ch32v307eth_mac );
|
ch32v307ethGetMacInUC(ch32v307eth_mac);
|
||||||
|
|
||||||
ETH->MACA0HR = (uint32_t)((ch32v307eth_mac[5]<<8) | ch32v307eth_mac[4]);
|
ETH->MACA0HR = (uint32_t)((ch32v307eth_mac[5] << 8) | ch32v307eth_mac[4]);
|
||||||
ETH->MACA0LR = (uint32_t)(ch32v307eth_mac[0] | (ch32v307eth_mac[1]<<8) | (ch32v307eth_mac[2]<<16) | (ch32v307eth_mac[3]<<24));
|
ETH->MACA0LR = (uint32_t)(ch32v307eth_mac[0] | (ch32v307eth_mac[1] << 8) | (ch32v307eth_mac[2] << 16) | (ch32v307eth_mac[3] << 24));
|
||||||
|
|
||||||
ETH->MACFFR = (uint32_t)(ETH_ReceiveAll_Disable |
|
ETH->MACFFR = (uint32_t)(ETH_ReceiveAll_Disable |
|
||||||
ETH_SourceAddrFilter_Disable |
|
ETH_SourceAddrFilter_Disable |
|
||||||
|
|
@ -367,7 +369,7 @@ static int ch32v307ethInit( void )
|
||||||
|
|
||||||
// Configure RX/TX chains.
|
// Configure RX/TX chains.
|
||||||
ETH_DMADESCTypeDef *tdesc;
|
ETH_DMADESCTypeDef *tdesc;
|
||||||
for(i = 0; i < CH32V307GIGABIT_TXBUFNB; i++)
|
for (i = 0; i < CH32V307GIGABIT_TXBUFNB; i++)
|
||||||
{
|
{
|
||||||
tdesc = ch32v307eth_DMATxDscrTab + i;
|
tdesc = ch32v307eth_DMATxDscrTab + i;
|
||||||
tdesc->ControlBufferSize = 0;
|
tdesc->ControlBufferSize = 0;
|
||||||
|
|
@ -376,7 +378,7 @@ static int ch32v307ethInit( void )
|
||||||
tdesc->Buffer2NextDescAddr = (i < CH32V307GIGABIT_TXBUFNB - 1) ? ((uint32_t)(ch32v307eth_DMATxDscrTab + i + 1)) : (uint32_t)ch32v307eth_DMATxDscrTab;
|
tdesc->Buffer2NextDescAddr = (i < CH32V307GIGABIT_TXBUFNB - 1) ? ((uint32_t)(ch32v307eth_DMATxDscrTab + i + 1)) : (uint32_t)ch32v307eth_DMATxDscrTab;
|
||||||
}
|
}
|
||||||
ETH->DMATDLAR = (uint32_t)ch32v307eth_DMATxDscrTab;
|
ETH->DMATDLAR = (uint32_t)ch32v307eth_DMATxDscrTab;
|
||||||
for(i = 0; i < CH32V307GIGABIT_RXBUFNB; i++)
|
for (i = 0; i < CH32V307GIGABIT_RXBUFNB; i++)
|
||||||
{
|
{
|
||||||
tdesc = ch32v307eth_DMARxDscrTab + i;
|
tdesc = ch32v307eth_DMARxDscrTab + i;
|
||||||
tdesc->Status = ETH_DMARxDesc_OWN;
|
tdesc->Status = ETH_DMARxDesc_OWN;
|
||||||
|
|
@ -401,7 +403,7 @@ static int ch32v307ethInit( void )
|
||||||
ETH_DMA_IT_AIS | // Abnormal interrupt
|
ETH_DMA_IT_AIS | // Abnormal interrupt
|
||||||
ETH_DMA_IT_RBU; // Receive buffer unavailable interrupt enable
|
ETH_DMA_IT_RBU; // Receive buffer unavailable interrupt enable
|
||||||
|
|
||||||
NVIC_EnableIRQ( ETH_IRQn );
|
NVIC_EnableIRQ(ETH_IRQn);
|
||||||
|
|
||||||
// Actually enable receiving process.
|
// Actually enable receiving process.
|
||||||
ETH->DMAOMR = ETH_DMAOMR_SR | ETH_DMAOMR_ST | ETH_DMAOMR_TSF | ETH_DMAOMR_FEF;
|
ETH->DMAOMR = ETH_DMAOMR_SR | ETH_DMAOMR_ST | ETH_DMAOMR_TSF | ETH_DMAOMR_FEF;
|
||||||
|
|
@ -409,15 +411,15 @@ static int ch32v307ethInit( void )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ETH_IRQHandler( void ) __attribute__((interrupt));
|
void ETH_IRQHandler(void) __attribute__((interrupt));
|
||||||
void ETH_IRQHandler( void )
|
void ETH_IRQHandler(void)
|
||||||
{
|
{
|
||||||
uint32_t int_sta;
|
uint32_t int_sta;
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
int_sta = ETH->DMASR;
|
int_sta = ETH->DMASR;
|
||||||
if ( ( int_sta & ( ETH_DMA_IT_AIS | ETH_DMA_IT_NIS ) ) == 0 )
|
if ((int_sta & (ETH_DMA_IT_AIS | ETH_DMA_IT_NIS)) == 0)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -429,7 +431,7 @@ void ETH_IRQHandler( void )
|
||||||
if (int_sta & ETH_DMA_IT_RBU)
|
if (int_sta & ETH_DMA_IT_RBU)
|
||||||
{
|
{
|
||||||
ETH->DMASR = ETH_DMA_IT_RBU;
|
ETH->DMASR = ETH_DMA_IT_RBU;
|
||||||
if((INFO->CHIPID & 0xf0) == 0x10)
|
if ((INFO->CHIPID & 0xf0) == 0x10)
|
||||||
{
|
{
|
||||||
((ETH_DMADESCTypeDef *)(((ETH_DMADESCTypeDef *)(ETH->DMACHRDR))->Buffer2NextDescAddr))->Status = ETH_DMARxDesc_OWN;
|
((ETH_DMADESCTypeDef *)(((ETH_DMADESCTypeDef *)(ETH->DMACHRDR))->Buffer2NextDescAddr))->Status = ETH_DMARxDesc_OWN;
|
||||||
ETH->DMARPDR = 0;
|
ETH->DMARPDR = 0;
|
||||||
|
|
@ -439,9 +441,9 @@ void ETH_IRQHandler( void )
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nominal interrupts.
|
// Nominal interrupts.
|
||||||
if( int_sta & ETH_DMA_IT_NIS )
|
if (int_sta & ETH_DMA_IT_NIS)
|
||||||
{
|
{
|
||||||
if( int_sta & ETH_DMA_IT_R )
|
if (int_sta & ETH_DMA_IT_R)
|
||||||
{
|
{
|
||||||
// Received a packet, normally.
|
// Received a packet, normally.
|
||||||
// Status is in Table 27-17 Definitions of RDes0
|
// Status is in Table 27-17 Definitions of RDes0
|
||||||
|
|
@ -452,7 +454,7 @@ void ETH_IRQHandler( void )
|
||||||
ETH->DMASR = ETH_DMA_IT_R;
|
ETH->DMASR = ETH_DMA_IT_R;
|
||||||
|
|
||||||
uint32_t status = pDMARxGet->Status;
|
uint32_t status = pDMARxGet->Status;
|
||||||
if( status & ETH_DMARxDesc_OWN ) break;
|
if (status & ETH_DMARxDesc_OWN) break;
|
||||||
|
|
||||||
// We only have a valid packet in a specific situation.
|
// We only have a valid packet in a specific situation.
|
||||||
// So, we take the status, then mask off the bits we care about
|
// So, we take the status, then mask off the bits we care about
|
||||||
|
|
@ -470,45 +472,45 @@ void ETH_IRQHandler( void )
|
||||||
|
|
||||||
int suppress_own = 0;
|
int suppress_own = 0;
|
||||||
|
|
||||||
if( ( status & mask ) == eq )
|
if ((status & mask) == eq)
|
||||||
{
|
{
|
||||||
int32_t frame_length = ((status & ETH_DMARxDesc_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4;
|
int32_t frame_length = ((status & ETH_DMARxDesc_FL) >> ETH_DMARXDESC_FRAME_LENGTHSHIFT) - 4;
|
||||||
if( frame_length > 0 )
|
if (frame_length > 0)
|
||||||
{
|
{
|
||||||
uint8_t * data = (uint8_t*)pDMARxGet->Buffer1Addr;
|
uint8_t *data = (uint8_t *)pDMARxGet->Buffer1Addr;
|
||||||
suppress_own = ch32v307ethInitHandlePacket( data, frame_length, pDMARxGet );
|
suppress_own = ch32v307ethInitHandlePacket(data, frame_length, pDMARxGet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Otherwise, Invalid Packet
|
// Otherwise, Invalid Packet
|
||||||
|
|
||||||
// Relinquish control back to underlying hardware.
|
// Relinquish control back to underlying hardware.
|
||||||
if( !suppress_own )
|
if (!suppress_own)
|
||||||
pDMARxGet->Status = ETH_DMARxDesc_OWN;
|
pDMARxGet->Status = ETH_DMARxDesc_OWN;
|
||||||
|
|
||||||
// Tricky logic for figuring out the next packet. Originally
|
// Tricky logic for figuring out the next packet. Originally
|
||||||
// discussed in ch32v30x_eth.c in ETH_DropRxPkt
|
// discussed in ch32v30x_eth.c in ETH_DropRxPkt
|
||||||
if((pDMARxGet->ControlBufferSize & ETH_DMARxDesc_RCH) != (uint32_t)RESET)
|
if ((pDMARxGet->ControlBufferSize & ETH_DMARxDesc_RCH) != (uint32_t)RESET)
|
||||||
pDMARxGet = (ETH_DMADESCTypeDef *)(pDMARxGet->Buffer2NextDescAddr);
|
pDMARxGet = (ETH_DMADESCTypeDef *)(pDMARxGet->Buffer2NextDescAddr);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if((pDMARxGet->ControlBufferSize & ETH_DMARxDesc_RER) != (uint32_t)RESET)
|
if ((pDMARxGet->ControlBufferSize & ETH_DMARxDesc_RER) != (uint32_t)RESET)
|
||||||
pDMARxGet = (ETH_DMADESCTypeDef *)(ETH->DMARDLAR);
|
pDMARxGet = (ETH_DMADESCTypeDef *)(ETH->DMARDLAR);
|
||||||
else
|
else
|
||||||
pDMARxGet = (ETH_DMADESCTypeDef *)((uint32_t)pDMARxGet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2));
|
pDMARxGet = (ETH_DMADESCTypeDef *)((uint32_t)pDMARxGet + 0x10 + ((ETH->DMABMR & ETH_DMABMR_DSL) >> 2));
|
||||||
}
|
}
|
||||||
} while( 1 );
|
} while (1);
|
||||||
}
|
}
|
||||||
if( int_sta & ETH_DMA_IT_T )
|
if (int_sta & ETH_DMA_IT_T)
|
||||||
{
|
{
|
||||||
ch32v307ethInitHandleTXC();
|
ch32v307ethInitHandleTXC();
|
||||||
ETH->DMASR = ETH_DMA_IT_T;
|
ETH->DMASR = ETH_DMA_IT_T;
|
||||||
}
|
}
|
||||||
ETH->DMASR = ETH_DMA_IT_NIS;
|
ETH->DMASR = ETH_DMA_IT_NIS;
|
||||||
}
|
}
|
||||||
} while( 1 );
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ch32v307ethTransmitStatic(uint8_t * buffer, uint32_t length, int enable_txc)
|
static int ch32v307ethTransmitStatic(uint8_t *buffer, uint32_t length, int enable_txc)
|
||||||
{
|
{
|
||||||
// The official SDK waits until ETH_DMATxDesc_TTSS is set.
|
// The official SDK waits until ETH_DMATxDesc_TTSS is set.
|
||||||
// This also provides a transmit timestamp, which could be
|
// This also provides a transmit timestamp, which could be
|
||||||
|
|
@ -516,7 +518,7 @@ static int ch32v307ethTransmitStatic(uint8_t * buffer, uint32_t length, int enab
|
||||||
// But we don't want to do that.
|
// But we don't want to do that.
|
||||||
// We just want to go. If anyone cares, they can check later.
|
// We just want to go. If anyone cares, they can check later.
|
||||||
|
|
||||||
if( pDMATxSet->Status & ETH_DMATxDesc_OWN )
|
if (pDMATxSet->Status & ETH_DMATxDesc_OWN)
|
||||||
{
|
{
|
||||||
ETH->DMATPDR = 0;
|
ETH->DMATPDR = 0;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -535,7 +537,7 @@ static int ch32v307ethTransmitStatic(uint8_t * buffer, uint32_t length, int enab
|
||||||
ETH_DMATxDesc_CIC_TCPUDPICMP_Full | // Do all header checksums.
|
ETH_DMATxDesc_CIC_TCPUDPICMP_Full | // Do all header checksums.
|
||||||
ETH_DMATxDesc_OWN; // Own back to hardware
|
ETH_DMATxDesc_OWN; // Own back to hardware
|
||||||
|
|
||||||
pDMATxSet = (ETH_DMADESCTypeDef*)pDMATxSet->Buffer2NextDescAddr;
|
pDMATxSet = (ETH_DMADESCTypeDef *)pDMATxSet->Buffer2NextDescAddr;
|
||||||
|
|
||||||
ETH->DMASR = ETH_DMASR_TBUS; // This resets the transmit process (or "starts" it)
|
ETH->DMASR = ETH_DMASR_TBUS; // This resets the transmit process (or "starts" it)
|
||||||
ETH->DMATPDR = 0;
|
ETH->DMATPDR = 0;
|
||||||
|
|
@ -543,6 +545,4 @@ static int ch32v307ethTransmitStatic(uint8_t * buffer, uint32_t length, int enab
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,25 +2,25 @@
|
||||||
#include "ch32fun.h"
|
#include "ch32fun.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define UEP_CTRL_H(n) (((uint16_t*)&USBHSD->UEP0_TX_CTRL)[n*2])
|
#define UEP_CTRL_H(n) (((uint16_t *)&USBHSD->UEP0_TX_CTRL)[n * 2])
|
||||||
|
|
||||||
struct _USBState HSUSBCTX;
|
struct _USBState HSUSBCTX;
|
||||||
|
|
||||||
// based on https://github.com/openwch/ch32v307/blob/main/EVT/EXAM/USB/USBHS/DEVICE/CompositeKM
|
// based on https://github.com/openwch/ch32v307/blob/main/EVT/EXAM/USB/USBHS/DEVICE/CompositeKM
|
||||||
|
|
||||||
// Mask for the combined USBHSD->INT_FG + USBHSD->INT_ST
|
// Mask for the combined USBHSD->INT_FG + USBHSD->INT_ST
|
||||||
#define CRB_U_IS_NAK (1<<7)
|
#define CRB_U_IS_NAK (1 << 7)
|
||||||
#define CTOG_MATCH_SYNC (1<<6)
|
#define CTOG_MATCH_SYNC (1 << 6)
|
||||||
#define CRB_UIF_SETUP_ACT (1<<5) // CRB_U_SIE_FREE on USBFS
|
#define CRB_UIF_SETUP_ACT (1 << 5) // CRB_U_SIE_FREE on USBFS
|
||||||
#define CRB_UIF_FIFO_OV (1<<4)
|
#define CRB_UIF_FIFO_OV (1 << 4)
|
||||||
#define CRB_UIF_HST_SOF (1<<3)
|
#define CRB_UIF_HST_SOF (1 << 3)
|
||||||
#define CRB_UIF_SUSPEND (1<<2)
|
#define CRB_UIF_SUSPEND (1 << 2)
|
||||||
#define CRB_UIF_TRANSFER (1<<1)
|
#define CRB_UIF_TRANSFER (1 << 1)
|
||||||
#define CRB_UIF_BUS_RST (1<<0)
|
#define CRB_UIF_BUS_RST (1 << 0)
|
||||||
#define CSETUP_ACT (1<<15)
|
#define CSETUP_ACT (1 << 15)
|
||||||
#define CRB_UIS_TOG_OK (1<<14)
|
#define CRB_UIS_TOG_OK (1 << 14)
|
||||||
#define CMASK_UIS_TOKEN (3<<12)
|
#define CMASK_UIS_TOKEN (3 << 12)
|
||||||
#define CMASK_UIS_ENDP (0xf<<8)
|
#define CMASK_UIS_ENDP (0xf << 8)
|
||||||
|
|
||||||
#define CUIS_TOKEN_OUT 0x0
|
#define CUIS_TOKEN_OUT 0x0
|
||||||
#define CUIS_TOKEN_SOF 0x1
|
#define CUIS_TOKEN_SOF 0x1
|
||||||
|
|
@ -44,7 +44,7 @@ static inline void DMA7FastCopy( uint8_t * dest, const uint8_t * src, int len )
|
||||||
DMA_MemoryInc_Enable |
|
DMA_MemoryInc_Enable |
|
||||||
DMA_PeripheralInc_Enable |
|
DMA_PeripheralInc_Enable |
|
||||||
DMA_Mode_Normal | DMA_CFGR1_EN;
|
DMA_Mode_Normal | DMA_CFGR1_EN;
|
||||||
#if !( FUSB_CURSED_TURBO_DMA == 1 )
|
#if !(FUSB_CURSED_TURBO_DMA == 1)
|
||||||
// Somehow, it seems to work (unsafely) without this.
|
// Somehow, it seems to work (unsafely) without this.
|
||||||
// Really, though, it's probably fine.
|
// Really, though, it's probably fine.
|
||||||
while( DMA1_Channel7->CNTR );
|
while( DMA1_Channel7->CNTR );
|
||||||
|
|
@ -57,11 +57,11 @@ static inline void DMA7FastCopyComplete() { while( DMA1_Channel7->CNTR ); }
|
||||||
|
|
||||||
void USBHS_InternalFinishSetup();
|
void USBHS_InternalFinishSetup();
|
||||||
|
|
||||||
//void USBHSWakeUp_IRQHandler(void) __attribute((interrupt));
|
// void USBHSWakeUp_IRQHandler(void) __attribute((interrupt));
|
||||||
//void USBHSWakeUp_IRQHandler(void)
|
// void USBHSWakeUp_IRQHandler(void)
|
||||||
//{
|
//{
|
||||||
// printf( "USBHSWakeUp MSTATUS:%08x MTVAL:%08x MCAUSE:%08x MEPC:%08x\n", (int)__get_MSTATUS(), (int)__get_MTVAL(), (int)__get_MCAUSE(), (int)__get_MEPC() );
|
// printf( "USBHSWakeUp MSTATUS:%08x MTVAL:%08x MCAUSE:%08x MEPC:%08x\n", (int)__get_MSTATUS(), (int)__get_MTVAL(), (int)__get_MCAUSE(), (int)__get_MEPC() );
|
||||||
//}
|
// }
|
||||||
extern uint8_t scratchpad[];
|
extern uint8_t scratchpad[];
|
||||||
|
|
||||||
void USBHS_IRQHandler(void) __attribute((interrupt));
|
void USBHS_IRQHandler(void) __attribute((interrupt));
|
||||||
|
|
@ -69,12 +69,12 @@ void USBHS_IRQHandler(void)
|
||||||
{
|
{
|
||||||
// Based on https://github.com/openwch/ch32v307/blob/main/EVT/EXAM/USB/USBHS/DEVICE/CompositeKM/User/ch32v30x_usbhs_device.c
|
// Based on https://github.com/openwch/ch32v307/blob/main/EVT/EXAM/USB/USBHS/DEVICE/CompositeKM/User/ch32v30x_usbhs_device.c
|
||||||
// Combined FG + ST flag
|
// Combined FG + ST flag
|
||||||
uint16_t intfgst = *(uint16_t*)(&USBHSD->INT_FG);
|
uint16_t intfgst = *(uint16_t *)(&USBHSD->INT_FG);
|
||||||
int len = 0;
|
int len = 0;
|
||||||
struct _USBState * ctx = &HSUSBCTX;
|
struct _USBState *ctx = &HSUSBCTX;
|
||||||
uint8_t * ctrl0buff = CTRL0BUFF;
|
uint8_t *ctrl0buff = CTRL0BUFF;
|
||||||
|
|
||||||
if( intfgst & ( CRB_UIF_SETUP_ACT ) )
|
if (intfgst & (CRB_UIF_SETUP_ACT))
|
||||||
{
|
{
|
||||||
// On the Chapter 22 USB, SETUP Requests are handled here instead of in UIF_TRANSFER, with TOKEN_SETUP.
|
// On the Chapter 22 USB, SETUP Requests are handled here instead of in UIF_TRANSFER, with TOKEN_SETUP.
|
||||||
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
|
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
|
||||||
|
|
@ -85,43 +85,43 @@ void USBHS_IRQHandler(void)
|
||||||
int USBHS_SetupReqCode = HSUSBCTX.USBHS_SetupReqCode = pUSBHS_SetupReqPak->bRequest;
|
int USBHS_SetupReqCode = HSUSBCTX.USBHS_SetupReqCode = pUSBHS_SetupReqPak->bRequest;
|
||||||
int USBHS_SetupReqLen = HSUSBCTX.USBHS_SetupReqLen = pUSBHS_SetupReqPak->wLength;
|
int USBHS_SetupReqLen = HSUSBCTX.USBHS_SetupReqLen = pUSBHS_SetupReqPak->wLength;
|
||||||
int USBHS_SetupReqIndex = pUSBHS_SetupReqPak->wIndex;
|
int USBHS_SetupReqIndex = pUSBHS_SetupReqPak->wIndex;
|
||||||
int USBHS_IndexValue = HSUSBCTX.USBHS_IndexValue = ( pUSBHS_SetupReqPak->wIndex << 16 ) | pUSBHS_SetupReqPak->wValue;
|
int USBHS_IndexValue = HSUSBCTX.USBHS_IndexValue = (pUSBHS_SetupReqPak->wIndex << 16) | pUSBHS_SetupReqPak->wValue;
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
//printf( "Setup: %d %d %d %d %d\n", USBHS_SetupReqType, USBHS_SetupReqCode, USBHS_SetupReqLen,
|
// printf( "Setup: %d %d %d %d %d\n", USBHS_SetupReqType, USBHS_SetupReqCode, USBHS_SetupReqLen,
|
||||||
// USBHS_SetupReqIndex, USBHS_IndexValue );
|
// USBHS_SetupReqIndex, USBHS_IndexValue );
|
||||||
|
|
||||||
if( ( USBHS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
|
if ((USBHS_SetupReqType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD)
|
||||||
{
|
{
|
||||||
#if HUSB_HID_INTERFACES > 0
|
#if HUSB_HID_INTERFACES > 0
|
||||||
if( ( USBHS_SetupReqType & USB_REQ_TYP_MASK ) == USB_REQ_TYP_CLASS )
|
if ((USBHS_SetupReqType & USB_REQ_TYP_MASK) == USB_REQ_TYP_CLASS)
|
||||||
{
|
{
|
||||||
/* Class Request */
|
/* Class Request */
|
||||||
//printf( "REQ: %d [%02x %02x %04x %04x]\n", USBHS_SetupReqCode, pUSBHS_SetupReqPak->bmRequestType, pUSBHS_SetupReqPak->bRequest, pUSBHS_SetupReqPak->wValue, pUSBHS_SetupReqPak->wLength );
|
// printf( "REQ: %d [%02x %02x %04x %04x]\n", USBHS_SetupReqCode, pUSBHS_SetupReqPak->bmRequestType, pUSBHS_SetupReqPak->bRequest, pUSBHS_SetupReqPak->wValue, pUSBHS_SetupReqPak->wLength );
|
||||||
switch( USBHS_SetupReqCode )
|
switch (USBHS_SetupReqCode)
|
||||||
{
|
{
|
||||||
case HID_SET_REPORT:
|
case HID_SET_REPORT:
|
||||||
#if HUSB_HID_USER_REPORTS
|
#if HUSB_HID_USER_REPORTS
|
||||||
len = HandleHidUserSetReportSetup( ctx, pUSBHS_SetupReqPak );
|
len = HandleHidUserSetReportSetup(ctx, pUSBHS_SetupReqPak);
|
||||||
if( len < 0 ) goto sendstall;
|
if (len < 0) goto sendstall;
|
||||||
ctx->USBHS_SetupReqLen = len;
|
ctx->USBHS_SetupReqLen = len;
|
||||||
USBHSD->UEP0_TX_LEN = 0;
|
USBHSD->UEP0_TX_LEN = 0;
|
||||||
USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_ACK;
|
USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_ACK;
|
||||||
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1;
|
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1;
|
||||||
goto replycomplete;
|
goto replycomplete;
|
||||||
case HID_GET_REPORT:
|
case HID_GET_REPORT:
|
||||||
len = HandleHidUserGetReportSetup( ctx, pUSBHS_SetupReqPak );
|
len = HandleHidUserGetReportSetup(ctx, pUSBHS_SetupReqPak);
|
||||||
if( len < 0 ) goto sendstall;
|
if (len < 0) goto sendstall;
|
||||||
ctx->USBHS_SetupReqLen = len;
|
ctx->USBHS_SetupReqLen = len;
|
||||||
len = len >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : len;
|
len = len >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : len;
|
||||||
if( !ctx->pCtrlPayloadPtr )
|
if (!ctx->pCtrlPayloadPtr)
|
||||||
{
|
{
|
||||||
len = HandleHidUserReportDataIn( ctx, ctrl0buff, len );
|
len = HandleHidUserReportDataIn(ctx, ctrl0buff, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len );
|
// DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len );
|
||||||
memcpy( ctrl0buff, ctx->pCtrlPayloadPtr, len );
|
memcpy(ctrl0buff, ctx->pCtrlPayloadPtr, len);
|
||||||
ctx->pCtrlPayloadPtr += len;
|
ctx->pCtrlPayloadPtr += len;
|
||||||
}
|
}
|
||||||
USBHSD->UEP0_TX_LEN = len;
|
USBHSD->UEP0_TX_LEN = len;
|
||||||
|
|
@ -131,28 +131,27 @@ void USBHS_IRQHandler(void)
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case HID_SET_IDLE:
|
case HID_SET_IDLE:
|
||||||
if( USBHS_SetupReqIndex < HUSB_HID_INTERFACES )
|
if (USBHS_SetupReqIndex < HUSB_HID_INTERFACES)
|
||||||
HSUSBCTX.USBHS_HidIdle[ USBHS_SetupReqIndex ] = (uint8_t)( USBHS_IndexValue >> 8 );
|
HSUSBCTX.USBHS_HidIdle[USBHS_SetupReqIndex] = (uint8_t)(USBHS_IndexValue >> 8);
|
||||||
break;
|
break;
|
||||||
case HID_SET_PROTOCOL:
|
case HID_SET_PROTOCOL:
|
||||||
if ( USBHS_SetupReqIndex < HUSB_HID_INTERFACES )
|
if (USBHS_SetupReqIndex < HUSB_HID_INTERFACES)
|
||||||
HSUSBCTX.USBHS_HidProtocol[USBHS_SetupReqIndex] = (uint8_t)USBHS_IndexValue;
|
HSUSBCTX.USBHS_HidProtocol[USBHS_SetupReqIndex] = (uint8_t)USBHS_IndexValue;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_GET_IDLE:
|
case HID_GET_IDLE:
|
||||||
if( USBHS_SetupReqIndex < HUSB_HID_INTERFACES )
|
if (USBHS_SetupReqIndex < HUSB_HID_INTERFACES)
|
||||||
{
|
{
|
||||||
ctrl0buff[0] = HSUSBCTX.USBHS_HidIdle[ USBHS_SetupReqIndex ];
|
ctrl0buff[0] = HSUSBCTX.USBHS_HidIdle[USBHS_SetupReqIndex];
|
||||||
len = 1;
|
len = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case HID_GET_PROTOCOL:
|
case HID_GET_PROTOCOL:
|
||||||
if( USBHS_SetupReqIndex < HUSB_HID_INTERFACES )
|
if (USBHS_SetupReqIndex < HUSB_HID_INTERFACES)
|
||||||
{
|
{
|
||||||
ctrl0buff[0] = HSUSBCTX.USBHS_HidProtocol[ USBHS_SetupReqIndex ];
|
ctrl0buff[0] = HSUSBCTX.USBHS_HidProtocol[USBHS_SetupReqIndex];
|
||||||
len = 1;
|
len = 1;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -169,37 +168,36 @@ void USBHS_IRQHandler(void)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* usb standard request processing */
|
/* usb standard request processing */
|
||||||
switch( USBHS_SetupReqCode )
|
switch (USBHS_SetupReqCode)
|
||||||
{
|
{
|
||||||
/* get device/configuration/string/report/... descriptors */
|
/* get device/configuration/string/report/... descriptors */
|
||||||
case USB_GET_DESCRIPTOR:
|
case USB_GET_DESCRIPTOR:
|
||||||
{
|
{
|
||||||
const struct descriptor_list_struct * e = descriptor_list;
|
const struct descriptor_list_struct *e = descriptor_list;
|
||||||
const struct descriptor_list_struct * e_end = e + DESCRIPTOR_LIST_ENTRIES;
|
const struct descriptor_list_struct *e_end = e + DESCRIPTOR_LIST_ENTRIES;
|
||||||
for( ; e != e_end; e++ )
|
for (; e != e_end; e++)
|
||||||
{
|
{
|
||||||
if( e->lIndexValue == USBHS_IndexValue )
|
if (e->lIndexValue == USBHS_IndexValue)
|
||||||
{
|
{
|
||||||
ctx->pCtrlPayloadPtr = (uint8_t*)e->addr;
|
ctx->pCtrlPayloadPtr = (uint8_t *)e->addr;
|
||||||
len = e->length;
|
len = e->length;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( e == e_end )
|
if (e == e_end)
|
||||||
{
|
{
|
||||||
goto sendstall;
|
goto sendstall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Copy Descriptors to Endp0 DMA buffer */
|
/* Copy Descriptors to Endp0 DMA buffer */
|
||||||
int totalLen = USBHS_SetupReqLen;
|
int totalLen = USBHS_SetupReqLen;
|
||||||
if( totalLen > len )
|
if (totalLen > len)
|
||||||
{
|
{
|
||||||
totalLen = len;
|
totalLen = len;
|
||||||
}
|
}
|
||||||
len = ( totalLen >= DEF_USBD_UEP0_SIZE ) ? DEF_USBD_UEP0_SIZE : totalLen;
|
len = (totalLen >= DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : totalLen;
|
||||||
//DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len ); //memcpy( CTRL0BUFF, ctx->pCtrlPayloadPtr, len );
|
// DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len ); //memcpy( CTRL0BUFF, ctx->pCtrlPayloadPtr, len );
|
||||||
memcpy( ctrl0buff, ctx->pCtrlPayloadPtr, len );
|
memcpy(ctrl0buff, ctx->pCtrlPayloadPtr, len);
|
||||||
ctx->USBHS_SetupReqLen = totalLen - len;
|
ctx->USBHS_SetupReqLen = totalLen - len;
|
||||||
ctx->pCtrlPayloadPtr += len;
|
ctx->pCtrlPayloadPtr += len;
|
||||||
USBHSD->UEP0_TX_LEN = len;
|
USBHSD->UEP0_TX_LEN = len;
|
||||||
|
|
@ -209,29 +207,29 @@ void USBHS_IRQHandler(void)
|
||||||
|
|
||||||
/* Set usb address */
|
/* Set usb address */
|
||||||
case USB_SET_ADDRESS:
|
case USB_SET_ADDRESS:
|
||||||
ctx->USBHS_DevAddr = (uint16_t)( ctx->USBHS_IndexValue & 0xFF );
|
ctx->USBHS_DevAddr = (uint16_t)(ctx->USBHS_IndexValue & 0xFF);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Get usb configuration now set */
|
/* Get usb configuration now set */
|
||||||
case USB_GET_CONFIGURATION:
|
case USB_GET_CONFIGURATION:
|
||||||
ctrl0buff[0] = ctx->USBHS_DevConfig;
|
ctrl0buff[0] = ctx->USBHS_DevConfig;
|
||||||
if( ctx->USBHS_SetupReqLen > 1 )
|
if (ctx->USBHS_SetupReqLen > 1)
|
||||||
ctx->USBHS_SetupReqLen = 1;
|
ctx->USBHS_SetupReqLen = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Set usb configuration to use */
|
/* Set usb configuration to use */
|
||||||
case USB_SET_CONFIGURATION:
|
case USB_SET_CONFIGURATION:
|
||||||
ctx->USBHS_DevConfig = (uint8_t)( ctx->USBHS_IndexValue & 0xFF );
|
ctx->USBHS_DevConfig = (uint8_t)(ctx->USBHS_IndexValue & 0xFF);
|
||||||
ctx->USBHS_DevEnumStatus = 0x01;
|
ctx->USBHS_DevEnumStatus = 0x01;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* Clear or disable one usb feature */
|
/* Clear or disable one usb feature */
|
||||||
case USB_CLEAR_FEATURE:
|
case USB_CLEAR_FEATURE:
|
||||||
#if HUSB_SUPPORTS_SLEEP
|
#if HUSB_SUPPORTS_SLEEP
|
||||||
if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
|
if ((USBHS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE)
|
||||||
{
|
{
|
||||||
/* clear one device feature */
|
/* clear one device feature */
|
||||||
if( (uint8_t)( USBHS_IndexValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP )
|
if ((uint8_t)(USBHS_IndexValue & 0xFF) == USB_REQ_FEAT_REMOTE_WAKEUP)
|
||||||
{
|
{
|
||||||
/* clear usb sleep status, device not prepare to sleep */
|
/* clear usb sleep status, device not prepare to sleep */
|
||||||
ctx->USBHS_DevSleepStatus &= ~0x01;
|
ctx->USBHS_DevSleepStatus &= ~0x01;
|
||||||
|
|
@ -243,13 +241,13 @@ void USBHS_IRQHandler(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
|
if ((USBHS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP)
|
||||||
{
|
{
|
||||||
if( (uint8_t)( USBHS_IndexValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT )
|
if ((uint8_t)(USBHS_IndexValue & 0xFF) == USB_REQ_FEAT_ENDP_HALT)
|
||||||
{
|
{
|
||||||
/* Clear End-point Feature */
|
/* Clear End-point Feature */
|
||||||
int ep = USBHS_SetupReqIndex & 0xf;
|
int ep = USBHS_SetupReqIndex & 0xf;
|
||||||
if( ( USBHS_SetupReqIndex & DEF_UEP_IN ) && ep < HUSB_CONFIG_EPS )
|
if ((USBHS_SetupReqIndex & DEF_UEP_IN) && ep < HUSB_CONFIG_EPS)
|
||||||
{
|
{
|
||||||
UEP_CTRL_H(ep) = USBHS_UEP_T_TOG_DATA0 | USBHS_UEP_T_RES_NAK;
|
UEP_CTRL_H(ep) = USBHS_UEP_T_TOG_DATA0 | USBHS_UEP_T_RES_NAK;
|
||||||
}
|
}
|
||||||
|
|
@ -271,11 +269,11 @@ void USBHS_IRQHandler(void)
|
||||||
|
|
||||||
/* set or enable one usb feature */
|
/* set or enable one usb feature */
|
||||||
case USB_SET_FEATURE:
|
case USB_SET_FEATURE:
|
||||||
if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
|
if ((USBHS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE)
|
||||||
{
|
{
|
||||||
#if HUSB_SUPPORTS_SLEEP
|
#if HUSB_SUPPORTS_SLEEP
|
||||||
/* Set Device Feature */
|
/* Set Device Feature */
|
||||||
if( (uint8_t)( USBHS_IndexValue & 0xFF ) == USB_REQ_FEAT_REMOTE_WAKEUP )
|
if ((uint8_t)(USBHS_IndexValue & 0xFF) == USB_REQ_FEAT_REMOTE_WAKEUP)
|
||||||
{
|
{
|
||||||
/* Set Wake-up flag, device prepare to sleep */
|
/* Set Wake-up flag, device prepare to sleep */
|
||||||
USBHS_DevSleepStatus |= 0x01;
|
USBHS_DevSleepStatus |= 0x01;
|
||||||
|
|
@ -286,14 +284,14 @@ void USBHS_IRQHandler(void)
|
||||||
goto sendstall;
|
goto sendstall;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
|
else if ((USBHS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP)
|
||||||
{
|
{
|
||||||
/* Set Endpoint Feature */
|
/* Set Endpoint Feature */
|
||||||
if( (uint8_t)( USBHS_IndexValue & 0xFF ) == USB_REQ_FEAT_ENDP_HALT )
|
if ((uint8_t)(USBHS_IndexValue & 0xFF) == USB_REQ_FEAT_ENDP_HALT)
|
||||||
{
|
{
|
||||||
int ep = USBHS_SetupReqIndex & 0xf;
|
int ep = USBHS_SetupReqIndex & 0xf;
|
||||||
if( ( USBHS_SetupReqIndex & DEF_UEP_IN ) && ep < HUSB_CONFIG_EPS )
|
if ((USBHS_SetupReqIndex & DEF_UEP_IN) && ep < HUSB_CONFIG_EPS)
|
||||||
UEP_CTRL_H(ep) = ( UEP_CTRL_H(ep) & ~USBHS_UEP_T_RES_MASK ) | USBHS_UEP_T_RES_STALL;
|
UEP_CTRL_H(ep) = (UEP_CTRL_H(ep) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_STALL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto sendstall;
|
goto sendstall;
|
||||||
|
|
@ -305,7 +303,7 @@ void USBHS_IRQHandler(void)
|
||||||
/* This request allows the host to select another setting for the specified interface */
|
/* This request allows the host to select another setting for the specified interface */
|
||||||
case USB_GET_INTERFACE:
|
case USB_GET_INTERFACE:
|
||||||
ctrl0buff[0] = 0x00;
|
ctrl0buff[0] = 0x00;
|
||||||
if( USBHS_SetupReqLen > 1 ) USBHS_SetupReqLen = 1;
|
if (USBHS_SetupReqLen > 1) USBHS_SetupReqLen = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case USB_SET_INTERFACE:
|
case USB_SET_INTERFACE:
|
||||||
|
|
@ -315,25 +313,25 @@ void USBHS_IRQHandler(void)
|
||||||
case USB_GET_STATUS:
|
case USB_GET_STATUS:
|
||||||
ctrl0buff[0] = 0x00;
|
ctrl0buff[0] = 0x00;
|
||||||
ctrl0buff[1] = 0x00;
|
ctrl0buff[1] = 0x00;
|
||||||
if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_DEVICE )
|
if ((USBHS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_DEVICE)
|
||||||
{
|
{
|
||||||
#if FUSB_SUPPORTS_SLEEP
|
#if FUSB_SUPPORTS_SLEEP
|
||||||
ctrl0buff[0] = (ctx->USBHS_DevSleepStatus & 0x01)<<1;
|
ctrl0buff[0] = (ctx->USBHS_DevSleepStatus & 0x01) << 1;
|
||||||
#else
|
#else
|
||||||
ctrl0buff[0] = 0x00;
|
ctrl0buff[0] = 0x00;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else if( ( USBHS_SetupReqType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )
|
else if ((USBHS_SetupReqType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP)
|
||||||
{
|
{
|
||||||
int ep = USBHS_SetupReqIndex & 0xf;
|
int ep = USBHS_SetupReqIndex & 0xf;
|
||||||
if( ( USBHS_SetupReqIndex & DEF_UEP_IN ) && ep < HUSB_CONFIG_EPS )
|
if ((USBHS_SetupReqIndex & DEF_UEP_IN) && ep < HUSB_CONFIG_EPS)
|
||||||
ctrl0buff[0] = ( UEP_CTRL_H(ep) & USBHS_UEP_T_RES_MASK ) == USBHS_UEP_T_RES_STALL;
|
ctrl0buff[0] = (UEP_CTRL_H(ep) & USBHS_UEP_T_RES_MASK) == USBHS_UEP_T_RES_STALL;
|
||||||
else
|
else
|
||||||
goto sendstall;
|
goto sendstall;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
goto sendstall;
|
goto sendstall;
|
||||||
if( USBHS_SetupReqLen > 2 )
|
if (USBHS_SetupReqLen > 2)
|
||||||
USBHS_SetupReqLen = 2;
|
USBHS_SetupReqLen = 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -343,19 +341,18 @@ void USBHS_IRQHandler(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
/* end-point 0 data Tx/Rx */
|
/* end-point 0 data Tx/Rx */
|
||||||
if( USBHS_SetupReqType & DEF_UEP_IN )
|
if (USBHS_SetupReqType & DEF_UEP_IN)
|
||||||
{
|
{
|
||||||
len = ( USBHS_SetupReqLen > DEF_USBD_UEP0_SIZE )? DEF_USBD_UEP0_SIZE : USBHS_SetupReqLen;
|
len = (USBHS_SetupReqLen > DEF_USBD_UEP0_SIZE) ? DEF_USBD_UEP0_SIZE : USBHS_SetupReqLen;
|
||||||
USBHS_SetupReqLen -= len;
|
USBHS_SetupReqLen -= len;
|
||||||
USBHSD->UEP0_TX_LEN = len;
|
USBHSD->UEP0_TX_LEN = len;
|
||||||
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
|
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( USBHS_SetupReqLen == 0 )
|
if (USBHS_SetupReqLen == 0)
|
||||||
{
|
{
|
||||||
USBHSD->UEP0_TX_LEN = 0;
|
USBHSD->UEP0_TX_LEN = 0;
|
||||||
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
|
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_ACK;
|
||||||
|
|
@ -375,23 +372,22 @@ void USBHS_IRQHandler(void)
|
||||||
// if one request not support, return stall. Stall means permanent error.
|
// if one request not support, return stall. Stall means permanent error.
|
||||||
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_STALL;
|
USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_STALL;
|
||||||
USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_STALL;
|
USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_STALL;
|
||||||
replycomplete:
|
replycomplete:;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
if( intfgst & ( CRB_UIF_TRANSFER ) )
|
if (intfgst & (CRB_UIF_TRANSFER))
|
||||||
{
|
{
|
||||||
int token = ( intfgst & CMASK_UIS_TOKEN) >> 12;
|
int token = (intfgst & CMASK_UIS_TOKEN) >> 12;
|
||||||
int ep = ( intfgst & CMASK_UIS_ENDP ) >> 8;
|
int ep = (intfgst & CMASK_UIS_ENDP) >> 8;
|
||||||
switch ( token )
|
switch (token)
|
||||||
{
|
{
|
||||||
case CUIS_TOKEN_IN:
|
case CUIS_TOKEN_IN:
|
||||||
if( ep )
|
if (ep)
|
||||||
{
|
{
|
||||||
if( ep < HUSB_CONFIG_EPS )
|
if (ep < HUSB_CONFIG_EPS)
|
||||||
{
|
{
|
||||||
UEP_CTRL_H(ep) = ( UEP_CTRL_H(ep) & ~USBHS_UEP_T_RES_MASK ) | USBHS_UEP_T_RES_NAK;
|
UEP_CTRL_H(ep) = (UEP_CTRL_H(ep) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_NAK;
|
||||||
UEP_CTRL_H(ep) ^= USBHS_UEP_T_TOG_DATA1;
|
UEP_CTRL_H(ep) ^= USBHS_UEP_T_TOG_DATA1;
|
||||||
ctx->USBHS_Endp_Busy[ ep ] = 0;
|
ctx->USBHS_Endp_Busy[ep] = 0;
|
||||||
// Don't set EP in here. Wait for out.
|
// Don't set EP in here. Wait for out.
|
||||||
// Optimization: Could we set EP here?
|
// Optimization: Could we set EP here?
|
||||||
}
|
}
|
||||||
|
|
@ -399,19 +395,19 @@ void USBHS_IRQHandler(void)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* end-point 0 data in interrupt */
|
/* end-point 0 data in interrupt */
|
||||||
if( ctx->USBHS_SetupReqLen == 0 )
|
if (ctx->USBHS_SetupReqLen == 0)
|
||||||
{
|
{
|
||||||
USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_ACK;
|
USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_ACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( ctx->pCtrlPayloadPtr )
|
if (ctx->pCtrlPayloadPtr)
|
||||||
{
|
{
|
||||||
// Shortcut mechanism, for descriptors or if the user wants it.
|
// Shortcut mechanism, for descriptors or if the user wants it.
|
||||||
len = ctx->USBHS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBHS_SetupReqLen;
|
len = ctx->USBHS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBHS_SetupReqLen;
|
||||||
//DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len ); // FYI -> Would need to do this if using DMA
|
// DMA7FastCopy( ctrl0buff, ctx->pCtrlPayloadPtr, len ); // FYI -> Would need to do this if using DMA
|
||||||
memcpy( ctrl0buff, ctx->pCtrlPayloadPtr, len );
|
memcpy(ctrl0buff, ctx->pCtrlPayloadPtr, len);
|
||||||
ctx->USBHS_SetupReqLen -= len;
|
ctx->USBHS_SetupReqLen -= len;
|
||||||
if( ctx->USBHS_SetupReqLen > 0 )
|
if (ctx->USBHS_SetupReqLen > 0)
|
||||||
ctx->pCtrlPayloadPtr += len;
|
ctx->pCtrlPayloadPtr += len;
|
||||||
else
|
else
|
||||||
ctx->pCtrlPayloadPtr = 0;
|
ctx->pCtrlPayloadPtr = 0;
|
||||||
|
|
@ -419,14 +415,13 @@ void USBHS_IRQHandler(void)
|
||||||
USBHSD->UEP0_TX_LEN = len;
|
USBHSD->UEP0_TX_LEN = len;
|
||||||
USBHSD->UEP0_TX_CTRL ^= USBHS_UEP_T_TOG_DATA1;
|
USBHSD->UEP0_TX_CTRL ^= USBHS_UEP_T_TOG_DATA1;
|
||||||
}
|
}
|
||||||
else if ( ( ctx->USBHS_SetupReqType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )
|
else if ((ctx->USBHS_SetupReqType & USB_REQ_TYP_MASK) != USB_REQ_TYP_STANDARD)
|
||||||
{
|
{
|
||||||
|
|
||||||
#if HUSB_HID_USER_REPORTS
|
#if HUSB_HID_USER_REPORTS
|
||||||
len = ctx->USBHS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBHS_SetupReqLen;
|
len = ctx->USBHS_SetupReqLen >= DEF_USBD_UEP0_SIZE ? DEF_USBD_UEP0_SIZE : ctx->USBHS_SetupReqLen;
|
||||||
if( len && HSUSBCTX.USBHS_SetupReqCode == HID_GET_REPORT )
|
if (len && HSUSBCTX.USBHS_SetupReqCode == HID_GET_REPORT)
|
||||||
{
|
{
|
||||||
len = HandleHidUserReportDataIn( ctx, ctrl0buff, len );
|
len = HandleHidUserReportDataIn(ctx, ctrl0buff, len);
|
||||||
USBHSD->UEP0_TX_LEN = len;
|
USBHSD->UEP0_TX_LEN = len;
|
||||||
USBHSD->UEP0_TX_CTRL ^= USBHS_UEP_T_TOG_DATA1;
|
USBHSD->UEP0_TX_CTRL ^= USBHS_UEP_T_TOG_DATA1;
|
||||||
ctx->USBHS_SetupReqLen -= len;
|
ctx->USBHS_SetupReqLen -= len;
|
||||||
|
|
@ -436,7 +431,7 @@ void USBHS_IRQHandler(void)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch( HSUSBCTX.USBHS_SetupReqCode )
|
switch (HSUSBCTX.USBHS_SetupReqCode)
|
||||||
{
|
{
|
||||||
case USB_GET_DESCRIPTOR:
|
case USB_GET_DESCRIPTOR:
|
||||||
break;
|
break;
|
||||||
|
|
@ -453,7 +448,7 @@ void USBHS_IRQHandler(void)
|
||||||
|
|
||||||
/* data-out stage processing */
|
/* data-out stage processing */
|
||||||
case CUIS_TOKEN_OUT:
|
case CUIS_TOKEN_OUT:
|
||||||
switch( ep )
|
switch (ep)
|
||||||
{
|
{
|
||||||
/* end-point 0 data out interrupt */
|
/* end-point 0 data out interrupt */
|
||||||
case DEF_UEP0:
|
case DEF_UEP0:
|
||||||
|
|
@ -461,38 +456,38 @@ void USBHS_IRQHandler(void)
|
||||||
// XXX WARNINGS:
|
// XXX WARNINGS:
|
||||||
// 1. intfgst & CRB_UIS_TOG_OK is not set for non-odd transactions, i.e. first, third, etc, are all fine.
|
// 1. intfgst & CRB_UIS_TOG_OK is not set for non-odd transactions, i.e. first, third, etc, are all fine.
|
||||||
// 2. HandleHidUserReportOutComplete doesn't seem to work.
|
// 2. HandleHidUserReportOutComplete doesn't seem to work.
|
||||||
//if( intfgst & CRB_UIS_TOG_OK )
|
// if( intfgst & CRB_UIS_TOG_OK )
|
||||||
|
|
||||||
#if HUSB_HID_USER_REPORTS
|
#if HUSB_HID_USER_REPORTS
|
||||||
int len = USBHSD->RX_LEN;
|
int len = USBHSD->RX_LEN;
|
||||||
uint8_t * cptr = ctx->pCtrlPayloadPtr;
|
uint8_t *cptr = ctx->pCtrlPayloadPtr;
|
||||||
if( !cptr )
|
if (!cptr)
|
||||||
{
|
{
|
||||||
HandleHidUserReportDataOut( ctx, ctrl0buff, len );
|
HandleHidUserReportDataOut(ctx, ctrl0buff, len);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int remain = ctx->USBHS_SetupReqLen - len;
|
int remain = ctx->USBHS_SetupReqLen - len;
|
||||||
if( remain < 0 )
|
if (remain < 0)
|
||||||
{
|
{
|
||||||
len += remain;
|
len += remain;
|
||||||
remain = 0;
|
remain = 0;
|
||||||
}
|
}
|
||||||
//DMA7FastCopy( cptr, ctrl0buff, len );
|
// DMA7FastCopy( cptr, ctrl0buff, len );
|
||||||
memcpy( cptr, ctrl0buff, len );
|
memcpy(cptr, ctrl0buff, len);
|
||||||
ctx->USBHS_SetupReqLen = remain;
|
ctx->USBHS_SetupReqLen = remain;
|
||||||
if( remain > 0 )
|
if (remain > 0)
|
||||||
ctx->pCtrlPayloadPtr = cptr + len;
|
ctx->pCtrlPayloadPtr = cptr + len;
|
||||||
else
|
else
|
||||||
ctx->pCtrlPayloadPtr = 0;
|
ctx->pCtrlPayloadPtr = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if( ctx->USBHS_SetupReqLen == 0 )
|
if (ctx->USBHS_SetupReqLen == 0)
|
||||||
{
|
{
|
||||||
#if HUSB_HID_USER_REPORTS
|
#if HUSB_HID_USER_REPORTS
|
||||||
//DMA7FastCopyComplete();
|
// DMA7FastCopyComplete();
|
||||||
HandleHidUserReportOutComplete( ctx );
|
HandleHidUserReportOutComplete(ctx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -503,10 +498,10 @@ void USBHS_IRQHandler(void)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// Any other out. (also happens with In)
|
// Any other out. (also happens with In)
|
||||||
HSUSBCTX.USBHS_Endp_Busy[ ep ] = 0x02;
|
HSUSBCTX.USBHS_Endp_Busy[ep] = 0x02;
|
||||||
USBHSD_UEP_RXCTRL( ep ) = ((USBHSD_UEP_RXCTRL( ep )) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
|
USBHSD_UEP_RXCTRL(ep) = ((USBHSD_UEP_RXCTRL(ep)) & ~USBHS_UEP_R_RES_MASK) | USBHS_UEP_R_RES_NAK;
|
||||||
#if HUSB_BULK_USER_REPORTS
|
#if HUSB_BULK_USER_REPORTS
|
||||||
HandleGotEPComplete( ctx, ep );
|
HandleGotEPComplete(ctx, ep);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -515,11 +510,11 @@ void USBHS_IRQHandler(void)
|
||||||
case CUIS_TOKEN_SOF: // Sof pack processing
|
case CUIS_TOKEN_SOF: // Sof pack processing
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default :
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(intfgst & USBHS_UIF_BUS_RST)
|
if (intfgst & USBHS_UIF_BUS_RST)
|
||||||
{
|
{
|
||||||
/* usb reset interrupt processing */
|
/* usb reset interrupt processing */
|
||||||
ctx->USBHS_DevConfig = 0;
|
ctx->USBHS_DevConfig = 0;
|
||||||
|
|
@ -528,18 +523,18 @@ void USBHS_IRQHandler(void)
|
||||||
ctx->USBHS_DevEnumStatus = 0;
|
ctx->USBHS_DevEnumStatus = 0;
|
||||||
|
|
||||||
USBHSD->DEV_AD = 0;
|
USBHSD->DEV_AD = 0;
|
||||||
USBHS_InternalFinishSetup( );
|
USBHS_InternalFinishSetup();
|
||||||
}
|
}
|
||||||
if(intfgst & USBHS_UIF_SUSPEND)
|
if (intfgst & USBHS_UIF_SUSPEND)
|
||||||
{
|
{
|
||||||
USBHSD->INT_FG = USBHS_UIF_SUSPEND;
|
USBHSD->INT_FG = USBHS_UIF_SUSPEND;
|
||||||
Delay_Us(10);
|
Delay_Us(10);
|
||||||
|
|
||||||
// USB suspend interrupt processing
|
// USB suspend interrupt processing
|
||||||
if(USBHSD->MIS_ST & USBHS_UMS_SUSPEND)
|
if (USBHSD->MIS_ST & USBHS_UMS_SUSPEND)
|
||||||
{
|
{
|
||||||
HSUSBCTX.USBHS_DevSleepStatus |= 0x02;
|
HSUSBCTX.USBHS_DevSleepStatus |= 0x02;
|
||||||
if(HSUSBCTX.USBHS_DevSleepStatus == 0x03)
|
if (HSUSBCTX.USBHS_DevSleepStatus == 0x03)
|
||||||
{
|
{
|
||||||
// TODO: Handle usb sleep here
|
// TODO: Handle usb sleep here
|
||||||
}
|
}
|
||||||
|
|
@ -555,21 +550,16 @@ void USBHS_IRQHandler(void)
|
||||||
|
|
||||||
void USBHS_InternalFinishSetup()
|
void USBHS_InternalFinishSetup()
|
||||||
{
|
{
|
||||||
|
|
||||||
// To reconfigure your endpoints for TX/RX do it here.
|
// To reconfigure your endpoints for TX/RX do it here.
|
||||||
|
|
||||||
#if HUSB_CONFIG_EPS > 5
|
#if HUSB_CONFIG_EPS > 5
|
||||||
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN
|
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN | USBHS_UEP2_T_EN | USBHS_UEP3_T_EN | USBHS_UEP4_T_EN | USBHS_UEP5_R_EN;
|
||||||
| USBHS_UEP2_T_EN | USBHS_UEP3_T_EN | USBHS_UEP4_T_EN | USBHS_UEP5_R_EN;
|
|
||||||
#elif HUSB_CONFIG_EPS > 4
|
#elif HUSB_CONFIG_EPS > 4
|
||||||
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN
|
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN | USBHS_UEP2_T_EN | USBHS_UEP3_T_EN | USBHS_UEP4_T_EN;
|
||||||
| USBHS_UEP2_T_EN | USBHS_UEP3_T_EN | USBHS_UEP4_T_EN;
|
|
||||||
#elif HUSB_CONFIG_EPS > 3
|
#elif HUSB_CONFIG_EPS > 3
|
||||||
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN
|
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN | USBHS_UEP2_T_EN | USBHS_UEP3_T_EN;
|
||||||
| USBHS_UEP2_T_EN | USBHS_UEP3_T_EN;
|
|
||||||
#elif HUSB_CONFIG_EPS > 2
|
#elif HUSB_CONFIG_EPS > 2
|
||||||
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN
|
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN | USBHS_UEP2_T_EN;
|
||||||
| USBHS_UEP2_T_EN;
|
|
||||||
#elif HUSB_CONFIG_EPS > 1
|
#elif HUSB_CONFIG_EPS > 1
|
||||||
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN;
|
USBHSD->ENDP_CONFIG = USBHS_UEP0_T_EN | USBHS_UEP0_R_EN | USBHS_UEP1_T_EN;
|
||||||
#else
|
#else
|
||||||
|
|
@ -610,12 +600,12 @@ void USBHS_InternalFinishSetup()
|
||||||
|
|
||||||
UEP_CTRL_H(0) = USBHS_UEP_R_RES_ACK | USBHS_UEP_T_RES_NAK;
|
UEP_CTRL_H(0) = USBHS_UEP_R_RES_ACK | USBHS_UEP_T_RES_NAK;
|
||||||
int i;
|
int i;
|
||||||
for( i = 1; i < HUSB_CONFIG_EPS; i++ )
|
for (i = 1; i < HUSB_CONFIG_EPS; i++)
|
||||||
UEP_CTRL_H(i) = USBFS_UEP_T_RES_NAK;
|
UEP_CTRL_H(i) = USBFS_UEP_T_RES_NAK;
|
||||||
|
|
||||||
for(uint8_t i=0; i< sizeof(HSUSBCTX.USBHS_Endp_Busy)/sizeof(HSUSBCTX.USBHS_Endp_Busy[0]); i++ )
|
for (uint8_t i = 0; i < sizeof(HSUSBCTX.USBHS_Endp_Busy) / sizeof(HSUSBCTX.USBHS_Endp_Busy[0]); i++)
|
||||||
{
|
{
|
||||||
HSUSBCTX.USBHS_Endp_Busy[ i ] = 0;
|
HSUSBCTX.USBHS_Endp_Busy[i] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -659,5 +649,3 @@ int HSUSBSetup()
|
||||||
// Go on-bus.
|
// Go on-bus.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
This is referenced in Chapter 22 USB Host/Device Controller (USBHD) of CH32FV2x_V3xRM.pdf
|
This is referenced in Chapter 22 USB Host/Device Controller (USBHD) of CH32FV2x_V3xRM.pdf
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "ch32fun.h"
|
#include "ch32fun.h"
|
||||||
#include "usb_defines.h"
|
|
||||||
#include "usb_config.h"
|
#include "usb_config.h"
|
||||||
|
#include "usb_defines.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
struct _USBState
|
struct _USBState
|
||||||
{
|
{
|
||||||
|
|
@ -26,12 +26,12 @@ struct _USBState
|
||||||
uint8_t USBHS_DevSleepStatus;
|
uint8_t USBHS_DevSleepStatus;
|
||||||
uint8_t USBHS_DevEnumStatus;
|
uint8_t USBHS_DevEnumStatus;
|
||||||
|
|
||||||
uint8_t * pCtrlPayloadPtr;
|
uint8_t *pCtrlPayloadPtr;
|
||||||
|
|
||||||
uint8_t ENDPOINTS[HUSB_CONFIG_EPS][64];
|
uint8_t ENDPOINTS[HUSB_CONFIG_EPS][64];
|
||||||
|
|
||||||
#define CTRL0BUFF (HSUSBCTX.ENDPOINTS[0])
|
#define CTRL0BUFF (HSUSBCTX.ENDPOINTS[0])
|
||||||
#define pUSBHS_SetupReqPak ((tusb_control_request_t*)CTRL0BUFF)
|
#define pUSBHS_SetupReqPak ((tusb_control_request_t *)CTRL0BUFF)
|
||||||
|
|
||||||
#if HUSB_HID_INTERFACES > 0
|
#if HUSB_HID_INTERFACES > 0
|
||||||
uint8_t USBHS_HidIdle[HUSB_HID_INTERFACES];
|
uint8_t USBHS_HidIdle[HUSB_HID_INTERFACES];
|
||||||
|
|
@ -46,36 +46,35 @@ uint8_t USBHS_Endp_DataUp(uint8_t endp, const uint8_t *pbuf, uint16_t len, uint8
|
||||||
|
|
||||||
// Implement the following:
|
// Implement the following:
|
||||||
#if HUSB_HID_USER_REPORTS
|
#if HUSB_HID_USER_REPORTS
|
||||||
int HandleHidUserGetReportSetup( struct _USBState * ctx, tusb_control_request_t * req );
|
int HandleHidUserGetReportSetup(struct _USBState *ctx, tusb_control_request_t *req);
|
||||||
int HandleHidUserSetReportSetup( struct _USBState * ctx, tusb_control_request_t * req );
|
int HandleHidUserSetReportSetup(struct _USBState *ctx, tusb_control_request_t *req);
|
||||||
void HandleHidUserReportDataOut( struct _USBState * ctx, uint8_t * data, int len );
|
void HandleHidUserReportDataOut(struct _USBState *ctx, uint8_t *data, int len);
|
||||||
int HandleHidUserReportDataIn( struct _USBState * ctx, uint8_t * data, int len );
|
int HandleHidUserReportDataIn(struct _USBState *ctx, uint8_t *data, int len);
|
||||||
void HandleHidUserReportOutComplete( struct _USBState * ctx );
|
void HandleHidUserReportOutComplete(struct _USBState *ctx);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HUSB_BULK_USER_REPORTS
|
#if HUSB_BULK_USER_REPORTS
|
||||||
void HandleGotEPComplete( struct _USBState * ctx, int ep );
|
void HandleGotEPComplete(struct _USBState *ctx, int ep);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern struct _USBState HSUSBCTX;
|
extern struct _USBState HSUSBCTX;
|
||||||
|
|
||||||
|
|
||||||
// To TX, you can use USBFS_GetEPBufferIfAvailable or USBHSD_UEP_TXBUF( endp )
|
// To TX, you can use USBFS_GetEPBufferIfAvailable or USBHSD_UEP_TXBUF( endp )
|
||||||
|
|
||||||
static inline uint8_t * USBHS_GetEPBufferIfAvailable( int endp )
|
static inline uint8_t *USBHS_GetEPBufferIfAvailable(int endp)
|
||||||
{
|
{
|
||||||
if( HSUSBCTX.USBHS_Endp_Busy[ endp ] ) return 0;
|
if (HSUSBCTX.USBHS_Endp_Busy[endp]) return 0;
|
||||||
return USBHSD_UEP_TXBUF( endp );
|
return USBHSD_UEP_TXBUF(endp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void USBHS_SendEndpoint( int endp, int len, const uint8_t * data )
|
static inline void USBHS_SendEndpoint(int endp, int len, const uint8_t *data)
|
||||||
{
|
{
|
||||||
if( endp )
|
if (endp)
|
||||||
{
|
{
|
||||||
(((uint32_t*)(&USBHSD->UEP1_TX_DMA))[2-1]) = (uintptr_t)data;
|
(((uint32_t *)(&USBHSD->UEP1_TX_DMA))[2 - 1]) = (uintptr_t)data;
|
||||||
}
|
}
|
||||||
USBHSD_UEP_TLEN( endp ) = len;
|
USBHSD_UEP_TLEN(endp) = len;
|
||||||
USBHSD_UEP_TXCTRL( endp ) = ( USBHSD_UEP_TXCTRL( endp ) & ~USBHS_UEP_T_RES_MASK ) | USBHS_UEP_T_RES_ACK;
|
USBHSD_UEP_TXCTRL(endp) = (USBHSD_UEP_TXCTRL(endp) & ~USBHS_UEP_T_RES_MASK) | USBHS_UEP_T_RES_ACK;
|
||||||
HSUSBCTX.USBHS_Endp_Busy[ endp ] = 0x01;
|
HSUSBCTX.USBHS_Endp_Busy[endp] = 0x01;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,30 @@
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* Psuedo Random Number Generator using a Linear Feedback Shift Register
|
* Psuedo Random Number Generator using a Linear Feedback Shift Register
|
||||||
* See the GitHub for more information:
|
* See the GitHub for more information:
|
||||||
* https://github.com/ADBeta/CH32V003_lib_rand
|
* https://github.com/ADBeta/CH32V003_lib_rand
|
||||||
*
|
*
|
||||||
* Ver 1.1 09 Sep 2024
|
* Ver 1.1 09 Sep 2024
|
||||||
*
|
*
|
||||||
* Released under the MIT Licence
|
* Released under the MIT Licence
|
||||||
* Copyright ADBeta (c) 2024
|
* Copyright ADBeta (c) 2024
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
* of this software and associated documentation files (the "Software"), to
|
* of this software and associated documentation files (the "Software"), to
|
||||||
* deal in the Software without restriction, including without limitation the
|
* deal in the Software without restriction, including without limitation the
|
||||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
* sell copies of the Software, and to permit persons to whom the Software is
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
* furnished to do so, subject to the following conditions:
|
* furnished to do so, subject to the following conditions:
|
||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*
|
*
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||||
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||||
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
* USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
#ifndef CH32V003_LIB_RAND
|
#ifndef CH32V003_LIB_RAND
|
||||||
#define CH32V003_LIB_RAND
|
#define CH32V003_LIB_RAND
|
||||||
|
|
||||||
|
|
@ -35,13 +35,12 @@
|
||||||
// Example: #define RANDOM_STRENGTH 2
|
// Example: #define RANDOM_STRENGTH 2
|
||||||
|
|
||||||
#ifndef RANDOM_STRENGTH
|
#ifndef RANDOM_STRENGTH
|
||||||
#error "Error in lib_rand. Must define RANDOM_STRENGTH"
|
#error "Error in lib_rand. Must define RANDOM_STRENGTH"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// @brief set the random LFSR values seed by default to a known-good value
|
// @brief set the random LFSR values seed by default to a known-good value
|
||||||
static uint32_t _rand_lfsr = 0x747AA32F;
|
static uint32_t _rand_lfsr = 0x747AA32F;
|
||||||
|
|
||||||
|
|
||||||
/*** Library specific Functions - Do Not Use *********************************/
|
/*** Library specific Functions - Do Not Use *********************************/
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
/// @brief Updates the LFSR by getting a new tap bit, for MSB, then shifting
|
/// @brief Updates the LFSR by getting a new tap bit, for MSB, then shifting
|
||||||
|
|
@ -65,7 +64,6 @@ uint8_t _rand_lfsr_update(void)
|
||||||
return msb >> 31;
|
return msb >> 31;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Generates a Random 32-bit number, using the LFSR - by generating
|
/// @brief Generates a Random 32-bit number, using the LFSR - by generating
|
||||||
/// a random bit from LFSR taps, 32 times.
|
/// a random bit from LFSR taps, 32 times.
|
||||||
/// @param None
|
/// @param None
|
||||||
|
|
@ -75,7 +73,7 @@ uint32_t _rand_gen_32b(void)
|
||||||
uint32_t rand_out = 0;
|
uint32_t rand_out = 0;
|
||||||
|
|
||||||
uint8_t bits = 32;
|
uint8_t bits = 32;
|
||||||
while(bits--)
|
while (bits--)
|
||||||
{
|
{
|
||||||
// Shift the current rand value for the new LSB
|
// Shift the current rand value for the new LSB
|
||||||
rand_out = rand_out << 1;
|
rand_out = rand_out << 1;
|
||||||
|
|
@ -86,17 +84,15 @@ uint32_t _rand_gen_32b(void)
|
||||||
return rand_out;
|
return rand_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// @brief Generates a Random n-bit number, using the LFSR - by generating
|
/// @brief Generates a Random n-bit number, using the LFSR - by generating
|
||||||
/// a random bit from LFSR taps, n times.
|
/// a random bit from LFSR taps, n times.
|
||||||
/// @param None
|
/// @param None
|
||||||
/// @return a (psuedo)random n-bit value
|
/// @return a (psuedo)random n-bit value
|
||||||
uint32_t _rand_gen_nb( int bits)
|
uint32_t _rand_gen_nb(int bits)
|
||||||
{
|
{
|
||||||
uint32_t rand_out = 0;
|
uint32_t rand_out = 0;
|
||||||
|
|
||||||
while(bits--)
|
while (bits--)
|
||||||
{
|
{
|
||||||
// Shift the current rand value for the new LSB
|
// Shift the current rand value for the new LSB
|
||||||
rand_out = rand_out << 1;
|
rand_out = rand_out << 1;
|
||||||
|
|
@ -107,7 +103,6 @@ uint32_t _rand_gen_nb( int bits)
|
||||||
return rand_out;
|
return rand_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*** API Functions ***********************************************************/
|
/*** API Functions ***********************************************************/
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/// @brief seeds the Random LFSR to the value passed
|
/// @brief seeds the Random LFSR to the value passed
|
||||||
|
|
@ -118,7 +113,6 @@ void seed(const uint32_t seed_val)
|
||||||
_rand_lfsr = seed_val;
|
_rand_lfsr = seed_val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @brief Generates a Random (32-bit) Number, based on the RANDOM_STRENGTH
|
/// @brief Generates a Random (32-bit) Number, based on the RANDOM_STRENGTH
|
||||||
/// you have selected
|
/// you have selected
|
||||||
/// @param None
|
/// @param None
|
||||||
|
|
@ -127,26 +121,26 @@ uint32_t rand(void)
|
||||||
{
|
{
|
||||||
uint32_t rand_out = 0;
|
uint32_t rand_out = 0;
|
||||||
|
|
||||||
// If RANDOM_STRENGTH is level 1, Update LFSR Once, then return it
|
// If RANDOM_STRENGTH is level 1, Update LFSR Once, then return it
|
||||||
#if RANDOM_STRENGTH == 1
|
#if RANDOM_STRENGTH == 1
|
||||||
// Update the LFSR, discard result, and return _lsfr raw
|
// Update the LFSR, discard result, and return _lsfr raw
|
||||||
(void)_rand_lfsr_update();
|
(void)_rand_lfsr_update();
|
||||||
rand_out = _rand_lfsr;
|
rand_out = _rand_lfsr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If RANDOM_STRENGTH is level 2, generate a 32-bit output, using 32 random
|
// If RANDOM_STRENGTH is level 2, generate a 32-bit output, using 32 random
|
||||||
// bits from the LFSR
|
// bits from the LFSR
|
||||||
#if RANDOM_STRENGTH == 2
|
#if RANDOM_STRENGTH == 2
|
||||||
rand_out = _rand_gen_32b();
|
rand_out = _rand_gen_32b();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// If RANDOM_STRENGTH is level 3, generate 2 32-bit outputs, then XOR them
|
// If RANDOM_STRENGTH is level 3, generate 2 32-bit outputs, then XOR them
|
||||||
// together
|
// together
|
||||||
#if RANDOM_STRENGTH == 3
|
#if RANDOM_STRENGTH == 3
|
||||||
uint32_t rand_a = _rand_gen_32b();
|
uint32_t rand_a = _rand_gen_32b();
|
||||||
uint32_t rand_b = _rand_gen_32b();
|
uint32_t rand_b = _rand_gen_32b();
|
||||||
rand_out = rand_a ^ rand_b;
|
rand_out = rand_a ^ rand_b;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return rand_out;
|
return rand_out;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,19 +6,19 @@
|
||||||
#ifndef _SSD1306_H
|
#ifndef _SSD1306_H
|
||||||
#define _SSD1306_H
|
#define _SSD1306_H
|
||||||
|
|
||||||
|
#include "font_8x8.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "font_8x8.h"
|
|
||||||
|
|
||||||
// comfortable packet size for this OLED
|
// comfortable packet size for this OLED
|
||||||
#define SSD1306_PSZ 32
|
#define SSD1306_PSZ 32
|
||||||
|
|
||||||
#if defined (SSD1306_CUSTOM)
|
#if defined(SSD1306_CUSTOM)
|
||||||
// Let the caller configure the OLED.
|
// Let the caller configure the OLED.
|
||||||
#else
|
#else
|
||||||
// characteristics of each type
|
// characteristics of each type
|
||||||
#if !defined (SSD1306_64X32) && !defined (SSD1306_128X32) && !defined (SSD1306_128X64) && !defined (SH1107_128x128) && !(defined(SSD1306_W) && defined(SSD1306_H) && defined(SSD1306_OFFSET) )
|
#if !defined(SSD1306_64X32) && !defined(SSD1306_128X32) && !defined(SSD1306_128X64) && !defined(SH1107_128x128) && !(defined(SSD1306_W) && defined(SSD1306_H) && defined(SSD1306_OFFSET))
|
||||||
#error "Please define the SSD1306_WXH resolution used in your application"
|
#error "Please define the SSD1306_WXH resolution used in your application"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SSD1306_64X32
|
#ifdef SSD1306_64X32
|
||||||
|
|
@ -98,13 +98,13 @@ uint8_t ssd1306_data(uint8_t *data, int sz)
|
||||||
/* choose VCC mode */
|
/* choose VCC mode */
|
||||||
#define SSD1306_EXTERNALVCC 0x1
|
#define SSD1306_EXTERNALVCC 0x1
|
||||||
#define SSD1306_SWITCHCAPVCC 0x2
|
#define SSD1306_SWITCHCAPVCC 0x2
|
||||||
//#define vccstate SSD1306_EXTERNALVCC
|
// #define vccstate SSD1306_EXTERNALVCC
|
||||||
#define vccstate SSD1306_SWITCHCAPVCC
|
#define vccstate SSD1306_SWITCHCAPVCC
|
||||||
|
|
||||||
#if !defined(SSD1306_CUSTOM_INIT_ARRAY) || !SSD1306_CUSTOM_INIT_ARRAY
|
#if !defined(SSD1306_CUSTOM_INIT_ARRAY) || !SSD1306_CUSTOM_INIT_ARRAY
|
||||||
// OLED initialization commands for 128x32
|
// OLED initialization commands for 128x32
|
||||||
const uint8_t ssd1306_init_array[] =
|
const uint8_t ssd1306_init_array[] =
|
||||||
{
|
{
|
||||||
#ifdef SH1107
|
#ifdef SH1107
|
||||||
SSD1306_DISPLAYOFF, // Turn OLED off
|
SSD1306_DISPLAYOFF, // Turn OLED off
|
||||||
0x00, // Low column
|
0x00, // Low column
|
||||||
|
|
@ -114,7 +114,7 @@ const uint8_t ssd1306_init_array[] =
|
||||||
SSD1306_SETCONTRAST, 0x6f, // Set constrast
|
SSD1306_SETCONTRAST, 0x6f, // Set constrast
|
||||||
SSD1306_COLUMNADDR, // Set memory addressing mode
|
SSD1306_COLUMNADDR, // Set memory addressing mode
|
||||||
SSD1306_DISPLAYALLON_RESUME, // normal (as opposed to invert colors, always on or off.)
|
SSD1306_DISPLAYALLON_RESUME, // normal (as opposed to invert colors, always on or off.)
|
||||||
SSD1306_SETMULTIPLEX, (SSD1306_H-1), // Iterate over all 128 rows (Multiplex Ratio)
|
SSD1306_SETMULTIPLEX, (SSD1306_H - 1), // Iterate over all 128 rows (Multiplex Ratio)
|
||||||
SSD1306_SETDISPLAYOFFSET, 0x00, // Set display offset // Where this appears on-screen (Some displays will be different)
|
SSD1306_SETDISPLAYOFFSET, 0x00, // Set display offset // Where this appears on-screen (Some displays will be different)
|
||||||
SSD1306_SETDISPLAYCLOCKDIV, 0xf0, // Set precharge properties. THIS IS A LIE This has todo with timing. <<< This makes it go brrrrrrrrr
|
SSD1306_SETDISPLAYCLOCKDIV, 0xf0, // Set precharge properties. THIS IS A LIE This has todo with timing. <<< This makes it go brrrrrrrrr
|
||||||
SSD1306_SETPRECHARGE, 0x1d, // Set pre-charge period (This controls brightness)
|
SSD1306_SETPRECHARGE, 0x1d, // Set pre-charge period (This controls brightness)
|
||||||
|
|
@ -125,7 +125,7 @@ const uint8_t ssd1306_init_array[] =
|
||||||
SSD1306_SETPRECHARGE, 0x06, // ???? No idea what this does, but this looks best.
|
SSD1306_SETPRECHARGE, 0x06, // ???? No idea what this does, but this looks best.
|
||||||
SSD1306_SETCONTRAST, 0xfe, // Set constrast
|
SSD1306_SETCONTRAST, 0xfe, // Set constrast
|
||||||
SSD1306_SETVCOMDETECT, 0xfe, // Set vcomh
|
SSD1306_SETVCOMDETECT, 0xfe, // Set vcomh
|
||||||
SSD1306_SETMULTIPLEX, (SSD1306_H-1), // 128-wide.
|
SSD1306_SETMULTIPLEX, (SSD1306_H - 1), // 128-wide.
|
||||||
SSD1306_DISPLAYON, // Display on.
|
SSD1306_DISPLAYON, // Display on.
|
||||||
#else
|
#else
|
||||||
SSD1306_DISPLAYOFF, // 0xAE
|
SSD1306_DISPLAYOFF, // 0xAE
|
||||||
|
|
@ -165,7 +165,7 @@ const uint8_t ssd1306_init_array[] =
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// the display buffer
|
// the display buffer
|
||||||
uint8_t ssd1306_buffer[SSD1306_W*SSD1306_H/8];
|
uint8_t ssd1306_buffer[SSD1306_W * SSD1306_H / 8];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set the buffer to a color
|
* set the buffer to a color
|
||||||
|
|
@ -180,11 +180,23 @@ void ssd1306_setbuf(uint8_t color)
|
||||||
* expansion array for OLED with every other row unused
|
* expansion array for OLED with every other row unused
|
||||||
*/
|
*/
|
||||||
const uint8_t expand[16] =
|
const uint8_t expand[16] =
|
||||||
{
|
{
|
||||||
0x00,0x02,0x08,0x0a,
|
0x00,
|
||||||
0x20,0x22,0x28,0x2a,
|
0x02,
|
||||||
0x80,0x82,0x88,0x8a,
|
0x08,
|
||||||
0xa0,0xa2,0xa8,0xaa,
|
0x0a,
|
||||||
|
0x20,
|
||||||
|
0x22,
|
||||||
|
0x28,
|
||||||
|
0x2a,
|
||||||
|
0x80,
|
||||||
|
0x82,
|
||||||
|
0x88,
|
||||||
|
0x8a,
|
||||||
|
0xa0,
|
||||||
|
0xa2,
|
||||||
|
0xa8,
|
||||||
|
0xaa,
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -199,20 +211,20 @@ void ssd1306_refresh(void)
|
||||||
|
|
||||||
ssd1306_cmd(SSD1306_MEMORYMODE); // vertical addressing mode.
|
ssd1306_cmd(SSD1306_MEMORYMODE); // vertical addressing mode.
|
||||||
|
|
||||||
for(i=0;i<SSD1306_H/8;i++)
|
for (i = 0; i < SSD1306_H / 8; i++)
|
||||||
{
|
{
|
||||||
ssd1306_cmd(0xb0 | i);
|
ssd1306_cmd(0xb0 | i);
|
||||||
ssd1306_cmd( 0x00 | (0&0xf) );
|
ssd1306_cmd(0x00 | (0 & 0xf));
|
||||||
ssd1306_cmd( 0x10 | (0>>4) );
|
ssd1306_cmd(0x10 | (0 >> 4));
|
||||||
ssd1306_data(&ssd1306_buffer[i*4*SSD1306_PSZ+0*SSD1306_PSZ], SSD1306_PSZ);
|
ssd1306_data(&ssd1306_buffer[i * 4 * SSD1306_PSZ + 0 * SSD1306_PSZ], SSD1306_PSZ);
|
||||||
ssd1306_data(&ssd1306_buffer[i*4*SSD1306_PSZ+1*SSD1306_PSZ], SSD1306_PSZ);
|
ssd1306_data(&ssd1306_buffer[i * 4 * SSD1306_PSZ + 1 * SSD1306_PSZ], SSD1306_PSZ);
|
||||||
ssd1306_data(&ssd1306_buffer[i*4*SSD1306_PSZ+2*SSD1306_PSZ], SSD1306_PSZ);
|
ssd1306_data(&ssd1306_buffer[i * 4 * SSD1306_PSZ + 2 * SSD1306_PSZ], SSD1306_PSZ);
|
||||||
ssd1306_data(&ssd1306_buffer[i*4*SSD1306_PSZ+3*SSD1306_PSZ], SSD1306_PSZ);
|
ssd1306_data(&ssd1306_buffer[i * 4 * SSD1306_PSZ + 3 * SSD1306_PSZ], SSD1306_PSZ);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ssd1306_cmd(SSD1306_COLUMNADDR);
|
ssd1306_cmd(SSD1306_COLUMNADDR);
|
||||||
ssd1306_cmd(SSD1306_OFFSET); // Column start address (0 = reset)
|
ssd1306_cmd(SSD1306_OFFSET); // Column start address (0 = reset)
|
||||||
ssd1306_cmd(SSD1306_OFFSET+SSD1306_W-1); // Column end address (127 = reset)
|
ssd1306_cmd(SSD1306_OFFSET + SSD1306_W - 1); // Column end address (127 = reset)
|
||||||
|
|
||||||
ssd1306_cmd(SSD1306_PAGEADDR);
|
ssd1306_cmd(SSD1306_PAGEADDR);
|
||||||
ssd1306_cmd(0); // Page start address (0 = reset)
|
ssd1306_cmd(0); // Page start address (0 = reset)
|
||||||
|
|
@ -220,7 +232,7 @@ void ssd1306_refresh(void)
|
||||||
|
|
||||||
#ifdef SSD1306_FULLUSE
|
#ifdef SSD1306_FULLUSE
|
||||||
/* for fully used rows just plow thru everything */
|
/* for fully used rows just plow thru everything */
|
||||||
for(i=0;i<sizeof(ssd1306_buffer);i+=SSD1306_PSZ)
|
for (i = 0; i < sizeof(ssd1306_buffer); i += SSD1306_PSZ)
|
||||||
{
|
{
|
||||||
/* send PSZ block of data */
|
/* send PSZ block of data */
|
||||||
ssd1306_data(&ssd1306_buffer[i], SSD1306_PSZ);
|
ssd1306_data(&ssd1306_buffer[i], SSD1306_PSZ);
|
||||||
|
|
@ -228,23 +240,23 @@ void ssd1306_refresh(void)
|
||||||
#else
|
#else
|
||||||
/* for displays with odd rows unused expand bytes */
|
/* for displays with odd rows unused expand bytes */
|
||||||
uint8_t tbuf[SSD1306_PSZ], j, k;
|
uint8_t tbuf[SSD1306_PSZ], j, k;
|
||||||
for(i=0;i<sizeof(ssd1306_buffer);i+=128)
|
for (i = 0; i < sizeof(ssd1306_buffer); i += 128)
|
||||||
{
|
{
|
||||||
/* low nybble */
|
/* low nybble */
|
||||||
for(j=0;j<128;j+=SSD1306_PSZ)
|
for (j = 0; j < 128; j += SSD1306_PSZ)
|
||||||
{
|
{
|
||||||
for(k=0;k<SSD1306_PSZ;k++)
|
for (k = 0; k < SSD1306_PSZ; k++)
|
||||||
tbuf[k] = expand[ssd1306_buffer[i+j+k]&0xf];
|
tbuf[k] = expand[ssd1306_buffer[i + j + k] & 0xf];
|
||||||
|
|
||||||
/* send PSZ block of data */
|
/* send PSZ block of data */
|
||||||
ssd1306_data(tbuf, SSD1306_PSZ);
|
ssd1306_data(tbuf, SSD1306_PSZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* high nybble */
|
/* high nybble */
|
||||||
for(j=0;j<128;j+=SSD1306_PSZ)
|
for (j = 0; j < 128; j += SSD1306_PSZ)
|
||||||
{
|
{
|
||||||
for(k=0;k<SSD1306_PSZ;k++)
|
for (k = 0; k < SSD1306_PSZ; k++)
|
||||||
tbuf[k] = expand[(ssd1306_buffer[i+j+k]>>4)&0xf];
|
tbuf[k] = expand[(ssd1306_buffer[i + j + k] >> 4) & 0xf];
|
||||||
|
|
||||||
/* send PSZ block of data */
|
/* send PSZ block of data */
|
||||||
ssd1306_data(tbuf, SSD1306_PSZ);
|
ssd1306_data(tbuf, SSD1306_PSZ);
|
||||||
|
|
@ -252,7 +264,6 @@ void ssd1306_refresh(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -263,19 +274,19 @@ void ssd1306_drawPixel(uint32_t x, uint32_t y, int color)
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
|
|
||||||
/* clip */
|
/* clip */
|
||||||
if(x >= SSD1306_W)
|
if (x >= SSD1306_W)
|
||||||
return;
|
return;
|
||||||
if(y >= SSD1306_H)
|
if (y >= SSD1306_H)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* compute buffer address */
|
/* compute buffer address */
|
||||||
addr = x + SSD1306_W*(y/8);
|
addr = x + SSD1306_W * (y / 8);
|
||||||
|
|
||||||
/* set/clear bit in buffer */
|
/* set/clear bit in buffer */
|
||||||
if(color)
|
if (color)
|
||||||
ssd1306_buffer[addr] |= (1<<(y&7));
|
ssd1306_buffer[addr] |= (1 << (y & 7));
|
||||||
else
|
else
|
||||||
ssd1306_buffer[addr] &= ~(1<<(y&7));
|
ssd1306_buffer[addr] &= ~(1 << (y & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -286,31 +297,34 @@ void ssd1306_xorPixel(uint32_t x, uint32_t y)
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
|
|
||||||
/* clip */
|
/* clip */
|
||||||
if(x >= SSD1306_W)
|
if (x >= SSD1306_W)
|
||||||
return;
|
return;
|
||||||
if(y >= SSD1306_H)
|
if (y >= SSD1306_H)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* compute buffer address */
|
/* compute buffer address */
|
||||||
addr = x + SSD1306_W*(y/8);
|
addr = x + SSD1306_W * (y / 8);
|
||||||
|
|
||||||
ssd1306_buffer[addr] ^= (1<<(y&7));
|
ssd1306_buffer[addr] ^= (1 << (y & 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* draw a an image from an array, directly into to the display buffer
|
* draw a an image from an array, directly into to the display buffer
|
||||||
* the color modes allow for overwriting and even layering (sprites!)
|
* the color modes allow for overwriting and even layering (sprites!)
|
||||||
*/
|
*/
|
||||||
void ssd1306_drawImage(uint32_t x, uint32_t y, const unsigned char* input, uint32_t width, uint32_t height, uint32_t color_mode) {
|
void ssd1306_drawImage(uint32_t x, uint32_t y, const unsigned char *input, uint32_t width, uint32_t height, uint32_t color_mode)
|
||||||
|
{
|
||||||
uint32_t x_absolute;
|
uint32_t x_absolute;
|
||||||
uint32_t y_absolute;
|
uint32_t y_absolute;
|
||||||
uint32_t pixel;
|
uint32_t pixel;
|
||||||
uint32_t bytes_to_draw = width / 8;
|
uint32_t bytes_to_draw = width / 8;
|
||||||
uint32_t buffer_addr;
|
uint32_t buffer_addr;
|
||||||
|
|
||||||
for (uint32_t line = 0; line < height; line++) {
|
for (uint32_t line = 0; line < height; line++)
|
||||||
|
{
|
||||||
y_absolute = y + line;
|
y_absolute = y + line;
|
||||||
if (y_absolute >= SSD1306_H) {
|
if (y_absolute >= SSD1306_H)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -318,12 +332,15 @@ void ssd1306_drawImage(uint32_t x, uint32_t y, const unsigned char* input, uint3
|
||||||
// bitmask for current pixel in vertical (output) byte
|
// bitmask for current pixel in vertical (output) byte
|
||||||
uint32_t v_mask = 1 << (y_absolute & 7);
|
uint32_t v_mask = 1 << (y_absolute & 7);
|
||||||
|
|
||||||
for (uint32_t byte = 0; byte < bytes_to_draw; byte++) {
|
for (uint32_t byte = 0; byte < bytes_to_draw; byte++)
|
||||||
|
{
|
||||||
uint32_t input_byte = input[byte + line * bytes_to_draw];
|
uint32_t input_byte = input[byte + line * bytes_to_draw];
|
||||||
|
|
||||||
for (pixel = 0; pixel < 8; pixel++) {
|
for (pixel = 0; pixel < 8; pixel++)
|
||||||
|
{
|
||||||
x_absolute = x + 8 * (bytes_to_draw - byte) + pixel;
|
x_absolute = x + 8 * (bytes_to_draw - byte) + pixel;
|
||||||
if (x_absolute >= SSD1306_W) {
|
if (x_absolute >= SSD1306_W)
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// looking at the horizontal display, we're drawing bytes bottom to top, not left to right, hence y / 8
|
// looking at the horizontal display, we're drawing bytes bottom to top, not left to right, hence y / 8
|
||||||
|
|
@ -331,7 +348,8 @@ void ssd1306_drawImage(uint32_t x, uint32_t y, const unsigned char* input, uint3
|
||||||
// state of current pixel
|
// state of current pixel
|
||||||
uint8_t input_pixel = input_byte & (1 << pixel);
|
uint8_t input_pixel = input_byte & (1 << pixel);
|
||||||
|
|
||||||
switch (color_mode) {
|
switch (color_mode)
|
||||||
|
{
|
||||||
case 0:
|
case 0:
|
||||||
// write pixels as they are
|
// write pixels as they are
|
||||||
ssd1306_buffer[buffer_addr] = (ssd1306_buffer[buffer_addr] & ~v_mask) | (input_pixel ? v_mask : 0);
|
ssd1306_buffer[buffer_addr] = (ssd1306_buffer[buffer_addr] & ~v_mask) | (input_pixel ? v_mask : 0);
|
||||||
|
|
@ -358,13 +376,13 @@ void ssd1306_drawImage(uint32_t x, uint32_t y, const unsigned char* input, uint3
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if SSD1306_LOG_IMAGE == 1
|
#if SSD1306_LOG_IMAGE == 1
|
||||||
printf("%02x ", input_byte);
|
printf("%02x ", input_byte);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#if SSD1306_LOG_IMAGE == 1
|
#if SSD1306_LOG_IMAGE == 1
|
||||||
printf("\n\r");
|
printf("\n\r");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -374,9 +392,9 @@ void ssd1306_drawImage(uint32_t x, uint32_t y, const unsigned char* input, uint3
|
||||||
void ssd1306_drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
|
void ssd1306_drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
|
||||||
{
|
{
|
||||||
// clipping
|
// clipping
|
||||||
if((x >= SSD1306_W) || (y >= SSD1306_H)) return;
|
if ((x >= SSD1306_W) || (y >= SSD1306_H)) return;
|
||||||
if((y+h-1) >= SSD1306_H) h = SSD1306_H-y;
|
if ((y + h - 1) >= SSD1306_H) h = SSD1306_H - y;
|
||||||
while(h--)
|
while (h--)
|
||||||
{
|
{
|
||||||
ssd1306_drawPixel(x, y++, color);
|
ssd1306_drawPixel(x, y++, color);
|
||||||
}
|
}
|
||||||
|
|
@ -388,8 +406,8 @@ void ssd1306_drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
|
||||||
void ssd1306_drawFastHLine(uint32_t x, uint32_t y, uint32_t w, uint32_t color)
|
void ssd1306_drawFastHLine(uint32_t x, uint32_t y, uint32_t w, uint32_t color)
|
||||||
{
|
{
|
||||||
// clipping
|
// clipping
|
||||||
if((x >= SSD1306_W) || (y >= SSD1306_H)) return;
|
if ((x >= SSD1306_W) || (y >= SSD1306_H)) return;
|
||||||
if((x+w-1) >= SSD1306_W) w = SSD1306_W-x;
|
if ((x + w - 1) >= SSD1306_W) w = SSD1306_W - x;
|
||||||
|
|
||||||
while (w--)
|
while (w--)
|
||||||
{
|
{
|
||||||
|
|
@ -402,7 +420,7 @@ void ssd1306_drawFastHLine(uint32_t x, uint32_t y, uint32_t w, uint32_t color)
|
||||||
*/
|
*/
|
||||||
int gfx_abs(int x)
|
int gfx_abs(int x)
|
||||||
{
|
{
|
||||||
return (x<0) ? -x : x;
|
return (x < 0) ? -x : x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -426,14 +444,14 @@ void ssd1306_drawLine(int x0, int y0, int x1, int y1, uint32_t color)
|
||||||
/* flip sense 45deg to keep error calc in range */
|
/* flip sense 45deg to keep error calc in range */
|
||||||
steep = (gfx_abs(y1 - y0) > gfx_abs(x1 - x0));
|
steep = (gfx_abs(y1 - y0) > gfx_abs(x1 - x0));
|
||||||
|
|
||||||
if(steep)
|
if (steep)
|
||||||
{
|
{
|
||||||
gfx_swap(&x0, &y0);
|
gfx_swap(&x0, &y0);
|
||||||
gfx_swap(&x1, &y1);
|
gfx_swap(&x1, &y1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* run low->high */
|
/* run low->high */
|
||||||
if(x0 > x1)
|
if (x0 > x1)
|
||||||
{
|
{
|
||||||
gfx_swap(&x0, &x1);
|
gfx_swap(&x0, &x1);
|
||||||
gfx_swap(&y0, &y1);
|
gfx_swap(&y0, &y1);
|
||||||
|
|
@ -442,18 +460,18 @@ void ssd1306_drawLine(int x0, int y0, int x1, int y1, uint32_t color)
|
||||||
/* set up loop initial conditions */
|
/* set up loop initial conditions */
|
||||||
deltax = x1 - x0;
|
deltax = x1 - x0;
|
||||||
deltay = gfx_abs(y1 - y0);
|
deltay = gfx_abs(y1 - y0);
|
||||||
error = deltax/2;
|
error = deltax / 2;
|
||||||
y = y0;
|
y = y0;
|
||||||
if(y0 < y1)
|
if (y0 < y1)
|
||||||
ystep = 1;
|
ystep = 1;
|
||||||
else
|
else
|
||||||
ystep = -1;
|
ystep = -1;
|
||||||
|
|
||||||
/* loop x */
|
/* loop x */
|
||||||
for(x=x0;x<=x1;x++)
|
for (x = x0; x <= x1; x++)
|
||||||
{
|
{
|
||||||
/* plot point */
|
/* plot point */
|
||||||
if(steep)
|
if (steep)
|
||||||
/* flip point & plot */
|
/* flip point & plot */
|
||||||
ssd1306_drawPixel(y, x, color);
|
ssd1306_drawPixel(y, x, color);
|
||||||
else
|
else
|
||||||
|
|
@ -464,7 +482,7 @@ void ssd1306_drawLine(int x0, int y0, int x1, int y1, uint32_t color)
|
||||||
error = error - deltay;
|
error = error - deltay;
|
||||||
|
|
||||||
/* update y */
|
/* update y */
|
||||||
if(error < 0)
|
if (error < 0)
|
||||||
{
|
{
|
||||||
y = y + ystep;
|
y = y + ystep;
|
||||||
error = error + deltax;
|
error = error + deltax;
|
||||||
|
|
@ -483,19 +501,23 @@ void ssd1306_drawCircle(int x, int y, int radius, int color)
|
||||||
int err = 2 - 2 * radius;
|
int err = 2 - 2 * radius;
|
||||||
int e2;
|
int e2;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
ssd1306_drawPixel(x - x_pos, y + y_pos, color);
|
ssd1306_drawPixel(x - x_pos, y + y_pos, color);
|
||||||
ssd1306_drawPixel(x + x_pos, y + y_pos, color);
|
ssd1306_drawPixel(x + x_pos, y + y_pos, color);
|
||||||
ssd1306_drawPixel(x + x_pos, y - y_pos, color);
|
ssd1306_drawPixel(x + x_pos, y - y_pos, color);
|
||||||
ssd1306_drawPixel(x - x_pos, y - y_pos, color);
|
ssd1306_drawPixel(x - x_pos, y - y_pos, color);
|
||||||
e2 = err;
|
e2 = err;
|
||||||
if (e2 <= y_pos) {
|
if (e2 <= y_pos)
|
||||||
|
{
|
||||||
err += ++y_pos * 2 + 1;
|
err += ++y_pos * 2 + 1;
|
||||||
if(-x_pos == y_pos && e2 <= x_pos) {
|
if (-x_pos == y_pos && e2 <= x_pos)
|
||||||
|
{
|
||||||
e2 = 0;
|
e2 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (e2 > x_pos) {
|
if (e2 > x_pos)
|
||||||
|
{
|
||||||
err += ++x_pos * 2 + 1;
|
err += ++x_pos * 2 + 1;
|
||||||
}
|
}
|
||||||
} while (x_pos <= 0);
|
} while (x_pos <= 0);
|
||||||
|
|
@ -512,7 +534,8 @@ void ssd1306_fillCircle(int x, int y, int radius, int color)
|
||||||
int err = 2 - 2 * radius;
|
int err = 2 - 2 * radius;
|
||||||
int e2;
|
int e2;
|
||||||
|
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
ssd1306_drawPixel(x - x_pos, y + y_pos, color);
|
ssd1306_drawPixel(x - x_pos, y + y_pos, color);
|
||||||
ssd1306_drawPixel(x + x_pos, y + y_pos, color);
|
ssd1306_drawPixel(x + x_pos, y + y_pos, color);
|
||||||
ssd1306_drawPixel(x + x_pos, y - y_pos, color);
|
ssd1306_drawPixel(x + x_pos, y - y_pos, color);
|
||||||
|
|
@ -520,16 +543,19 @@ void ssd1306_fillCircle(int x, int y, int radius, int color)
|
||||||
ssd1306_drawFastHLine(x + x_pos, y + y_pos, 2 * (-x_pos) + 1, color);
|
ssd1306_drawFastHLine(x + x_pos, y + y_pos, 2 * (-x_pos) + 1, color);
|
||||||
ssd1306_drawFastHLine(x + x_pos, y - y_pos, 2 * (-x_pos) + 1, color);
|
ssd1306_drawFastHLine(x + x_pos, y - y_pos, 2 * (-x_pos) + 1, color);
|
||||||
e2 = err;
|
e2 = err;
|
||||||
if (e2 <= y_pos) {
|
if (e2 <= y_pos)
|
||||||
|
{
|
||||||
err += ++y_pos * 2 + 1;
|
err += ++y_pos * 2 + 1;
|
||||||
if(-x_pos == y_pos && e2 <= x_pos) {
|
if (-x_pos == y_pos && e2 <= x_pos)
|
||||||
|
{
|
||||||
e2 = 0;
|
e2 = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(e2 > x_pos) {
|
if (e2 > x_pos)
|
||||||
|
{
|
||||||
err += ++x_pos * 2 + 1;
|
err += ++x_pos * 2 + 1;
|
||||||
}
|
}
|
||||||
} while(x_pos <= 0);
|
} while (x_pos <= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -538,9 +564,9 @@ void ssd1306_fillCircle(int x, int y, int radius, int color)
|
||||||
void ssd1306_drawRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint32_t color)
|
void ssd1306_drawRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint32_t color)
|
||||||
{
|
{
|
||||||
ssd1306_drawFastVLine(x, y, h, color);
|
ssd1306_drawFastVLine(x, y, h, color);
|
||||||
ssd1306_drawFastVLine(x+w-1, y, h, color);
|
ssd1306_drawFastVLine(x + w - 1, y, h, color);
|
||||||
ssd1306_drawFastHLine(x, y, w, color);
|
ssd1306_drawFastHLine(x, y, w, color);
|
||||||
ssd1306_drawFastHLine(x, y+h-1, w, color);
|
ssd1306_drawFastHLine(x, y + h - 1, w, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -548,15 +574,15 @@ void ssd1306_drawRect(int32_t x, int32_t y, uint32_t w, uint32_t h, uint32_t col
|
||||||
*/
|
*/
|
||||||
void ssd1306_fillRect(uint32_t x, uint32_t y, uint8_t w, uint32_t h, uint32_t color)
|
void ssd1306_fillRect(uint32_t x, uint32_t y, uint8_t w, uint32_t h, uint32_t color)
|
||||||
{
|
{
|
||||||
uint32_t m, n=y, iw = w;
|
uint32_t m, n = y, iw = w;
|
||||||
|
|
||||||
/* scan vertical */
|
/* scan vertical */
|
||||||
while(h--)
|
while (h--)
|
||||||
{
|
{
|
||||||
m=x;
|
m = x;
|
||||||
w=iw;
|
w = iw;
|
||||||
/* scan horizontal */
|
/* scan horizontal */
|
||||||
while(w--)
|
while (w--)
|
||||||
{
|
{
|
||||||
/* invert pixels */
|
/* invert pixels */
|
||||||
ssd1306_drawPixel(m++, n, color);
|
ssd1306_drawPixel(m++, n, color);
|
||||||
|
|
@ -570,15 +596,15 @@ void ssd1306_fillRect(uint32_t x, uint32_t y, uint8_t w, uint32_t h, uint32_t co
|
||||||
*/
|
*/
|
||||||
void ssd1306_xorrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
|
void ssd1306_xorrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
|
||||||
{
|
{
|
||||||
uint8_t m, n=y, iw = w;
|
uint8_t m, n = y, iw = w;
|
||||||
|
|
||||||
/* scan vertical */
|
/* scan vertical */
|
||||||
while(h--)
|
while (h--)
|
||||||
{
|
{
|
||||||
m=x;
|
m = x;
|
||||||
w=iw;
|
w = iw;
|
||||||
/* scan horizontal */
|
/* scan horizontal */
|
||||||
while(w--)
|
while (w--)
|
||||||
{
|
{
|
||||||
/* invert pixels */
|
/* invert pixels */
|
||||||
ssd1306_xorPixel(m++, n);
|
ssd1306_xorPixel(m++, n);
|
||||||
|
|
@ -595,17 +621,17 @@ void ssd1306_drawchar(uint8_t x, uint8_t y, uint8_t chr, uint8_t color)
|
||||||
uint16_t i, j, col;
|
uint16_t i, j, col;
|
||||||
uint8_t d;
|
uint8_t d;
|
||||||
|
|
||||||
for(i=0;i<8;i++)
|
for (i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
d = fontdata[(chr<<3)+i];
|
d = fontdata[(chr << 3) + i];
|
||||||
for(j=0;j<8;j++)
|
for (j = 0; j < 8; j++)
|
||||||
{
|
{
|
||||||
if(d&0x80)
|
if (d & 0x80)
|
||||||
col = color;
|
col = color;
|
||||||
else
|
else
|
||||||
col = (~color)&1;
|
col = (~color) & 1;
|
||||||
|
|
||||||
ssd1306_drawPixel(x+j, y+i, col);
|
ssd1306_drawPixel(x + j, y + i, col);
|
||||||
|
|
||||||
// next bit
|
// next bit
|
||||||
d <<= 1;
|
d <<= 1;
|
||||||
|
|
@ -620,11 +646,11 @@ void ssd1306_drawstr(uint8_t x, uint8_t y, char *str, uint8_t color)
|
||||||
{
|
{
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
|
||||||
while((c=*str++))
|
while ((c = *str++))
|
||||||
{
|
{
|
||||||
ssd1306_drawchar(x, y, c, color);
|
ssd1306_drawchar(x, y, c, color);
|
||||||
x += 8;
|
x += 8;
|
||||||
if(x>120)
|
if (x > 120)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -632,7 +658,8 @@ void ssd1306_drawstr(uint8_t x, uint8_t y, char *str, uint8_t color)
|
||||||
/*
|
/*
|
||||||
* enum for font size
|
* enum for font size
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum
|
||||||
|
{
|
||||||
fontsize_8x8 = 1,
|
fontsize_8x8 = 1,
|
||||||
fontsize_16x16 = 2,
|
fontsize_16x16 = 2,
|
||||||
fontsize_32x32 = 4,
|
fontsize_32x32 = 4,
|
||||||
|
|
@ -666,8 +693,10 @@ void ssd1306_drawchar_sz(uint8_t x, uint8_t y, uint8_t chr, uint8_t color, font_
|
||||||
col = (~color) & 1;
|
col = (~color) & 1;
|
||||||
|
|
||||||
// Draw the pixel at the original size and scaled size using nested for-loops
|
// Draw the pixel at the original size and scaled size using nested for-loops
|
||||||
for (uint8_t k = 0; k < font_scale; k++) {
|
for (uint8_t k = 0; k < font_scale; k++)
|
||||||
for (uint8_t l = 0; l < font_scale; l++) {
|
{
|
||||||
|
for (uint8_t l = 0; l < font_scale; l++)
|
||||||
|
{
|
||||||
ssd1306_drawPixel(x + (j * font_scale) + k, y + (i * font_scale) + l, col);
|
ssd1306_drawPixel(x + (j * font_scale) + k, y + (i * font_scale) + l, col);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -685,11 +714,11 @@ void ssd1306_drawstr_sz(uint8_t x, uint8_t y, char *str, uint8_t color, font_siz
|
||||||
{
|
{
|
||||||
uint8_t c;
|
uint8_t c;
|
||||||
|
|
||||||
while((c=*str++))
|
while ((c = *str++))
|
||||||
{
|
{
|
||||||
ssd1306_drawchar_sz(x, y, c, color, font_size);
|
ssd1306_drawchar_sz(x, y, c, color, font_size);
|
||||||
x += 8 * font_size;
|
x += 8 * font_size;
|
||||||
if(x>128 - 8 * font_size)
|
if (x > 128 - 8 * font_size)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -707,9 +736,9 @@ uint8_t ssd1306_init(void)
|
||||||
// initialize OLED
|
// initialize OLED
|
||||||
#if !defined(SSD1306_CUSTOM_INIT_ARRAY) || !SSD1306_CUSTOM_INIT_ARRAY
|
#if !defined(SSD1306_CUSTOM_INIT_ARRAY) || !SSD1306_CUSTOM_INIT_ARRAY
|
||||||
uint8_t *cmd_list = (uint8_t *)ssd1306_init_array;
|
uint8_t *cmd_list = (uint8_t *)ssd1306_init_array;
|
||||||
while(*cmd_list != SSD1306_TERMINATE_CMDS)
|
while (*cmd_list != SSD1306_TERMINATE_CMDS)
|
||||||
{
|
{
|
||||||
if(ssd1306_cmd(*cmd_list++))
|
if (ssd1306_cmd(*cmd_list++))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -27,14 +27,14 @@
|
||||||
#define TIMEOUT_MAX 100000
|
#define TIMEOUT_MAX 100000
|
||||||
|
|
||||||
// uncomment this to enable IRQ-driven operation
|
// uncomment this to enable IRQ-driven operation
|
||||||
//#define SSD1306_I2C_IRQ
|
// #define SSD1306_I2C_IRQ
|
||||||
|
|
||||||
#ifdef SSD1306_I2C_IRQ
|
#ifdef SSD1306_I2C_IRQ
|
||||||
// some stuff that IRQ mode needs
|
// some stuff that IRQ mode needs
|
||||||
volatile uint8_t ssd1306_i2c_send_buffer[64], *ssd1306_i2c_send_ptr, ssd1306_i2c_send_sz, ssd1306_i2c_irq_state;
|
volatile uint8_t ssd1306_i2c_send_buffer[64], *ssd1306_i2c_send_ptr, ssd1306_i2c_send_sz, ssd1306_i2c_irq_state;
|
||||||
|
|
||||||
// uncomment this to enable time diags in IRQ
|
// uncomment this to enable time diags in IRQ
|
||||||
//#define IRQ_DIAG
|
// #define IRQ_DIAG
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -51,22 +51,22 @@ void ssd1306_i2c_setup(void)
|
||||||
// set freq
|
// set freq
|
||||||
tempreg = I2C1->CTLR2;
|
tempreg = I2C1->CTLR2;
|
||||||
tempreg &= ~I2C_CTLR2_FREQ;
|
tempreg &= ~I2C_CTLR2_FREQ;
|
||||||
tempreg |= (FUNCONF_SYSTEM_CORE_CLOCK/SSD1306_I2C_PRERATE)&I2C_CTLR2_FREQ;
|
tempreg |= (FUNCONF_SYSTEM_CORE_CLOCK / SSD1306_I2C_PRERATE) & I2C_CTLR2_FREQ;
|
||||||
I2C1->CTLR2 = tempreg;
|
I2C1->CTLR2 = tempreg;
|
||||||
|
|
||||||
// Set clock config
|
// Set clock config
|
||||||
tempreg = 0;
|
tempreg = 0;
|
||||||
#if (SSD1306_I2C_CLKRATE <= 100000)
|
#if (SSD1306_I2C_CLKRATE <= 100000)
|
||||||
// standard mode good to 100kHz
|
// standard mode good to 100kHz
|
||||||
tempreg = (FUNCONF_SYSTEM_CORE_CLOCK/(2*SSD1306_I2C_CLKRATE))&I2C_CKCFGR_CCR;
|
tempreg = (FUNCONF_SYSTEM_CORE_CLOCK / (2 * SSD1306_I2C_CLKRATE)) & I2C_CKCFGR_CCR;
|
||||||
#else
|
#else
|
||||||
// fast mode over 100kHz
|
// fast mode over 100kHz
|
||||||
#ifndef SSD1306_I2C_DUTY
|
#ifndef SSD1306_I2C_DUTY
|
||||||
// 33% duty cycle
|
// 33% duty cycle
|
||||||
tempreg = (FUNCONF_SYSTEM_CORE_CLOCK/(3*SSD1306_I2C_CLKRATE))&I2C_CKCFGR_CCR;
|
tempreg = (FUNCONF_SYSTEM_CORE_CLOCK / (3 * SSD1306_I2C_CLKRATE)) & I2C_CKCFGR_CCR;
|
||||||
#else
|
#else
|
||||||
// 36% duty cycle
|
// 36% duty cycle
|
||||||
tempreg = (FUNCONF_SYSTEM_CORE_CLOCK/(25*SSD1306_I2C_CLKRATE))&I2C_CKCFGR_CCR;
|
tempreg = (FUNCONF_SYSTEM_CORE_CLOCK / (25 * SSD1306_I2C_CLKRATE)) & I2C_CKCFGR_CCR;
|
||||||
tempreg |= I2C_CKCFGR_DUTY;
|
tempreg |= I2C_CKCFGR_DUTY;
|
||||||
#endif
|
#endif
|
||||||
tempreg |= I2C_CKCFGR_FS;
|
tempreg |= I2C_CKCFGR_FS;
|
||||||
|
|
@ -92,7 +92,7 @@ void ssd1306_i2c_setup(void)
|
||||||
* error descriptions
|
* error descriptions
|
||||||
*/
|
*/
|
||||||
char *errstr[] =
|
char *errstr[] =
|
||||||
{
|
{
|
||||||
"not busy",
|
"not busy",
|
||||||
"master mode",
|
"master mode",
|
||||||
"transmit mode",
|
"transmit mode",
|
||||||
|
|
@ -125,7 +125,7 @@ uint8_t ssd1306_i2c_error(uint8_t err)
|
||||||
uint8_t ssd1306_i2c_chk_evt(uint32_t event_mask)
|
uint8_t ssd1306_i2c_chk_evt(uint32_t event_mask)
|
||||||
{
|
{
|
||||||
/* read order matters here! STAR1 before STAR2!! */
|
/* read order matters here! STAR1 before STAR2!! */
|
||||||
uint32_t status = I2C1->STAR1 | (I2C1->STAR2<<16);
|
uint32_t status = I2C1->STAR1 | (I2C1->STAR2 << 16);
|
||||||
return (status & event_mask) == event_mask;
|
return (status & event_mask) == event_mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,19 +138,20 @@ uint8_t ssd1306_i2c_send(uint8_t addr, uint8_t *data, uint8_t sz)
|
||||||
int32_t timeout;
|
int32_t timeout;
|
||||||
|
|
||||||
#ifdef IRQ_DIAG
|
#ifdef IRQ_DIAG
|
||||||
GPIOC->BSHR = (1<<(3));
|
GPIOC->BSHR = (1 << (3));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// error out if buffer under/overflow
|
// error out if buffer under/overflow
|
||||||
if((sz > sizeof(ssd1306_i2c_send_buffer)) || !sz)
|
if ((sz > sizeof(ssd1306_i2c_send_buffer)) || !sz)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
// wait for previous packet to finish
|
// wait for previous packet to finish
|
||||||
while(ssd1306_i2c_irq_state);
|
while (ssd1306_i2c_irq_state)
|
||||||
|
;
|
||||||
|
|
||||||
#ifdef IRQ_DIAG
|
#ifdef IRQ_DIAG
|
||||||
GPIOC->BSHR = (1<<(16+3));
|
GPIOC->BSHR = (1 << (16 + 3));
|
||||||
GPIOC->BSHR = (1<<(4));
|
GPIOC->BSHR = (1 << (4));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// init buffer for sending
|
// init buffer for sending
|
||||||
|
|
@ -160,8 +161,9 @@ uint8_t ssd1306_i2c_send(uint8_t addr, uint8_t *data, uint8_t sz)
|
||||||
|
|
||||||
// wait for not busy
|
// wait for not busy
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while((I2C1->STAR2 & I2C_STAR2_BUSY) && (timeout--));
|
while ((I2C1->STAR2 & I2C_STAR2_BUSY) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(0);
|
return ssd1306_i2c_error(0);
|
||||||
|
|
||||||
// Set START condition
|
// Set START condition
|
||||||
|
|
@ -169,17 +171,19 @@ uint8_t ssd1306_i2c_send(uint8_t addr, uint8_t *data, uint8_t sz)
|
||||||
|
|
||||||
// wait for master mode select
|
// wait for master mode select
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_MODE_SELECT)) && (timeout--));
|
while ((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_MODE_SELECT)) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(1);
|
return ssd1306_i2c_error(1);
|
||||||
|
|
||||||
// send 7-bit address + write flag
|
// send 7-bit address + write flag
|
||||||
I2C1->DATAR = addr<<1;
|
I2C1->DATAR = addr << 1;
|
||||||
|
|
||||||
// wait for transmit condition
|
// wait for transmit condition
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (timeout--));
|
while ((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(2);
|
return ssd1306_i2c_error(2);
|
||||||
|
|
||||||
// Enable TXE interrupt
|
// Enable TXE interrupt
|
||||||
|
|
@ -187,7 +191,7 @@ uint8_t ssd1306_i2c_send(uint8_t addr, uint8_t *data, uint8_t sz)
|
||||||
ssd1306_i2c_irq_state = 1;
|
ssd1306_i2c_irq_state = 1;
|
||||||
|
|
||||||
#ifdef IRQ_DIAG
|
#ifdef IRQ_DIAG
|
||||||
GPIOC->BSHR = (1<<(16+4));
|
GPIOC->BSHR = (1 << (16 + 4));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// exit
|
// exit
|
||||||
|
|
@ -203,7 +207,7 @@ void I2C1_EV_IRQHandler(void)
|
||||||
uint16_t STAR1, STAR2 __attribute__((unused));
|
uint16_t STAR1, STAR2 __attribute__((unused));
|
||||||
|
|
||||||
#ifdef IRQ_DIAG
|
#ifdef IRQ_DIAG
|
||||||
GPIOC->BSHR = (1<<(4));
|
GPIOC->BSHR = (1 << (4));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// read status, clear any events
|
// read status, clear any events
|
||||||
|
|
@ -211,14 +215,14 @@ void I2C1_EV_IRQHandler(void)
|
||||||
STAR2 = I2C1->STAR2;
|
STAR2 = I2C1->STAR2;
|
||||||
|
|
||||||
/* check for TXE */
|
/* check for TXE */
|
||||||
if(STAR1 & I2C_STAR1_TXE)
|
if (STAR1 & I2C_STAR1_TXE)
|
||||||
{
|
{
|
||||||
/* check for remaining data */
|
/* check for remaining data */
|
||||||
if(ssd1306_i2c_send_sz--)
|
if (ssd1306_i2c_send_sz--)
|
||||||
I2C1->DATAR = *ssd1306_i2c_send_ptr++;
|
I2C1->DATAR = *ssd1306_i2c_send_ptr++;
|
||||||
|
|
||||||
/* was that the last byte? */
|
/* was that the last byte? */
|
||||||
if(!ssd1306_i2c_send_sz)
|
if (!ssd1306_i2c_send_sz)
|
||||||
{
|
{
|
||||||
// disable TXE interrupt
|
// disable TXE interrupt
|
||||||
I2C1->CTLR2 &= ~(I2C_CTLR2_ITBUFEN | I2C_CTLR2_ITEVTEN);
|
I2C1->CTLR2 &= ~(I2C_CTLR2_ITBUFEN | I2C_CTLR2_ITEVTEN);
|
||||||
|
|
@ -227,7 +231,8 @@ void I2C1_EV_IRQHandler(void)
|
||||||
ssd1306_i2c_irq_state = 0;
|
ssd1306_i2c_irq_state = 0;
|
||||||
|
|
||||||
// wait for tx complete
|
// wait for tx complete
|
||||||
while(!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_BYTE_TRANSMITTED));
|
while (!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_BYTE_TRANSMITTED))
|
||||||
|
;
|
||||||
|
|
||||||
// set STOP condition
|
// set STOP condition
|
||||||
I2C1->CTLR1 |= I2C_CTLR1_STOP;
|
I2C1->CTLR1 |= I2C_CTLR1_STOP;
|
||||||
|
|
@ -235,7 +240,7 @@ void I2C1_EV_IRQHandler(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef IRQ_DIAG
|
#ifdef IRQ_DIAG
|
||||||
GPIOC->BSHR = (1<<(16+4));
|
GPIOC->BSHR = (1 << (16 + 4));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
@ -248,8 +253,9 @@ uint8_t ssd1306_i2c_send(uint8_t addr, const uint8_t *data, int sz)
|
||||||
|
|
||||||
// wait for not busy
|
// wait for not busy
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while((I2C1->STAR2 & I2C_STAR2_BUSY) && (timeout--));
|
while ((I2C1->STAR2 & I2C_STAR2_BUSY) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(0);
|
return ssd1306_i2c_error(0);
|
||||||
|
|
||||||
// Set START condition
|
// Set START condition
|
||||||
|
|
@ -257,26 +263,29 @@ uint8_t ssd1306_i2c_send(uint8_t addr, const uint8_t *data, int sz)
|
||||||
|
|
||||||
// wait for master mode select
|
// wait for master mode select
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_MODE_SELECT)) && (timeout--));
|
while ((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_MODE_SELECT)) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(1);
|
return ssd1306_i2c_error(1);
|
||||||
|
|
||||||
// send 7-bit address + write flag
|
// send 7-bit address + write flag
|
||||||
I2C1->DATAR = addr<<1;
|
I2C1->DATAR = addr << 1;
|
||||||
|
|
||||||
// wait for transmit condition
|
// wait for transmit condition
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (timeout--));
|
while ((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(2);
|
return ssd1306_i2c_error(2);
|
||||||
|
|
||||||
// send data one byte at a time
|
// send data one byte at a time
|
||||||
while(sz--)
|
while (sz--)
|
||||||
{
|
{
|
||||||
// wait for TX Empty
|
// wait for TX Empty
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while(!(I2C1->STAR1 & I2C_STAR1_TXE) && (timeout--));
|
while (!(I2C1->STAR1 & I2C_STAR1_TXE) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(3);
|
return ssd1306_i2c_error(3);
|
||||||
|
|
||||||
// send command
|
// send command
|
||||||
|
|
@ -285,8 +294,9 @@ uint8_t ssd1306_i2c_send(uint8_t addr, const uint8_t *data, int sz)
|
||||||
|
|
||||||
// wait for tx complete
|
// wait for tx complete
|
||||||
timeout = TIMEOUT_MAX;
|
timeout = TIMEOUT_MAX;
|
||||||
while((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_BYTE_TRANSMITTED)) && (timeout--));
|
while ((!ssd1306_i2c_chk_evt(SSD1306_I2C_EVENT_MASTER_BYTE_TRANSMITTED)) && (timeout--))
|
||||||
if(timeout==-1)
|
;
|
||||||
|
if (timeout == -1)
|
||||||
return ssd1306_i2c_error(4);
|
return ssd1306_i2c_error(4);
|
||||||
|
|
||||||
// set STOP condition
|
// set STOP condition
|
||||||
|
|
@ -305,7 +315,7 @@ uint8_t ssd1306_pkt_send(const uint8_t *data, int sz, uint8_t cmd)
|
||||||
uint8_t pkt[33];
|
uint8_t pkt[33];
|
||||||
|
|
||||||
/* build command or data packets */
|
/* build command or data packets */
|
||||||
if(cmd)
|
if (cmd)
|
||||||
{
|
{
|
||||||
pkt[0] = 0;
|
pkt[0] = 0;
|
||||||
pkt[1] = *data;
|
pkt[1] = *data;
|
||||||
|
|
@ -315,7 +325,7 @@ uint8_t ssd1306_pkt_send(const uint8_t *data, int sz, uint8_t cmd)
|
||||||
pkt[0] = 0x40;
|
pkt[0] = 0x40;
|
||||||
memcpy(&pkt[1], data, sz);
|
memcpy(&pkt[1], data, sz);
|
||||||
}
|
}
|
||||||
return ssd1306_i2c_send(SSD1306_I2C_ADDR, pkt, sz+1);
|
return ssd1306_i2c_send(SSD1306_I2C_ADDR, pkt, sz + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -331,32 +341,32 @@ uint8_t ssd1306_i2c_init(void)
|
||||||
|
|
||||||
#ifdef SSD1306_REMAP_I2C
|
#ifdef SSD1306_REMAP_I2C
|
||||||
AFIO->PCFR1 |= AFIO_PCFR1_I2C1_REMAP;
|
AFIO->PCFR1 |= AFIO_PCFR1_I2C1_REMAP;
|
||||||
funPinMode( PB8, GPIO_CFGLR_OUT_10Mhz_AF_OD );
|
funPinMode(PB8, GPIO_CFGLR_OUT_10Mhz_AF_OD);
|
||||||
funPinMode( PB9, GPIO_CFGLR_OUT_10Mhz_AF_OD );
|
funPinMode(PB9, GPIO_CFGLR_OUT_10Mhz_AF_OD);
|
||||||
#else
|
#else
|
||||||
funPinMode( PB6, GPIO_CFGLR_OUT_10Mhz_AF_OD );
|
funPinMode(PB6, GPIO_CFGLR_OUT_10Mhz_AF_OD);
|
||||||
funPinMode( PB7, GPIO_CFGLR_OUT_10Mhz_AF_OD );
|
funPinMode(PB7, GPIO_CFGLR_OUT_10Mhz_AF_OD);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO;
|
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO;
|
||||||
// PC1 is SDA, 10MHz Output, alt func, open-drain
|
// PC1 is SDA, 10MHz Output, alt func, open-drain
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*1));
|
GPIOC->CFGLR &= ~(0xf << (4 * 1));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF)<<(4*1);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF) << (4 * 1);
|
||||||
|
|
||||||
// PC2 is SCL, 10MHz Output, alt func, open-drain
|
// PC2 is SCL, 10MHz Output, alt func, open-drain
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*2));
|
GPIOC->CFGLR &= ~(0xf << (4 * 2));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF)<<(4*2);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_OD_AF) << (4 * 2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef IRQ_DIAG
|
#ifdef IRQ_DIAG
|
||||||
// GPIO diags on PC3/PC4
|
// GPIO diags on PC3/PC4
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*3));
|
GPIOC->CFGLR &= ~(0xf << (4 * 3));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*3);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 3);
|
||||||
GPIOC->BSHR = (1<<(16+3));
|
GPIOC->BSHR = (1 << (16 + 3));
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*4));
|
GPIOC->CFGLR &= ~(0xf << (4 * 4));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*4);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP) << (4 * 4);
|
||||||
GPIOC->BSHR = (1<<(16+4));
|
GPIOC->BSHR = (1 << (16 + 4));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// load I2C regs
|
// load I2C regs
|
||||||
|
|
|
||||||
|
|
@ -27,97 +27,101 @@
|
||||||
void ssd1306_i2c_setup(void)
|
void ssd1306_i2c_setup(void)
|
||||||
{
|
{
|
||||||
funGpioInitAll();
|
funGpioInitAll();
|
||||||
funPinMode( SSD1306_I2C_BITBANG_SDA, GPIO_CFGLR_OUT_10Mhz_PP );
|
funPinMode(SSD1306_I2C_BITBANG_SDA, GPIO_CFGLR_OUT_10Mhz_PP);
|
||||||
funDigitalWrite( SSD1306_I2C_BITBANG_SDA, 1 );
|
funDigitalWrite(SSD1306_I2C_BITBANG_SDA, 1);
|
||||||
funPinMode( SSD1306_I2C_BITBANG_SCL, GPIO_CFGLR_OUT_10Mhz_PP );
|
funPinMode(SSD1306_I2C_BITBANG_SCL, GPIO_CFGLR_OUT_10Mhz_PP);
|
||||||
funDigitalWrite( SSD1306_I2C_BITBANG_SCL, 1 );
|
funDigitalWrite(SSD1306_I2C_BITBANG_SCL, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SDA_HIGH funDigitalWrite( SSD1306_I2C_BITBANG_SDA, 1 );
|
#define SDA_HIGH funDigitalWrite(SSD1306_I2C_BITBANG_SDA, 1);
|
||||||
#define SCL_HIGH funDigitalWrite( SSD1306_I2C_BITBANG_SCL, 1 );
|
#define SCL_HIGH funDigitalWrite(SSD1306_I2C_BITBANG_SCL, 1);
|
||||||
#define SDA_LOW funDigitalWrite( SSD1306_I2C_BITBANG_SDA, 0 );
|
#define SDA_LOW funDigitalWrite(SSD1306_I2C_BITBANG_SDA, 0);
|
||||||
#define SCL_LOW funDigitalWrite( SSD1306_I2C_BITBANG_SCL, 0 );
|
#define SCL_LOW funDigitalWrite(SSD1306_I2C_BITBANG_SCL, 0);
|
||||||
#define SDA_IN funDigitalRead( SSD1306_I2C_BITBANG_SDA );
|
#define SDA_IN funDigitalRead(SSD1306_I2C_BITBANG_SDA);
|
||||||
#define I2CSPEEDBASE 1
|
#define I2CSPEEDBASE 1
|
||||||
#define I2CDELAY_FUNC(x) ADD_N_NOPS(x*1)
|
#define I2CDELAY_FUNC(x) ADD_N_NOPS(x * 1)
|
||||||
//Delay_Us(x*1);
|
// Delay_Us(x*1);
|
||||||
|
|
||||||
static void ssd1306_i2c_sendstart()
|
static void ssd1306_i2c_sendstart()
|
||||||
{
|
{
|
||||||
SCL_HIGH
|
SCL_HIGH
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SDA_LOW
|
SDA_LOW
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SCL_LOW
|
SCL_LOW
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssd1306_i2c_sendstop()
|
void ssd1306_i2c_sendstop()
|
||||||
{
|
{
|
||||||
SDA_LOW
|
SDA_LOW
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SCL_LOW
|
SCL_LOW
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SCL_HIGH
|
SCL_HIGH
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SDA_HIGH
|
SDA_HIGH
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return nonzero on failure.
|
// Return nonzero on failure.
|
||||||
unsigned char ssd1306_i2c_sendbyte( unsigned char data )
|
unsigned char ssd1306_i2c_sendbyte(unsigned char data)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
for( i = 0; i < 8; i++ )
|
for (i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
if( data & 0x80 )
|
if (data & 0x80)
|
||||||
{ SDA_HIGH; }
|
{
|
||||||
|
SDA_HIGH;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{ SDA_LOW; }
|
{
|
||||||
data<<=1;
|
SDA_LOW;
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
}
|
||||||
|
data <<= 1;
|
||||||
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SCL_HIGH
|
SCL_HIGH
|
||||||
I2CDELAY_FUNC( 2 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(2 * I2CSPEEDBASE);
|
||||||
SCL_LOW
|
SCL_LOW
|
||||||
}
|
}
|
||||||
|
|
||||||
//Immediately after sending last bit, open up DDDR for control.
|
// Immediately after sending last bit, open up DDDR for control.
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
funPinMode( SSD1306_I2C_BITBANG_SDA, GPIO_CFGLR_IN_PUPD );
|
funPinMode(SSD1306_I2C_BITBANG_SDA, GPIO_CFGLR_IN_PUPD);
|
||||||
SDA_HIGH
|
SDA_HIGH
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SCL_HIGH
|
SCL_HIGH
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
i = SDA_IN;
|
i = SDA_IN;
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SCL_LOW
|
SCL_LOW
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
SDA_HIGH // Maybe?
|
SDA_HIGH // Maybe?
|
||||||
funPinMode( SSD1306_I2C_BITBANG_SDA, GPIO_CFGLR_OUT_10Mhz_PP );
|
funPinMode(SSD1306_I2C_BITBANG_SDA, GPIO_CFGLR_OUT_10Mhz_PP);
|
||||||
I2CDELAY_FUNC( 1 * I2CSPEEDBASE );
|
I2CDELAY_FUNC(1 * I2CSPEEDBASE);
|
||||||
return !!i;
|
return !!i;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ssd1306_pkt_send(const uint8_t *data, int sz, uint8_t cmd)
|
uint8_t ssd1306_pkt_send(const uint8_t *data, int sz, uint8_t cmd)
|
||||||
{
|
{
|
||||||
ssd1306_i2c_sendstart();
|
ssd1306_i2c_sendstart();
|
||||||
int r = ssd1306_i2c_sendbyte( SSD1306_I2C_ADDR<<1 );
|
int r = ssd1306_i2c_sendbyte(SSD1306_I2C_ADDR << 1);
|
||||||
if( r ) return r;
|
if (r) return r;
|
||||||
//ssd1306_i2c_sendstart(); For some reason displays don't want repeated start
|
// ssd1306_i2c_sendstart(); For some reason displays don't want repeated start
|
||||||
if(cmd)
|
if (cmd)
|
||||||
{
|
{
|
||||||
if( ssd1306_i2c_sendbyte( 0x00 ) )
|
if (ssd1306_i2c_sendbyte(0x00))
|
||||||
return 1; // Control
|
return 1; // Control
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if( ssd1306_i2c_sendbyte( 0x40 ) )
|
if (ssd1306_i2c_sendbyte(0x40))
|
||||||
return 1; // Data
|
return 1; // Data
|
||||||
}
|
}
|
||||||
for( int i = 0; i < sz; i++ )
|
for (int i = 0; i < sz; i++)
|
||||||
{
|
{
|
||||||
if( ssd1306_i2c_sendbyte( data[i] ) )
|
if (ssd1306_i2c_sendbyte(data[i]))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
ssd1306_i2c_sendstop();
|
ssd1306_i2c_sendstop();
|
||||||
|
|
@ -126,10 +130,10 @@ uint8_t ssd1306_pkt_send(const uint8_t *data, int sz, uint8_t cmd)
|
||||||
|
|
||||||
void ssd1306_rst(void)
|
void ssd1306_rst(void)
|
||||||
{
|
{
|
||||||
funPinMode( SSD1306_RST_PIN, GPIO_CFGLR_OUT_10Mhz_PP );
|
funPinMode(SSD1306_RST_PIN, GPIO_CFGLR_OUT_10Mhz_PP);
|
||||||
funDigitalWrite( SSD1306_RST_PIN, 0 );
|
funDigitalWrite(SSD1306_RST_PIN, 0);
|
||||||
Delay_Ms(10);
|
Delay_Ms(10);
|
||||||
funDigitalWrite( SSD1306_RST_PIN, 1 );
|
funDigitalWrite(SSD1306_RST_PIN, 1);
|
||||||
Delay_Us(10);
|
Delay_Us(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,15 +40,15 @@ uint8_t ssd1306_spi_init(void)
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_SPI1;
|
RCC->APB2PCENR |= RCC_APB2Periph_SPI1;
|
||||||
|
|
||||||
funGpioInitAll();
|
funGpioInitAll();
|
||||||
funPinMode( SSD1306_RST_PIN, GPIO_CFGLR_OUT_50Mhz_PP );
|
funPinMode(SSD1306_RST_PIN, GPIO_CFGLR_OUT_50Mhz_PP);
|
||||||
funPinMode( SSD1306_CS_PIN, GPIO_CFGLR_OUT_50Mhz_PP );
|
funPinMode(SSD1306_CS_PIN, GPIO_CFGLR_OUT_50Mhz_PP);
|
||||||
funPinMode( SSD1306_DC_PIN, GPIO_CFGLR_OUT_50Mhz_PP );
|
funPinMode(SSD1306_DC_PIN, GPIO_CFGLR_OUT_50Mhz_PP);
|
||||||
funPinMode( SSD1306_MOSI_PIN, GPIO_CFGLR_OUT_50Mhz_AF_PP );
|
funPinMode(SSD1306_MOSI_PIN, GPIO_CFGLR_OUT_50Mhz_AF_PP);
|
||||||
funPinMode( SSD1306_SCK_PIN, GPIO_CFGLR_OUT_50Mhz_AF_PP );
|
funPinMode(SSD1306_SCK_PIN, GPIO_CFGLR_OUT_50Mhz_AF_PP);
|
||||||
|
|
||||||
funDigitalWrite( SSD1306_RST_PIN, FUN_HIGH );
|
funDigitalWrite(SSD1306_RST_PIN, FUN_HIGH);
|
||||||
funDigitalWrite( SSD1306_CS_PIN, FUN_HIGH );
|
funDigitalWrite(SSD1306_CS_PIN, FUN_HIGH);
|
||||||
funDigitalWrite( SSD1306_DC_PIN, FUN_LOW );
|
funDigitalWrite(SSD1306_DC_PIN, FUN_LOW);
|
||||||
|
|
||||||
// Configure SPI
|
// Configure SPI
|
||||||
SPI1->CTLR1 =
|
SPI1->CTLR1 =
|
||||||
|
|
@ -68,9 +68,9 @@ uint8_t ssd1306_spi_init(void)
|
||||||
*/
|
*/
|
||||||
void ssd1306_rst(void)
|
void ssd1306_rst(void)
|
||||||
{
|
{
|
||||||
funDigitalWrite( SSD1306_RST_PIN, FUN_LOW );
|
funDigitalWrite(SSD1306_RST_PIN, FUN_LOW);
|
||||||
Delay_Ms(10);
|
Delay_Ms(10);
|
||||||
funDigitalWrite( SSD1306_RST_PIN, FUN_HIGH );
|
funDigitalWrite(SSD1306_RST_PIN, FUN_HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -78,31 +78,32 @@ void ssd1306_rst(void)
|
||||||
*/
|
*/
|
||||||
uint8_t ssd1306_pkt_send(const uint8_t *data, int sz, uint8_t cmd)
|
uint8_t ssd1306_pkt_send(const uint8_t *data, int sz, uint8_t cmd)
|
||||||
{
|
{
|
||||||
if(cmd)
|
if (cmd)
|
||||||
{
|
{
|
||||||
funDigitalWrite( SSD1306_DC_PIN, FUN_LOW );
|
funDigitalWrite(SSD1306_DC_PIN, FUN_LOW);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
funDigitalWrite( SSD1306_DC_PIN, FUN_HIGH );
|
funDigitalWrite(SSD1306_DC_PIN, FUN_HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
funDigitalWrite( SSD1306_CS_PIN, FUN_LOW );
|
funDigitalWrite(SSD1306_CS_PIN, FUN_LOW);
|
||||||
|
|
||||||
// send data
|
// send data
|
||||||
while(sz--)
|
while (sz--)
|
||||||
{
|
{
|
||||||
// wait for TXE
|
// wait for TXE
|
||||||
while(!(SPI1->STATR & SPI_STATR_TXE));
|
while (!(SPI1->STATR & SPI_STATR_TXE))
|
||||||
|
;
|
||||||
|
|
||||||
// Send byte
|
// Send byte
|
||||||
SPI1->DATAR = *data++;
|
SPI1->DATAR = *data++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for not busy before exiting
|
// wait for not busy before exiting
|
||||||
while(SPI1->STATR & SPI_STATR_BSY) { }
|
while (SPI1->STATR & SPI_STATR_BSY) {}
|
||||||
|
|
||||||
funDigitalWrite( SSD1306_CS_PIN, FUN_HIGH );
|
funDigitalWrite(SSD1306_CS_PIN, FUN_HIGH);
|
||||||
|
|
||||||
// we're happy
|
// we're happy
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -32,11 +32,11 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
// Use DMA and SPI to stream out WS2812B LED Data via the MOSI pin.
|
// Use DMA and SPI to stream out WS2812B LED Data via the MOSI pin.
|
||||||
void WS2812BDMAInit( );
|
void WS2812BDMAInit();
|
||||||
void WS2812BDMAStart( int leds );
|
void WS2812BDMAStart(int leds);
|
||||||
|
|
||||||
// Callbacks that you must implement.
|
// Callbacks that you must implement.
|
||||||
uint32_t WS2812BLEDCallback( int ledno );
|
uint32_t WS2812BLEDCallback(int ledno);
|
||||||
|
|
||||||
#ifdef WS2812DMA_IMPLEMENTATION
|
#ifdef WS2812DMA_IMPLEMENTATION
|
||||||
|
|
||||||
|
|
@ -51,9 +51,9 @@ uint32_t WS2812BLEDCallback( int ledno );
|
||||||
#define WS2812B_RESET_PERIOD 2
|
#define WS2812B_RESET_PERIOD 2
|
||||||
|
|
||||||
#ifdef WSRAW
|
#ifdef WSRAW
|
||||||
#define DMA_BUFFER_LEN (((DMALEDS)/2)*8)
|
#define DMA_BUFFER_LEN (((DMALEDS) / 2) * 8)
|
||||||
#else
|
#else
|
||||||
#define DMA_BUFFER_LEN (((DMALEDS)/2)*6)
|
#define DMA_BUFFER_LEN (((DMALEDS) / 2) * 6)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint16_t WS2812dmabuff[DMA_BUFFER_LEN];
|
static uint16_t WS2812dmabuff[DMA_BUFFER_LEN];
|
||||||
|
|
@ -62,23 +62,36 @@ static volatile int WS2812LEDPlace;
|
||||||
static volatile int WS2812BLEDInUse;
|
static volatile int WS2812BLEDInUse;
|
||||||
// This is the code that updates a portion of the WS2812dmabuff with new data.
|
// This is the code that updates a portion of the WS2812dmabuff with new data.
|
||||||
// This effectively creates the bitstream that outputs to the LEDs.
|
// This effectively creates the bitstream that outputs to the LEDs.
|
||||||
static void WS2812FillBuffSec( uint16_t * ptr, int numhalfwords, int tce )
|
static void WS2812FillBuffSec(uint16_t *ptr, int numhalfwords, int tce)
|
||||||
{
|
{
|
||||||
const static uint16_t bitquartets[16] = {
|
const static uint16_t bitquartets[16] = {
|
||||||
0b1000100010001000, 0b1000100010001110, 0b1000100011101000, 0b1000100011101110,
|
0b1000100010001000,
|
||||||
0b1000111010001000, 0b1000111010001110, 0b1000111011101000, 0b1000111011101110,
|
0b1000100010001110,
|
||||||
0b1110100010001000, 0b1110100010001110, 0b1110100011101000, 0b1110100011101110,
|
0b1000100011101000,
|
||||||
0b1110111010001000, 0b1110111010001110, 0b1110111011101000, 0b1110111011101110, };
|
0b1000100011101110,
|
||||||
|
0b1000111010001000,
|
||||||
|
0b1000111010001110,
|
||||||
|
0b1000111011101000,
|
||||||
|
0b1000111011101110,
|
||||||
|
0b1110100010001000,
|
||||||
|
0b1110100010001110,
|
||||||
|
0b1110100011101000,
|
||||||
|
0b1110100011101110,
|
||||||
|
0b1110111010001000,
|
||||||
|
0b1110111010001110,
|
||||||
|
0b1110111011101000,
|
||||||
|
0b1110111011101110,
|
||||||
|
};
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
uint16_t * end = ptr + numhalfwords;
|
uint16_t *end = ptr + numhalfwords;
|
||||||
int ledcount = WS2812LEDs;
|
int ledcount = WS2812LEDs;
|
||||||
int place = WS2812LEDPlace;
|
int place = WS2812LEDPlace;
|
||||||
|
|
||||||
#ifdef WSRAW
|
#ifdef WSRAW
|
||||||
while( place < 0 && ptr != end )
|
while (place < 0 && ptr != end)
|
||||||
{
|
{
|
||||||
uint32_t * lptr = (uint32_t *)ptr;
|
uint32_t *lptr = (uint32_t *)ptr;
|
||||||
lptr[0] = 0;
|
lptr[0] = 0;
|
||||||
lptr[1] = 0;
|
lptr[1] = 0;
|
||||||
lptr[2] = 0;
|
lptr[2] = 0;
|
||||||
|
|
@ -88,7 +101,7 @@ static void WS2812FillBuffSec( uint16_t * ptr, int numhalfwords, int tce )
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
while( place < 0 && ptr != end )
|
while (place < 0 && ptr != end)
|
||||||
{
|
{
|
||||||
(*ptr++) = 0;
|
(*ptr++) = 0;
|
||||||
(*ptr++) = 0;
|
(*ptr++) = 0;
|
||||||
|
|
@ -100,18 +113,18 @@ static void WS2812FillBuffSec( uint16_t * ptr, int numhalfwords, int tce )
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while( ptr != end )
|
while (ptr != end)
|
||||||
{
|
{
|
||||||
if( place >= ledcount )
|
if (place >= ledcount)
|
||||||
{
|
{
|
||||||
// Optionally, leave line high.
|
// Optionally, leave line high.
|
||||||
while( ptr != end )
|
while (ptr != end)
|
||||||
(*ptr++) = 0;//0xffff;
|
(*ptr++) = 0; // 0xffff;
|
||||||
|
|
||||||
// Only safe to do this when we're on the second leg.
|
// Only safe to do this when we're on the second leg.
|
||||||
if( tce )
|
if (tce)
|
||||||
{
|
{
|
||||||
if( place == ledcount )
|
if (place == ledcount)
|
||||||
{
|
{
|
||||||
// Take the DMA out of circular mode and let it expire.
|
// Take the DMA out of circular mode and let it expire.
|
||||||
DMA1_Channel3->CFGR &= ~DMA_Mode_Circular;
|
DMA1_Channel3->CFGR &= ~DMA_Mode_Circular;
|
||||||
|
|
@ -124,58 +137,57 @@ static void WS2812FillBuffSec( uint16_t * ptr, int numhalfwords, int tce )
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WSRAW
|
#ifdef WSRAW
|
||||||
uint32_t ledval32bit = WS2812BLEDCallback( place++ );
|
uint32_t ledval32bit = WS2812BLEDCallback(place++);
|
||||||
|
|
||||||
ptr[6] = bitquartets[(ledval32bit>>28)&0xf];
|
ptr[6] = bitquartets[(ledval32bit >> 28) & 0xf];
|
||||||
ptr[7] = bitquartets[(ledval32bit>>24)&0xf];
|
ptr[7] = bitquartets[(ledval32bit >> 24) & 0xf];
|
||||||
ptr[4] = bitquartets[(ledval32bit>>20)&0xf];
|
ptr[4] = bitquartets[(ledval32bit >> 20) & 0xf];
|
||||||
ptr[5] = bitquartets[(ledval32bit>>16)&0xf];
|
ptr[5] = bitquartets[(ledval32bit >> 16) & 0xf];
|
||||||
ptr[2] = bitquartets[(ledval32bit>>12)&0xf];
|
ptr[2] = bitquartets[(ledval32bit >> 12) & 0xf];
|
||||||
ptr[3] = bitquartets[(ledval32bit>>8)&0xf];
|
ptr[3] = bitquartets[(ledval32bit >> 8) & 0xf];
|
||||||
ptr[0] = bitquartets[(ledval32bit>>4)&0xf];
|
ptr[0] = bitquartets[(ledval32bit >> 4) & 0xf];
|
||||||
ptr[1] = bitquartets[(ledval32bit>>0)&0xf];
|
ptr[1] = bitquartets[(ledval32bit >> 0) & 0xf];
|
||||||
|
|
||||||
ptr += 8;
|
ptr += 8;
|
||||||
i += 8;
|
i += 8;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// Use a LUT to figure out how we should set the SPI line.
|
// Use a LUT to figure out how we should set the SPI line.
|
||||||
uint32_t ledval24bit = WS2812BLEDCallback( place++ );
|
uint32_t ledval24bit = WS2812BLEDCallback(place++);
|
||||||
|
|
||||||
#ifdef WSRBG
|
#ifdef WSRBG
|
||||||
ptr[0] = bitquartets[(ledval24bit>>12)&0xf];
|
ptr[0] = bitquartets[(ledval24bit >> 12) & 0xf];
|
||||||
ptr[1] = bitquartets[(ledval24bit>>8)&0xf];
|
ptr[1] = bitquartets[(ledval24bit >> 8) & 0xf];
|
||||||
ptr[2] = bitquartets[(ledval24bit>>20)&0xf];
|
ptr[2] = bitquartets[(ledval24bit >> 20) & 0xf];
|
||||||
ptr[3] = bitquartets[(ledval24bit>>16)&0xf];
|
ptr[3] = bitquartets[(ledval24bit >> 16) & 0xf];
|
||||||
ptr[4] = bitquartets[(ledval24bit>>4)&0xf];
|
ptr[4] = bitquartets[(ledval24bit >> 4) & 0xf];
|
||||||
ptr[5] = bitquartets[(ledval24bit>>0)&0xf];
|
ptr[5] = bitquartets[(ledval24bit >> 0) & 0xf];
|
||||||
#elif defined( WSGRB )
|
#elif defined(WSGRB)
|
||||||
ptr[0] = bitquartets[(ledval24bit>>12)&0xf];
|
ptr[0] = bitquartets[(ledval24bit >> 12) & 0xf];
|
||||||
ptr[1] = bitquartets[(ledval24bit>>8)&0xf];
|
ptr[1] = bitquartets[(ledval24bit >> 8) & 0xf];
|
||||||
ptr[2] = bitquartets[(ledval24bit>>4)&0xf];
|
ptr[2] = bitquartets[(ledval24bit >> 4) & 0xf];
|
||||||
ptr[3] = bitquartets[(ledval24bit>>0)&0xf];
|
ptr[3] = bitquartets[(ledval24bit >> 0) & 0xf];
|
||||||
ptr[4] = bitquartets[(ledval24bit>>20)&0xf];
|
ptr[4] = bitquartets[(ledval24bit >> 20) & 0xf];
|
||||||
ptr[5] = bitquartets[(ledval24bit>>16)&0xf];
|
ptr[5] = bitquartets[(ledval24bit >> 16) & 0xf];
|
||||||
#else
|
#else
|
||||||
ptr[0] = bitquartets[(ledval24bit>>20)&0xf];
|
ptr[0] = bitquartets[(ledval24bit >> 20) & 0xf];
|
||||||
ptr[1] = bitquartets[(ledval24bit>>16)&0xf];
|
ptr[1] = bitquartets[(ledval24bit >> 16) & 0xf];
|
||||||
ptr[2] = bitquartets[(ledval24bit>>12)&0xf];
|
ptr[2] = bitquartets[(ledval24bit >> 12) & 0xf];
|
||||||
ptr[3] = bitquartets[(ledval24bit>>8)&0xf];
|
ptr[3] = bitquartets[(ledval24bit >> 8) & 0xf];
|
||||||
ptr[4] = bitquartets[(ledval24bit>>4)&0xf];
|
ptr[4] = bitquartets[(ledval24bit >> 4) & 0xf];
|
||||||
ptr[5] = bitquartets[(ledval24bit>>0)&0xf];
|
ptr[5] = bitquartets[(ledval24bit >> 0) & 0xf];
|
||||||
#endif
|
#endif
|
||||||
ptr += 6;
|
ptr += 6;
|
||||||
i += 6;
|
i += 6;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
WS2812LEDPlace = place;
|
WS2812LEDPlace = place;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DMA1_Channel3_IRQHandler( void ) __attribute__((interrupt));
|
void DMA1_Channel3_IRQHandler(void) __attribute__((interrupt));
|
||||||
void DMA1_Channel3_IRQHandler( void )
|
void DMA1_Channel3_IRQHandler(void)
|
||||||
{
|
{
|
||||||
//GPIOD->BSHR = 1; // Turn on GPIOD0 for profiling
|
// GPIOD->BSHR = 1; // Turn on GPIOD0 for profiling
|
||||||
|
|
||||||
// Backup flags.
|
// Backup flags.
|
||||||
volatile int intfr = DMA1->INTFR;
|
volatile int intfr = DMA1->INTFR;
|
||||||
|
|
@ -188,23 +200,23 @@ void DMA1_Channel3_IRQHandler( void )
|
||||||
// DMA1_IT_TC3 should be COMPLETE. But for some reason, doing this causes
|
// DMA1_IT_TC3 should be COMPLETE. But for some reason, doing this causes
|
||||||
// LED jitter. I am henseforth flipping the order.
|
// LED jitter. I am henseforth flipping the order.
|
||||||
|
|
||||||
if( intfr & DMA1_IT_HT3 )
|
if (intfr & DMA1_IT_HT3)
|
||||||
{
|
{
|
||||||
// Halfwaay (Fill in first part)
|
// Halfwaay (Fill in first part)
|
||||||
WS2812FillBuffSec( WS2812dmabuff, DMA_BUFFER_LEN / 2, 1 );
|
WS2812FillBuffSec(WS2812dmabuff, DMA_BUFFER_LEN / 2, 1);
|
||||||
}
|
}
|
||||||
if( intfr & DMA1_IT_TC3 )
|
if (intfr & DMA1_IT_TC3)
|
||||||
{
|
{
|
||||||
// Complete (Fill in second part)
|
// Complete (Fill in second part)
|
||||||
WS2812FillBuffSec( WS2812dmabuff + DMA_BUFFER_LEN / 2, DMA_BUFFER_LEN / 2, 0 );
|
WS2812FillBuffSec(WS2812dmabuff + DMA_BUFFER_LEN / 2, DMA_BUFFER_LEN / 2, 0);
|
||||||
}
|
}
|
||||||
intfr = DMA1->INTFR;
|
intfr = DMA1->INTFR;
|
||||||
} while( intfr & DMA1_IT_GL3 );
|
} while (intfr & DMA1_IT_GL3);
|
||||||
|
|
||||||
//GPIOD->BSHR = 1<<16; // Turn off GPIOD0 for profiling
|
// GPIOD->BSHR = 1<<16; // Turn off GPIOD0 for profiling
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812BDMAStart( int leds )
|
void WS2812BDMAStart(int leds)
|
||||||
{
|
{
|
||||||
// Enter critical section.
|
// Enter critical section.
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
|
|
@ -216,27 +228,27 @@ void WS2812BDMAStart( int leds )
|
||||||
WS2812LEDPlace = -WS2812B_RESET_PERIOD;
|
WS2812LEDPlace = -WS2812B_RESET_PERIOD;
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
|
||||||
WS2812FillBuffSec( WS2812dmabuff, DMA_BUFFER_LEN, 0 );
|
WS2812FillBuffSec(WS2812dmabuff, DMA_BUFFER_LEN, 0);
|
||||||
|
|
||||||
DMA1_Channel3->CNTR = DMA_BUFFER_LEN; // Number of unique uint16_t entries.
|
DMA1_Channel3->CNTR = DMA_BUFFER_LEN; // Number of unique uint16_t entries.
|
||||||
DMA1_Channel3->CFGR |= DMA_Mode_Circular;
|
DMA1_Channel3->CFGR |= DMA_Mode_Circular;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812BDMAInit( )
|
void WS2812BDMAInit()
|
||||||
{
|
{
|
||||||
// Enable DMA + Peripherals
|
// Enable DMA + Peripherals
|
||||||
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
|
RCC->AHBPCENR |= RCC_AHBPeriph_DMA1;
|
||||||
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC | RCC_APB2Periph_SPI1;
|
RCC->APB2PCENR |= RCC_APB2Periph_GPIOC | RCC_APB2Periph_SPI1;
|
||||||
|
|
||||||
// MOSI, Configure GPIO Pin
|
// MOSI, Configure GPIO Pin
|
||||||
GPIOC->CFGLR &= ~(0xf<<(4*6));
|
GPIOC->CFGLR &= ~(0xf << (4 * 6));
|
||||||
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF)<<(4*6);
|
GPIOC->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP_AF) << (4 * 6);
|
||||||
|
|
||||||
// Configure SPI
|
// Configure SPI
|
||||||
SPI1->CTLR1 =
|
SPI1->CTLR1 =
|
||||||
SPI_NSS_Soft | SPI_CPHA_1Edge | SPI_CPOL_Low | SPI_DataSize_16b |
|
SPI_NSS_Soft | SPI_CPHA_1Edge | SPI_CPOL_Low | SPI_DataSize_16b |
|
||||||
SPI_Mode_Master | SPI_Direction_1Line_Tx |
|
SPI_Mode_Master | SPI_Direction_1Line_Tx |
|
||||||
3<<3; // Divisior = 16 (48/16 = 3MHz)
|
3 << 3; // Divisior = 16 (48/16 = 3MHz)
|
||||||
|
|
||||||
SPI1->CTLR2 = SPI_CTLR2_TXDMAEN;
|
SPI1->CTLR2 = SPI_CTLR2_TXDMAEN;
|
||||||
SPI1->HSCR = 1;
|
SPI1->HSCR = 1;
|
||||||
|
|
@ -245,10 +257,10 @@ void WS2812BDMAInit( )
|
||||||
|
|
||||||
SPI1->DATAR = 0; // Set SPI line Low.
|
SPI1->DATAR = 0; // Set SPI line Low.
|
||||||
|
|
||||||
//DMA1_Channel3 is for SPI1TX
|
// DMA1_Channel3 is for SPI1TX
|
||||||
DMA1_Channel3->PADDR = (uint32_t)&SPI1->DATAR;
|
DMA1_Channel3->PADDR = (uint32_t)&SPI1->DATAR;
|
||||||
DMA1_Channel3->MADDR = (uint32_t)WS2812dmabuff;
|
DMA1_Channel3->MADDR = (uint32_t)WS2812dmabuff;
|
||||||
DMA1_Channel3->CNTR = 0;// sizeof( bufferset )/2; // Number of unique copies. (Don't start, yet!)
|
DMA1_Channel3->CNTR = 0; // sizeof( bufferset )/2; // Number of unique copies. (Don't start, yet!)
|
||||||
DMA1_Channel3->CFGR =
|
DMA1_Channel3->CFGR =
|
||||||
DMA_M2M_Disable |
|
DMA_M2M_Disable |
|
||||||
DMA_Priority_VeryHigh |
|
DMA_Priority_VeryHigh |
|
||||||
|
|
@ -259,12 +271,12 @@ void WS2812BDMAInit( )
|
||||||
DMA_DIR_PeripheralDST |
|
DMA_DIR_PeripheralDST |
|
||||||
DMA_IT_TC | DMA_IT_HT; // Transmission Complete + Half Empty Interrupts.
|
DMA_IT_TC | DMA_IT_HT; // Transmission Complete + Half Empty Interrupts.
|
||||||
|
|
||||||
// NVIC_SetPriority( DMA1_Channel3_IRQn, 0<<4 ); //We don't need to tweak priority.
|
// NVIC_SetPriority( DMA1_Channel3_IRQn, 0<<4 ); //We don't need to tweak priority.
|
||||||
NVIC_EnableIRQ( DMA1_Channel3_IRQn );
|
NVIC_EnableIRQ(DMA1_Channel3_IRQn);
|
||||||
DMA1_Channel3->CFGR |= DMA_CFGR1_EN;
|
DMA1_Channel3->CFGR |= DMA_CFGR1_EN;
|
||||||
|
|
||||||
#ifdef WS2812B_ALLOW_INTERRUPT_NESTING
|
#ifdef WS2812B_ALLOW_INTERRUPT_NESTING
|
||||||
__set_INTSYSCR( __get_INTSYSCR() | 2 ); // Enable interrupt nesting.
|
__set_INTSYSCR(__get_INTSYSCR() | 2); // Enable interrupt nesting.
|
||||||
PFIC->IPRIOR[24] = 0b10000000; // Turn on preemption for DMA1Ch3
|
PFIC->IPRIOR[24] = 0b10000000; // Turn on preemption for DMA1Ch3
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -272,4 +284,3 @@ void WS2812BDMAInit( )
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
void WS2812BSimpleSend( GPIO_TypeDef * port, int pin, uint8_t * data, int len_in_bytes );
|
void WS2812BSimpleSend(GPIO_TypeDef *port, int pin, uint8_t *data, int len_in_bytes);
|
||||||
|
|
||||||
#ifdef WS2812BSIMPLE_IMPLEMENTATION
|
#ifdef WS2812BSIMPLE_IMPLEMENTATION
|
||||||
|
|
||||||
|
|
@ -25,28 +25,28 @@ void WS2812BSimpleSend( GPIO_TypeDef * port, int pin, uint8_t * data, int len_in
|
||||||
#error WS2812B Driver Requires FUNCONF_SYSTICK_USE_HCLK
|
#error WS2812B Driver Requires FUNCONF_SYSTICK_USE_HCLK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void WS2812BSimpleSend( GPIO_TypeDef * port, int pin, uint8_t * data, int len_in_bytes )
|
void WS2812BSimpleSend(GPIO_TypeDef *port, int pin, uint8_t *data, int len_in_bytes)
|
||||||
{
|
{
|
||||||
int port_id = (((intptr_t)port-(intptr_t)GPIOA)>>10);
|
int port_id = (((intptr_t)port - (intptr_t)GPIOA) >> 10);
|
||||||
RCC->APB2PCENR |= (RCC_APB2Periph_GPIOA<<port_id); // Make sure port is enabled.
|
RCC->APB2PCENR |= (RCC_APB2Periph_GPIOA << port_id); // Make sure port is enabled.
|
||||||
|
|
||||||
int poffset = (pin*4);
|
int poffset = (pin * 4);
|
||||||
port->CFGLR = ( port->CFGLR & (~(0xf<<poffset))) | ((GPIO_Speed_2MHz | GPIO_CNF_OUT_PP)<<(poffset));
|
port->CFGLR = (port->CFGLR & (~(0xf << poffset))) | ((GPIO_Speed_2MHz | GPIO_CNF_OUT_PP) << (poffset));
|
||||||
|
|
||||||
int maskon = 1<<pin;
|
int maskon = 1 << pin;
|
||||||
int maskoff = 1<<(16+pin);
|
int maskoff = 1 << (16 + pin);
|
||||||
|
|
||||||
port->BSHR = maskoff;
|
port->BSHR = maskoff;
|
||||||
|
|
||||||
uint8_t * end = data + len_in_bytes;
|
uint8_t *end = data + len_in_bytes;
|
||||||
while( data != end )
|
while (data != end)
|
||||||
{
|
{
|
||||||
uint8_t byte = *data;
|
uint8_t byte = *data;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for( i = 0; i < 8; i++ )
|
for (i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if( byte & 0x80 )
|
if (byte & 0x80)
|
||||||
{
|
{
|
||||||
// WS2812B's need AT LEAST 625ns for a logical "1"
|
// WS2812B's need AT LEAST 625ns for a logical "1"
|
||||||
port->BSHR = maskon;
|
port->BSHR = maskon;
|
||||||
|
|
@ -61,7 +61,7 @@ void WS2812BSimpleSend( GPIO_TypeDef * port, int pin, uint8_t * data, int len_in
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
#endif
|
#endif
|
||||||
port->BSHR = maskon;
|
port->BSHR = maskon;
|
||||||
asm volatile( "nop\nnop\nnop\nnop" );
|
asm volatile("nop\nnop\nnop\nnop");
|
||||||
port->BSHR = maskoff;
|
port->BSHR = maskoff;
|
||||||
#ifndef WS2812BSIMPLE_NO_IRQ_TWEAKING
|
#ifndef WS2812BSIMPLE_NO_IRQ_TWEAKING
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
|
|
@ -80,4 +80,3 @@ void WS2812BSimpleSend( GPIO_TypeDef * port, int pin, uint8_t * data, int len_in
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
5
src/misc/attic/.clang-format
Normal file
5
src/misc/attic/.clang-format
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"DisableFormat": true,
|
||||||
|
"SortIncludes": "Never"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,41 +1,48 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <string.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
const char * yes[] = { "SENTINEL_WILL_BE_REPLACED_BY_CMDLINE" }; // "CH32X03x", etc. element 0 is filled in by command-line
|
const char *yes[] = {"SENTINEL_WILL_BE_REPLACED_BY_CMDLINE"}; // "CH32X03x", etc. element 0 is filled in by command-line
|
||||||
const char * no[] = { "CH32V10x", "CH32V30x", "CH32V20x", "CH32X03x", "CH32V003" };
|
const char *no[] = {"CH32V10x", "CH32V30x", "CH32V20x", "CH32X03x", "CH32V003"};
|
||||||
|
|
||||||
char * WhitePull( const char ** sti )
|
char *WhitePull(const char **sti)
|
||||||
{
|
{
|
||||||
const char * st = *sti;
|
const char *st = *sti;
|
||||||
int len = 0;
|
int len = 0;
|
||||||
while( ( *st == ' ' || *st == '\t' || *st == '(' ) && *st ) { st++; }
|
while ((*st == ' ' || *st == '\t' || *st == '(') && *st)
|
||||||
const char * sts = st;
|
{
|
||||||
while( *st != ' ' && *st != '\t' && *st != '\n' && *st != ')' && *st != '(' && *st != 0 ) { st++; len++; }
|
st++;
|
||||||
if( *st == ')' ) { st++; }
|
}
|
||||||
char * ret = malloc( len + 1 );
|
const char *sts = st;
|
||||||
memcpy( ret, sts, len );
|
while (*st != ' ' && *st != '\t' && *st != '\n' && *st != ')' && *st != '(' && *st != 0)
|
||||||
|
{
|
||||||
|
st++;
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
if (*st == ')') { st++; }
|
||||||
|
char *ret = malloc(len + 1);
|
||||||
|
memcpy(ret, sts, len);
|
||||||
ret[len] = 0;
|
ret[len] = 0;
|
||||||
*sti = st;
|
*sti = st;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NYI( const char * s )
|
int NYI(const char *s)
|
||||||
{
|
{
|
||||||
int ret = 2;
|
int ret = 2;
|
||||||
char * wp = WhitePull( &s );
|
char *wp = WhitePull(&s);
|
||||||
int i;
|
int i;
|
||||||
for( i = 0; i < sizeof(yes)/sizeof(yes[0]); i++ )
|
for (i = 0; i < sizeof(yes) / sizeof(yes[0]); i++)
|
||||||
if( strcmp( yes[i], wp ) == 0 ) ret = 1;
|
if (strcmp(yes[i], wp) == 0) ret = 1;
|
||||||
if( ret != 1 )
|
if (ret != 1)
|
||||||
for( i = 0; i < sizeof(no)/sizeof(no[0]); i++ )
|
for (i = 0; i < sizeof(no) / sizeof(no[0]); i++)
|
||||||
if( strcmp( no[i], wp ) == 0 ) ret = 0;
|
if (strcmp(no[i], wp) == 0) ret = 0;
|
||||||
free( wp );
|
free(wp);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EvalSpec( const char * spl )
|
int EvalSpec(const char *spl)
|
||||||
{
|
{
|
||||||
int rsofar = 0;
|
int rsofar = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
@ -43,107 +50,120 @@ int EvalSpec( const char * spl )
|
||||||
int lasto = -1;
|
int lasto = -1;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
cont:
|
cont:
|
||||||
char * wp = WhitePull( &spl );
|
char *wp = WhitePull(&spl);
|
||||||
int def = -1;
|
int def = -1;
|
||||||
if( strcmp( wp, "defined" ) == 0 ) def = 1;
|
if (strcmp(wp, "defined") == 0) def = 1;
|
||||||
if( strcmp( wp, "!defined" ) == 0 ) def = 2;
|
if (strcmp(wp, "!defined") == 0) def = 2;
|
||||||
if( def < 0 ) return 2;
|
if (def < 0) return 2;
|
||||||
char * wpn = WhitePull( &spl );
|
char *wpn = WhitePull(&spl);
|
||||||
i = NYI( wpn );
|
i = NYI(wpn);
|
||||||
//printf( "SPIN: %s/%s/%d/%d/%d\n", wp, wpn, i, def, lasto );
|
// printf( "SPIN: %s/%s/%d/%d/%d\n", wp, wpn, i, def, lasto );
|
||||||
if( i == 2 ) return 2;
|
if (i == 2) return 2;
|
||||||
|
|
||||||
if( def == 2 ) i = !i;
|
if (def == 2) i = !i;
|
||||||
|
|
||||||
if( lasto == 1 )
|
if (lasto == 1)
|
||||||
{
|
{
|
||||||
ret = lastv || i;
|
ret = lastv || i;
|
||||||
}
|
}
|
||||||
else if( lasto == 2 )
|
else if (lasto == 2)
|
||||||
ret = lastv && i;
|
ret = lastv && i;
|
||||||
else
|
else
|
||||||
ret = i;
|
ret = i;
|
||||||
|
|
||||||
char * wpa = WhitePull( &spl );
|
char *wpa = WhitePull(&spl);
|
||||||
//printf( "WPA: \"%s\"\n", wpa );
|
// printf( "WPA: \"%s\"\n", wpa );
|
||||||
lastv = ret;
|
lastv = ret;
|
||||||
lasto = -1;
|
lasto = -1;
|
||||||
//printf( "RET: %d\n", ret );
|
// printf( "RET: %d\n", ret );
|
||||||
if( strcmp( wpa, "||" ) == 0 ) { lasto = 1; goto cont; }
|
if (strcmp(wpa, "||") == 0)
|
||||||
else if( strcmp( wpa, "&&" ) == 0 ) { lasto = 2; goto cont; }
|
{
|
||||||
else return ret;
|
lasto = 1;
|
||||||
|
goto cont;
|
||||||
|
}
|
||||||
|
else if (strcmp(wpa, "&&") == 0)
|
||||||
|
{
|
||||||
|
lasto = 2;
|
||||||
|
goto cont;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 for no
|
// 0 for no
|
||||||
// 1 for yes
|
// 1 for yes
|
||||||
// 2 for indeterminate
|
// 2 for indeterminate
|
||||||
int NoYesInd( const char * preprocc )
|
int NoYesInd(const char *preprocc)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int ofs = 0;
|
int ofs = 0;
|
||||||
if( strncmp( preprocc, "#if ", 4 ) == 0 ) ofs = 4;
|
if (strncmp(preprocc, "#if ", 4) == 0) ofs = 4;
|
||||||
if( strncmp( preprocc, "#elif ", 6 ) == 0 ) ofs = 6;
|
if (strncmp(preprocc, "#elif ", 6) == 0) ofs = 6;
|
||||||
if( ofs )
|
if (ofs)
|
||||||
{
|
{
|
||||||
ret = EvalSpec( preprocc + ofs );
|
ret = EvalSpec(preprocc + ofs);
|
||||||
//printf( "SPEC: %d\n", ret );
|
// printf( "SPEC: %d\n", ret );
|
||||||
}
|
}
|
||||||
else if( strncmp( preprocc, "#ifdef ", 7 ) == 0 )
|
else if (strncmp(preprocc, "#ifdef ", 7) == 0)
|
||||||
{
|
{
|
||||||
const char * ep = preprocc + 6;
|
const char *ep = preprocc + 6;
|
||||||
char * wp = WhitePull( &ep );
|
char *wp = WhitePull(&ep);
|
||||||
ret = NYI( wp );
|
ret = NYI(wp);
|
||||||
free( wp );
|
free(wp);
|
||||||
}
|
}
|
||||||
else if( strncmp( preprocc, "#ifndef ", 8 ) == 0 )
|
else if (strncmp(preprocc, "#ifndef ", 8) == 0)
|
||||||
{
|
{
|
||||||
const char * ep = preprocc + 6;
|
const char *ep = preprocc + 6;
|
||||||
char * wp = WhitePull( &ep );
|
char *wp = WhitePull(&ep);
|
||||||
ret = NYI( wp );
|
ret = NYI(wp);
|
||||||
if( ret < 2 ) ret = !ret;
|
if (ret < 2) ret = !ret;
|
||||||
free( wp );
|
free(wp);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ret = 2;
|
ret = 2;
|
||||||
//printf( "%d-> %s\n", ret, preprocc );
|
// printf( "%d-> %s\n", ret, preprocc );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char * sslineis( const char * line, const char * match )
|
const char *sslineis(const char *line, const char *match)
|
||||||
{
|
{
|
||||||
while( *line == ' ' || *line == '\t' ) line++;
|
while (*line == ' ' || *line == '\t')
|
||||||
const char * linestart = line;
|
line++;
|
||||||
while( *line && *match == *line ) { line++; match++; }
|
const char *linestart = line;
|
||||||
if( *match == 0 )
|
while (*line && *match == *line)
|
||||||
|
{
|
||||||
|
line++;
|
||||||
|
match++;
|
||||||
|
}
|
||||||
|
if (*match == 0)
|
||||||
return linestart;
|
return linestart;
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main( int argc, char ** argv )
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
if( argc != 3 )
|
if (argc != 3)
|
||||||
{
|
{
|
||||||
fprintf( stderr, "Syntax: transition [#define to trigger on] [file to convert]\nNo'd architectures:\n" );
|
fprintf(stderr, "Syntax: transition [#define to trigger on] [file to convert]\nNo'd architectures:\n");
|
||||||
int i;
|
int i;
|
||||||
for( i = 0; i < sizeof(no)/sizeof(no[0]); i++ )
|
for (i = 0; i < sizeof(no) / sizeof(no[0]); i++)
|
||||||
{
|
{
|
||||||
fprintf( stderr, "\t%s\n", no[i] );
|
fprintf(stderr, "\t%s\n", no[i]);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
yes[0] = argv[1];
|
yes[0] = argv[1];
|
||||||
|
|
||||||
FILE * f = fopen( argv[2], "r" );
|
FILE *f = fopen(argv[2], "r");
|
||||||
if( !f )
|
if (!f)
|
||||||
{
|
{
|
||||||
fprintf( stderr, "Error: Could not open \"%s\"\n", argv[2] );
|
fprintf(stderr, "Error: Could not open \"%s\"\n", argv[2]);
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
char line[1024];
|
char line[1024];
|
||||||
char * l;
|
char *l;
|
||||||
|
|
||||||
|
|
||||||
int depth = 0;
|
int depth = 0;
|
||||||
|
|
||||||
|
|
@ -154,73 +174,71 @@ int main( int argc, char ** argv )
|
||||||
int yesnoind[1024];
|
int yesnoind[1024];
|
||||||
yesnoind[0] = 1;
|
yesnoind[0] = 1;
|
||||||
|
|
||||||
while( l = fgets( line, sizeof(line)-1, f ) )
|
while (l = fgets(line, sizeof(line) - 1, f))
|
||||||
{
|
{
|
||||||
const char * ss = 0;
|
const char *ss = 0;
|
||||||
int nyi = yesnoind[depth];
|
int nyi = yesnoind[depth];
|
||||||
int waspre = 0;
|
int waspre = 0;
|
||||||
|
|
||||||
if( (ss = sslineis( line, "#if " ) ) || (ss = sslineis( line, "#ifdef " ) ) || (ss = sslineis( line, "#ifndef " ) ) )
|
if ((ss = sslineis(line, "#if ")) || (ss = sslineis(line, "#ifdef ")) || (ss = sslineis(line, "#ifndef ")))
|
||||||
{
|
{
|
||||||
waspre = 1;
|
waspre = 1;
|
||||||
//printf( "CHECK: %d/%s\n", depth, l );
|
// printf( "CHECK: %d/%s\n", depth, l );
|
||||||
nyi = NoYesInd( ss );
|
nyi = NoYesInd(ss);
|
||||||
depth++;
|
depth++;
|
||||||
yesnoind[depth] = nyi;
|
yesnoind[depth] = nyi;
|
||||||
}
|
}
|
||||||
else if( (ss = sslineis( line, "#elif " ) ) )
|
else if ((ss = sslineis(line, "#elif ")))
|
||||||
{
|
{
|
||||||
if( nyi != 2 )
|
if (nyi != 2)
|
||||||
{
|
{
|
||||||
waspre = 1;
|
waspre = 1;
|
||||||
if( nyi == 1 )
|
if (nyi == 1)
|
||||||
{
|
{
|
||||||
nyi = 3;
|
nyi = 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
nyi = NoYesInd( ss );
|
nyi = NoYesInd(ss);
|
||||||
}
|
}
|
||||||
//printf( "ELIF check: %s %d\n", ss, nyi );
|
// printf( "ELIF check: %s %d\n", ss, nyi );
|
||||||
yesnoind[depth] = nyi;
|
yesnoind[depth] = nyi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( (ss = sslineis( line, "#else" ) ) )
|
else if ((ss = sslineis(line, "#else")))
|
||||||
{
|
{
|
||||||
if( nyi != 2 )
|
if (nyi != 2)
|
||||||
{
|
{
|
||||||
waspre = 1;
|
waspre = 1;
|
||||||
if( yesnoind[depth] == 1 )
|
if (yesnoind[depth] == 1)
|
||||||
nyi = 3;
|
nyi = 3;
|
||||||
else
|
else
|
||||||
nyi = !yesnoind[depth];
|
nyi = !yesnoind[depth];
|
||||||
yesnoind[depth] = nyi;
|
yesnoind[depth] = nyi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( (ss = sslineis( line, "#endif" ) ) )
|
else if ((ss = sslineis(line, "#endif")))
|
||||||
{
|
{
|
||||||
waspre = 1;
|
waspre = 1;
|
||||||
depth--;
|
depth--;
|
||||||
if( depth < 0 )
|
if (depth < 0)
|
||||||
{
|
{
|
||||||
fprintf( stderr, "UNTERMD IF\n" );
|
fprintf(stderr, "UNTERMD IF\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int thisv = nyi;
|
int thisv = nyi;
|
||||||
int i;
|
int i;
|
||||||
for( i = 0; i <= depth; i++ )
|
for (i = 0; i <= depth; i++)
|
||||||
{
|
{
|
||||||
//printf( "%d", yesnoind[i] );
|
// printf( "%d", yesnoind[i] );
|
||||||
if( yesnoind[i] == 0 || yesnoind[i] == 3 ) thisv = 0;
|
if (yesnoind[i] == 0 || yesnoind[i] == 3) thisv = 0;
|
||||||
}
|
}
|
||||||
//printf( ">>%s", l );
|
// printf( ">>%s", l );
|
||||||
|
|
||||||
if( thisv != 0 && thisv != 3 && ( thisv != 1 || !waspre ) )
|
if (thisv != 0 && thisv != 3 && (thisv != 1 || !waspre))
|
||||||
{
|
{
|
||||||
printf( "%s", l );
|
printf("%s", l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
This only works for the WCH LinkE in RISC-V mode. If your programmer has the BLUE light ON shortly after boot your programmer is in ARM mode.
|
|
||||||
|
|
||||||
Please follow instructions here to convert your programmer to RISC-V mode from ARM mode.
|
|
||||||
|
|
||||||
Basically press-and-hold the ModeS button while plugging in the USB.
|
|
||||||
|
|
||||||
Once powered, it will store that to default.
|
|
||||||
|
|
||||||
The blue light should be OFF.
|
|
||||||
|
|
||||||
Once you are in RISC-V mode, you can install this driver by right-clicking on the driver and saying install.
|
|
||||||
Binary file not shown.
Binary file not shown.
|
|
@ -1,23 +0,0 @@
|
||||||
all : ci
|
|
||||||
|
|
||||||
EXAMPLES := $(wildcard ../../examples/*/.) $(wildcard ../../examples_v10x/*/.) $(wildcard ../../examples_v20x/*/.) $(wildcard ../../examples_v30x/*/.) $(wildcard ../../examples_x035/*/.)
|
|
||||||
|
|
||||||
.PHONY: ci tests all $(EXAMPLES) clean
|
|
||||||
|
|
||||||
results :
|
|
||||||
mkdir -p results
|
|
||||||
|
|
||||||
$(EXAMPLES) : results
|
|
||||||
echo $(shell basename $(realpath $(lastword $@)))
|
|
||||||
($(MAKE) -C $@ build > results/$(subst .,,$(subst /,_,$@)).txt 2> results/$(subst .,,$(subst /,_,$@)).warning && echo "success" > results/$(subst .,,$(subst /,_,$@)).result) || echo "failure" > results/$(subst .,,$(subst /,_,$@)).result
|
|
||||||
echo $(shell basename $(realpath $(lastword $@))).bin > results/$(subst .,,$(subst /,_,$@)).stat
|
|
||||||
sha1sum $@/$(shell basename $(realpath $(lastword $@))).bin | cut -d' ' -f 1 >> results/$(subst .,,$(subst /,_,$@)).stat
|
|
||||||
wc --bytes $@/$(shell basename $(realpath $(lastword $@))).bin | cut -d' ' -f 1 >> results/$(subst .,,$(subst /,_,$@)).stat
|
|
||||||
|
|
||||||
tests : $(EXAMPLES)
|
|
||||||
|
|
||||||
ci : install tests
|
|
||||||
|
|
||||||
clean :
|
|
||||||
rm -rf results
|
|
||||||
|
|
||||||
Loading…
Add table
Reference in a new issue