summary refs log tree commit diff
path: root/F2024/coe718/labs/lab2/bitbanding/bitband.c
blob: 54c2b6339e27a8e660c64e5baf3c9bd503ac6239 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "LPC17xx.h"
#include "GLCD.h"

#include <stdio.h>

//------- ITM Stimulus Port definitions for printf ------------------- //
#define ITM_Port8(n)    (*((volatile unsigned char *)(0xE0000000+4*n)))
#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))
#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))

#define DEMCR           (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA          0x01000000

struct __FILE { int handle;  };
FILE __stdout;
FILE __stdin;

int fputc(int ch, FILE *f) {
  if (DEMCR & TRCENA) {
    while (ITM_Port32(0) == 0);
    ITM_Port8(0) = ch;
  }
  return(ch);
}
//------------------------------------------------------------------- //

#define __USE_LCD 0	// Uncomment to use the LCD
#define __FI      1 // Font index 16x24 

// Bit Band Macros used to calculate the alias address at run time
#define ADDRESS(x)    (*((volatile unsigned long *)(x)))
#define BitBand(x, y) 	ADDRESS(((unsigned long)(x) & 0xF0000000) | 0x02000000 |(((unsigned long)(x) & 0x000FFFFF) << 5) | ((y) << 2))

#ifdef __USE_LCD
static inline void method2lcd(unsigned char* msg) {
  GLCD_DisplayString(6,  8, __FI,  msg);
}
#endif

// Simple register masking
static void method_mask(){
	LPC_GPIO1->FIOPIN ^= (1 << 28);
	LPC_GPIO2->FIOPIN ^= (1 << 2);
}

// Define pointer with bitband method
static void method_function(){
	volatile unsigned long* bit1 = &BitBand(&LPC_GPIO1->FIOPIN, 29);		
	volatile unsigned long* bit2 = &BitBand(&LPC_GPIO2->FIOPIN, 3);		

	static _Bool state = 1;
	
	*bit1 = *bit2 = state;
	state = !state;
}

// Raw bitbanding
static void method_bitbanding() {
	const size_t addr1 = 0x22000000 + (0x2009C034 * 32UL) + (31 * 4);
	const size_t addr2 = 0x22000000 + (0x2009C054 * 32UL) + (4 * 4);

	static _Bool state = 1;
	
	ADDRESS(addr1) = ADDRESS(addr2) = state;
	state = !state;
}
	
void SysTick_Handler(void) { 
	static size_t tick = 0;
	static size_t state = 0;

	if (tick++ < 500) { return; }
	tick = 0;
		
	// Uses MOVS instruction to implement jump table
	if 			(state == 0) { method_mask(); state++; }
	else if (state == 1) { method_function(); state++; }
	else if (state == 2) { method_bitbanding(); state = 0; }
	
	#ifdef __USE_LCD
	if 			(state == 1) { method2lcd("MASK    "); }
	else if (state == 2) { method2lcd("FUNCTION"); }
	else if (state == 0) { method2lcd("BITBAND "); }	
	#endif
}
	
int main(void){
	LPC_SC->PCONP     |= (1 << 15);            /* enable power to GPIO & IOCON  */
  LPC_GPIO1->FIODIR |= 0xB0000000;           /* LEDs on PORT1 are output      */
  LPC_GPIO2->FIODIR |= 0x0000007C;           /* LEDs on PORT2 are output			*/
	
	// Configure SysTick with interrupt and internal clock source
	ADDRESS(0xE000E010) = (1 << 0) | (1 << 1) | (1 << 2);
	
	// Run handler every 1ms
	ADDRESS(0xE000E014) = 99999;
	
	#ifdef __USE_LCD
  GLCD_Init();                               /* Initialize graphical LCD (if enabled */

  GLCD_Clear(White);                         /* Clear graphical LCD display   */
  GLCD_SetBackColor(Blue);
  GLCD_SetTextColor(Yellow);
  GLCD_DisplayString(0, 0, __FI, "     COE718 Lab 2    ");
	GLCD_SetTextColor(White);
  GLCD_DisplayString(1, 0, __FI, "       bitband.c     ");
  GLCD_DisplayString(2, 0, __FI, "  Watch the LEDs!    ");
  GLCD_SetBackColor(White);
  GLCD_SetTextColor(Blue);
  GLCD_DisplayString(6, 0, __FI, "Method:");
	#endif
	
	// Let SysTick callback run in background
	while (1) {}
}