Created
April 23, 2013 16:55
-
-
Save TechplexEngineer/be348493e1cf4a4812cd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| INCLUDE stm32l1xx_constants.s | |
| AREA lab10_DAC, CODE, READONLY | |
| EXPORT __main | |
| IMPORT SIN_LOOKUP | |
| ALIGN | |
| ENTRY | |
| __main FUNCTION | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ; Enable HSI & set as system clock | |
| BL HSI_SETUP | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ; GPIO PA.4 and PA.5 as Analog | |
| BL ANALOG_OUT_CONF | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ; Configure TIM4 as Master Trigger | |
| BL TIM4_CONFIG | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ; Configure DAC (DAC_OUT1 = PA.4, DAC_OUT2 = PA.5) | |
| BL DAC_CONFIG | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ; NVIC Interrupt | |
| BL TIM4_INT_CONF | |
| stop B stop | |
| ENDFUNC ; END MAIN | |
| HSI_SETUP FUNCTION | |
| ;1. Turn on HSI (RCC_CR_HSION) | |
| LDR r0, =(RCC_BASE+RCC_CR) | |
| LDR r1, [r0] | |
| ORR r1, r1, #RCC_CR_HSION | |
| STR r1, [r0] ;v | |
| ;2. Wait for HSI ready (RCC_CR_HSIRDY) | |
| LDR r0, =(RCC_BASE+RCC_CR) | |
| hsi_wait LDR r1, [r0] | |
| AND r1, r1, #RCC_CR_HSIRDY | |
| CMP r1, #0 | |
| BLO hsi_wait ;v | |
| ;4. Select HSI as the system clock (RCC_CFGR_SW_HSI) | |
| ; 00: MSI oscillator used as system clock | |
| ; 01: HSI oscillator used as system clock RCC_CFGR_SW_HSI | |
| ; 10: HSE oscillator used as system clock | |
| ; 11: PLL used as system clock | |
| LDR r0, =(RCC_BASE+RCC_CFGR) | |
| LDR r1, [r0] | |
| BIC r1, r1, #RCC_CFGR_SW | |
| ORR r1, r1, #RCC_CFGR_SW_HSI | |
| STR r1, [r0] ;v | |
| ;2. Wait for HSI to be selected as system clock (RCC_CFGR_SWS_HSI) | |
| LDR r0, =(RCC_BASE+RCC_CFGR) | |
| hsi_wait1 LDR r1, [r0] | |
| AND r1, r1, #RCC_CFGR_SWS_HSI | |
| CMP r1, #0 | |
| BLO hsi_wait1 ;v? | |
| BX lr | |
| ENDFUNC | |
| ANALOG_OUT_CONF FUNCTION | |
| ; Note: DAC_OUT1 = PA.4, DAC_OUT2 = PA.5 | |
| ; 1. Enable the clock of GPIO A (RCC_AHBENR_GPIOAEN) | |
| LDR r0, =(RCC_BASE+RCC_AHBENR) | |
| LDR r1, [r0] | |
| ORR r1, r1, #RCC_AHBENR_GPIOAEN | |
| STR r1, [r0] ;v | |
| ; 2. Set PA.4 and PA.5 as Analog (GPIO_MODER):: Analog: 0b11 | |
| LDR r0, =(GPIOA_BASE+GPIO_MODER) | |
| LDR r1, [r0] | |
| ORR r1, r1, #(GPIO_MODER_MODER4 :OR: GPIO_MODER_MODER5) | |
| STR r1, [r0] ;v? | |
| BX lr | |
| ENDFUNC | |
| TIM4_CONFIG FUNCTION | |
| ; 1. Enable the clock of TIM4 (RCC_APB1ENR_TIM4EN) | |
| LDR r0, =(RCC_BASE+RCC_APB1ENR) | |
| LDR r1, [r0] | |
| ORR r1, r1, #RCC_APB1ENR_TIM4EN | |
| STR r1, [r0] ;v | |
| ; 2. Set the prescaler (TIM4->PSC) | |
| LDR r0, =(TIM4_BASE+TIM_PSC) | |
| MOV r1, #(18+1) | |
| STR r1, [r0] ;v | |
| ; 3. Set the auto reload value (TIM4->ARR) | |
| LDR r0, =(TIM4_BASE+TIM_ARR) | |
| MOV r1, #(65535) | |
| STR r1, [r0] ;v | |
| ; 4. Set the compare register (TIM4->CCR1) | |
| LDR r0, =(TIM4_BASE+TIM_CCR1) | |
| LDR r1, [r0] | |
| MOV r1, #19 | |
| STR r1, [r0] ;v | |
| ; 5. Set OC1M bits of TIM4->CCMR1 for Channel 1 to Toggle OC1REF when TIM4_CNT=TIM4_CCR1 | |
| ; 011: Toggle - OC1REF toggles when TIMx_CNT=TIMx_CCR1. ;@ WHY? | |
| LDR r0, =(TIM4_BASE+TIM_CCMR1) | |
| LDR r1, [r0] | |
| BIC r1, r1, #TIM_CCMR1_OC1M | |
| ORR r1, r1, #(TIM_CCMR1_OC1M_0 :OR: TIM_CCMR1_OC1M_1) | |
| STR r1, [r0] ;v | |
| ; 6. Enable compare output 1 (TIM_CCER_CC1E) | |
| LDR r0, =(TIM4_BASE+TIM_CCER) | |
| LDR r1, [r0] | |
| ORR r1, r1, #TIM_CCER_CC1E | |
| STR r1, [r0] ;v | |
| ; 7. Enable the update (TIM_EGR_UG) | |
| LDR r0, =(TIM4_BASE+TIM_EGR) | |
| LDR r1, [r0] | |
| ORR r1, r1, #TIM_EGR_UG | |
| STR r1, [r0] ;This looks like it goes into the wrong reg... | |
| ; 8. Clear the update flag (TIM_SR_UIF) | |
| LDR r0, =(TIM4_BASE+TIM_SR) | |
| LDR r1, [r0] | |
| BIC r1, r1, #TIM_SR_UIF | |
| STR r1, [r0] ;This cleared what we just did | |
| ; 9. Enable the TIM4 interrupts (TIM_DIER_UIE, TIM_DIER_CC1IE) | |
| LDR r0, =(TIM4_BASE+TIM_DIER) | |
| LDR r1, [r0] | |
| ORR r1, r1, #(TIM_DIER_UIE :OR: TIM_DIER_CC1IE) | |
| STR r1, [r0] ;v | |
| ; 10. Select the master mode as OC1REF signal is as trigger output TRGO (TIM_CR2_MMS) | |
| ; 100: Compare - OC1REF signal is used as trigger output (TRGO) | |
| LDR r0, =(TIM4_BASE+TIM_CR2) | |
| LDR r1, [r0] | |
| BIC r1, r1, #(TIM_CR2_MMS) | |
| ORR r1, r1, #(TIM_CR2_MMS_2) | |
| STR r1, [r0] ;v | |
| ; 11. Enable the timer (TIM_CR1_CEN) | |
| LDR r0, =(TIM4_BASE+TIM_CR1) | |
| LDR r1, [r0] | |
| ORR r1, r1, #(TIM_CR1_CEN) | |
| STR r1, [r0] ;v | |
| BX lr | |
| ENDFUNC | |
| DAC_CONFIG FUNCTION | |
| ; 1. Enable DAC clock (RCC_APB1ENR_DACEN) | |
| LDR r0, =(RCC_BASE+RCC_APB1ENR) | |
| LDR r1, [r0] | |
| ORR r1, r1, #(RCC_APB1ENR_DACEN) | |
| STR r1, [r0] ;v | |
| ; 2. Enable DAC output buffer (DAC_CR_BOFF1, DAC_CR_BOFF2) | |
| LDR r0, =(DAC_BASE+DAC_CR) | |
| LDR r1, [r0] | |
| BIC r1, r1, #(DAC_CR_BOFF1 :OR: DAC_CR_BOFF2) | |
| STR r1, [r0] ;v | |
| ; 3. Select TIM4 TRGO as trigger for both outputs (DAC_CR_TSEL1, DAC_CR_TSEL2) | |
| ;DAC_CR_TSEL1 ||| 101: Timer 4 TRGO event | |
| LDR r0, =(DAC_BASE+DAC_CR) | |
| LDR r1, [r0] | |
| BIC r1, r1, #(DAC_CR_TSEL1) | |
| ORR r1, r1, #(DAC_CR_TSEL1_0 :OR: DAC_CR_TSEL1_2) | |
| STR r1, [r0] ;v | |
| ;DAC_CR_TSEL2 ||| 101: Timer 4 TRGO event | |
| LDR r0, =(DAC_BASE+DAC_CR) | |
| LDR r1, [r0] | |
| BIC r1, r1, #(DAC_CR_TSEL2) | |
| ORR r1, r1, #(DAC_CR_TSEL2_0 :OR: DAC_CR_TSEL2_2) | |
| STR r1, [r0] ;v | |
| ; 4. Enable DAC1 and DAC2 (DAC_CR_EN1, DAC_CR_EN2) | |
| LDR r0, =(DAC_BASE+DAC_CR) | |
| LDR r1, [r0] | |
| ORR r1, r1, #(DAC_CR_EN1 :OR: DAC_CR_EN2) | |
| STR r1, [r0] ;v | |
| BX lr | |
| ENDFUNC | |
| TIM4_INT_CONF FUNCTION | |
| ; 1. Enable TIM4_IRQn | |
| LDR r0, =NVIC_BASE | |
| LDR r1, [r0, #NVIC_ISER0] | |
| ORR r1, r1, #1<<TIM4_IRQn | |
| STR r1, [r0, #NVIC_ISER0] | |
| ; 2. Set priority for TIM4_IRQn | |
| ; LDR r3, =NVIC_BASE | |
| ; ADD r0, r3, #NVIC_IPR0 | |
| ; LDR r1, [r0, #28] | |
| ; BIC r1, r1, #NVIC_IPR7_PRI_30 | |
| ; STR r1, [r0, #28] | |
| BX lr | |
| ENDFUNC | |
| TIM4_IRQHandler FUNCTION | |
| EXPORT TIM4_IRQHandler | |
| PUSH {lr,r4-r6} | |
| LDR r0, =(TIM4_BASE+TIM_SR) | |
| LDR r0, [r0] | |
| AND r1, r0, #TIM_SR_CC1IF | |
| CMP r1, #0 ; check if the CC1IF is set | |
| POPEQ {pc,r4-r6} ; not the interrupt we want, exit out | |
| LDR r0, =value | |
| LDR r6, [r0] | |
| MOV r0, #36 ; should be 36 | |
| MUL r6, r6, r0 ;r6 = counter * 36 | |
| MOV r0, #10 | |
| UDIV r6, r6, r0 ; r6 = r6 / 10 | |
| MOV r0, r6 | |
| BL SIN_LOOKUP ;r0 = x degrees lookup value | |
| MOV r4, r0 ;Save the A value | |
| ; ADD r6, r6, #1 ;(counter *3) + 1 | |
| ; MOV r0, r6 | |
| ; BL SIN_LOOKUP ;r0 = x degrees lookup value | |
| ; MOV r5, r0 ;Save the B value | |
| ; LDR r0, =value | |
| ; LDR r6, [r0] | |
| ; MOV r1, #36 ; should be 36 | |
| ; MUL r6, r6, r1 ; r6 = c*36 | |
| ; ;frac = mod(r6, 10) | |
| ; ;;x = mod(x, 360); | |
| ; MOV r3, #10 | |
| ; UDIV r1, r6, r3 ;r1 = Q | |
| ; MLS r6, r1, r3, r6 ;MLS{cond} Rd, Rn, Rm, Ra ;;ra - rn*rm | |
| ; ;r6 = frac ;;should I be handling two decimal places? | |
| ; SUB r0, r5, r4 ; r0 = B-A | |
| ; MUL r0, r0, r6 ; r0 = (B-A)*frac | |
| ; MOV r1, #10 | |
| ; SDIV r0, r0, r6 ; r0 = [(B-A)*frac]/10 | |
| ; ADD r0, r0, r4 ; r0 = [(B-A)*frac]/10 + A | |
| ; MOV r4, r0 | |
| ; Increment the counter | |
| LDR r1, =value | |
| LDR r6, [r1] | |
| ADD r6, r6, #1 | |
| STR r6, [r1] | |
| ;Put r0 into the DAC's Conversion Register | |
| ;DAC->DHR12RD = sin(v) << 16 | sin(v); | |
| ;When using dual channels, the values stored in a shared register | |
| ORR r4, r4, r4, lsl #16 ; r4 = r4|r4<<16 ;;for both channels | |
| LDR r0, =(DAC_BASE + DAC_DHR12RD) | |
| STR r4, [r0] | |
| ; ADD r6, r6, #3 ;floor(3.6) | |
| ; MOV r0, r6 | |
| ; BL SIN_LOOKUP ;r0 = x degrees lookup value | |
| ; MOV r4, r0 ;Save the A value | |
| ; ADD r6, r6, #1 ;ceil(3.6) | |
| ; MOV r0, r6 | |
| ; BL SIN_LOOKUP | |
| ; MOV r5, r0 ;Save the B value | |
| ; SUB r0, r5, r4 ; r0 = B-A | |
| ; MOV r1, #6 | |
| ; MUL r0, r0, r1 ; r0 = (B-A)*6 | |
| ; MOV r1, #10 | |
| ; SDIV r0, r0, r1 ; r0 = [(B-A)*6]/10 | |
| ; ADD r0, r0, r4 ; r0 = [(B-A)*6]/10 + A | |
| ; ;Store the calculated value ; this is going to accumulate error | |
| ; LDR r1, =value | |
| ; STR r0, [r1] | |
| ; ;Put r0 into the DAC's Conversion Register | |
| ; ;DAC->DHR12RD = sin(v) << 16 | sin(v); | |
| ; ;When using dual channels, the values stored in a shared register | |
| ; MOV r4, r0 | |
| ; ORR r4, r4, r4, lsl #16 ; r4 = r4|r4<<16 ;;for both channels | |
| ; LDR r0, =(DAC_BASE + DAC_DHR12RD) | |
| ; STR r4, [r0] | |
| POP {pc,r4-r6} | |
| ENDFUNC | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| AREA mydata, DATA | |
| value DCD 0 | |
| END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment