PİC 18LF4520 Tetris Devresi Yardım

merkur

Üye
Katılım
7 Nis 2009
Mesajlar
3
Puanları
1
Merhabalar,
PİC18LF4520 İle tetris devresini yapıcağım.Devrenin internette isiste çizilmiş şeması bile yok.Devre bu halde ; "
pic18LF4520 ile tetris-elektroinfo.blogspot.com elektronik devreler elektrik haberleşme projeler devre şemaları "
Buraya göre yaptım ama isiste pickit 2 diye bir şey yok.Devre'nin dökümanlarını indirdim.Grafik çevrim kodunun içinde pic'in programlanması için gereken microbasic dosyası var, onu HEX dosyasına çevirdim.Devreye yükledim hex dosyasını devre çalıştı ama '$MCLR$ is low.Processor is in reset.' diye bir şey çıkıyor devreyi perşembeye kadar kurup baskı devresini çıkartmam lazım.Birisi yardım ederse çok sevinirim lütfen.Anlayamayan varsa sorsun cevaplarım sadece hallolsun yeterli benim için.Şimdiden herkese teşekkürler
 
MCLR pinini 10K ile VDD 'ye Bağla çalışır


Config MCLRE = Off -> KODU VAR

Yani MCLR Reset disable edilmiş koddakodlar Swordfish ile yazılmış sen microbasic ile derlemişsin.Açıkçası Swordfishi microbasic ile derleyebilirmisin bilemiyorum.Ama kodların çalıştığını söylemişsin.O zaman senin problemin şu ; bir şekilde bu kodu yazmamış atlamışsın ve MCLR reset aktif kalmış.Yada düzgün derlenmemiş.Kodum çalışır diyorsan MCLR pinini 10K ilşe VDD bağla.Yalnız bu durumda PİCkit2 programlayıcıyı ICSP ile devrene bağlama.Zif soket ile Programı at işlemcine
 
Son düzenleme:
arkadaşlar acil bakarmısınız baskı devresini buldum Tetris on a PIC Microcontroller [213] | Swordfish Projects | Swordfish Compiler ama paint dosyası bunun aresinden mevcut olan varmı ? yoksa da ben çizicem baskı devreyi ama ares te Güç kaynağı yani sl-100-05 malzemesini seçicem seçmiyor.Hocamın ares te açtım yazdım çıktı ama benim areste çıkmıyo birisi nolur yardım etsin bu hafta perşembeye kadar devrenin çalışır olması lazım
 
yani sl-100-05 diye bir eleman yok areste
 
Areste öyle bir eleman yoksa elemanın kaç bacaklı oldugunu biliyorsan ona göre pad at derim aynı aralıkta önemli olan elemanı yerleştirecegin pinlerinin uyuşması.
 
yani sl-100-05 diye bir eleman yok areste

Denemedim hiç ama bu elemanı hocanın bilgisayarında aç sonra ters tıkla falan bir şekilde script olarak yada artık bilemiyorum kopyasını alabileceğini düşünüyorum ben
 
ben bi türlü beceremedim çalışan *.hex dosyasını paylaşabilirmisin.
 
Kardeşim hem kaynak kodu hemde grafik kodu diye birşey var. Burada bu kodlar hex koduna mı çevrilecek. Hex koduna çeviren bir barkadaşımız paylaşabilirler mi acaba ?
 
Bende bu devreyi yapmak istiyorum ama bir türlü kaynak kodunu (source code) hex.e ceviremedim anlayan arkadaşlardan yardım bekliyorum...

' v1.0' release of the source code. Tetris without any bells + whistles.

' v1.1
' Added scorekeeping & highscores. The game will display the last high score at the start.
' If your score beats the highscore, it will be saved to the EEPROM as the new high score.


Device = 18F4520
Clock = 32
Config MCLRE = Off

Include "InternalOscillator.bas"
Include "RandGen.bas"
Include "Utils.bas"
Include "EEPROM.bas"

// PROGRAM DEFINES
Dim ObjectData(8) As Word
Dim tmpObjectData(8) As Word
Dim BackgroundData(8) As Word

Dim OriginX As Byte
Dim OriginY As Byte
Dim LimitedRotation As Byte
Dim CurrentRotation As Byte
Dim NumberOfLines As Word

Dim Left As PORTB.0
Dim Right As PORTB.1
Dim Rotate As PORTB.2
Dim Down As PORTB.3

Dim Left_Delay As Byte
Dim Right_Delay As Byte
Dim Rotate_Delay As Byte
Dim Down_Delay As Byte
Dim ButtonFlags As Byte
Dim Left_Debounce As ButtonFlags.0
Dim Right_Debounce As ButtonFlags.1
Dim Rotate_Debounce As ButtonFlags.2
Dim Down_Debounce As ButtonFlags.3

Dim Flags As Byte
Dim UpdateScreen As Flags.0
Dim InterruptComplete As Flags.1
Dim DropObject As Flags.2
Dim EndOfGame As Flags.3
Dim CheckForNewLines As Flags.4

// used for random graphic selection
Const NumberOfShapes = 7
Const RndWindow = 255/NumberOfShapes

// terminology (I could have added more..)
Const CW = 1
Const CCW = 0

// TMR2 variables
Dim TMR2IE As PIE1.1, // TMR2 interrupt enable
TMR2IF As PIR1.1, // TMR2 overflow flag
TMR2ON As T2CON.2, // Enables TMR2 to begin incrementing
mS As Word, // mS register
CurrentX As Byte,
sWDT As Byte // Software Watch Dog Timer for entering SLEEP mode

Const mS_Inc = 2
Const DebounceDelay = 10

// Sleep mode registers
Dim IDLEN As OSCCON.7,
SCS1 As OSCCON.1,
SCS0 As OSCCON.0

// SHAPES!
// Be sure to update "NumberOfShapes" if more are added (or some are removed)
// ###
// #
Const Graphic0(8) As Word = (%0000000000000000,%0000000000000000,%0000000000000000,%0000000000000001,%0000000000000011,%0000000000000001,%0000000000000000,%0000000000000000)
Const Graphic0_X = 4
Const Graphic0_Y = 0
Const LimitedRotation0 = 0

// ####
Const Graphic1(8) As Word = (%0000000000000000,%0000000000000000,%0000000000000001,%0000000000000001,%0000000000000001,%0000000000000001,%0000000000000000,%0000000000000000)
Const Graphic1_X = 4
Const Graphic1_Y = 0
Const Graphic_W = 1
Const Graphic_H = 1
Const LimitedRotation1 = 1

// ###
// #
Const Graphic2(8) As Word = (%0000000000000000,%0000000000000000,%0000000000000000,%0000000000000011,%0000000000000001,%0000000000000001,%0000000000000000,%0000000000000000)
Const Graphic2_X = 4
Const Graphic2_Y = 0
Const LimitedRotation2 = 0

// ###
// #
Const Graphic3(8) As Word = (%0000000000000000,%0000000000000000,%0000000000000000,%0000000000000001,%0000000000000001,%0000000000000011,%0000000000000000,%0000000000000000)
Const Graphic3_X = 4
Const Graphic3_Y = 0
Const LimitedRotation3 = 0

// ##
// ##
Const Graphic4(8) As Word = (%0000000000000000,%0000000000000000,%0000000000000000,%0000000000000011,%0000000000000011,%0000000000000000,%0000000000000000,%0000000000000000)
Const Graphic4_X = 3
Const Graphic4_Y = 1
Const LimitedRotation4 = 2

// ###
// ###
Const Graphic5(8) As Word = (%0000000000000000,%0000000000000000,%0000000000000000,%0000000000000010,%0000000000000011,%0000000000000001,%0000000000000000,%0000000000000000)
Const Graphic5_X = 4
Const Graphic5_Y = 1
Const LimitedRotation5 = 1

// ###
// ###
Const Graphic6(8) As Word = (%0000000000000000,%0000000000000000,%0000000000000000,%0000000000000001,%0000000000000011,%0000000000000010,%0000000000000000,%0000000000000000)
Const Graphic6_X = 4
Const Graphic6_Y = 1
Const LimitedRotation6 = 1

// TEXT
Const TETRIS(8) As Word = (%1000100001000001,%1111101111011111,%1000100001000001,%0000000000000000,%1001101111011111,%1010100101010101,%1100101010010001,%0000000000000000)

// NUMBERS
Const Number_0(8) As Word = (%0000000000011110,%0000000000010010,%0000000000010010,%0000000000010010,%0000000000011110,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_1(8) As Word = (%0000000000000100,%0000000000001100,%0000000000000100,%0000000000000100,%0000000000011110,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_2(8) As Word = (%0000000000011110,%0000000000000010,%0000000000011110,%0000000000010000,%0000000000011110,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_3(8) As Word = (%0000000000011110,%0000000000000010,%0000000000001110,%0000000000000010,%0000000000011110,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_4(8) As Word = (%0000000000010010,%0000000000010010,%0000000000011110,%0000000000000010,%0000000000000010,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_5(8) As Word = (%0000000000011110,%0000000000010000,%0000000000011110,%0000000000000010,%0000000000011110,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_6(8) As Word = (%0000000000011110,%0000000000010000,%0000000000011110,%0000000000010010,%0000000000011110,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_7(8) As Word = (%0000000000011110,%0000000000000010,%0000000000000100,%0000000000001000,%0000000000010000,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_8(8) As Word = (%0000000000011110,%0000000000010010,%0000000000011110,%0000000000010010,%0000000000011110,%0000000000000000,%0000000000000000,%0000000000000000)
Const Number_9(8) As Word = (%0000000000011110,%0000000000010010,%0000000000011110,%0000000000000010,%0000000000000010,%0000000000000000,%0000000000000000,%0000000000000000)

Inline Sub Sleep() // inline sub for SLEEP command
Asm
Sleep
End Asm
End Sub

Interrupt TMR2_Interrupt(2)
Save(0) // Back up system variables

If TMR2IF = 1 Then // Check if the interrupt was from TMR2
TMR2IF = 0 // Clear the TMR2 interrupt flag
// increment the mS variable
mS = mS + mS_Inc
If mS = 1000 Then
mS = 0
sWDT = sWDT + 1
If sWDT = 30 Then
IDLEN = 1 // Put the PIC in RC_IDLE mode on SLEEP
SCS1 = 1 //
SCS0 = 0 //
TRISA = $FF // Make all I/Os high impedance inputs
TRISB = $FF
TRISC = $FF
TRISD = $FF
TMR2ON = 0 // Disable TMR2
// Configure oscillator for 31Khz
OSCCON = OSCCON And %10001111
Sleep
EndIf
EndIf

// Button Debounces
// Ensures the button has been activated before performing a debounce.
// Interrupt driven, the user has X mS between button presses.
// Prevents double presses and and minimize the chance of switch chatter.
// The sub routine 'CheckButtons' controls the state of various flags here.
// check if left button requires debounce
If Left_Debounce = 1 Then
If Left_Delay = 0 Then
If Left = 1 Then
Left_Debounce = 0
EndIf
Else
Left_Delay = Left_Delay - mS_Inc
EndIf
EndIf
// check if the right button requires debounce
If Right_Debounce = 1 Then
If Right_Delay = 0 Then
If Right = 1 Then
Right_Debounce = 0
EndIf
Else
Right_Delay = Right_Delay - mS_Inc
EndIf
EndIf
// check if the rotate button requires debounce
If Rotate_Debounce = 1 Then
If Rotate_Delay = 0 Then
If Rotate = 1 Then
Rotate_Debounce = 0
EndIf
Else
Rotate_Delay = Rotate_Delay - mS_Inc
EndIf
EndIf
// check if the down button requires debounce
If Down_Debounce = 1 Then
If Down_Delay = 0 Then
If Down = 1 Then
Down_Debounce = 0
EndIf
Else
Down_Delay = Down_Delay - mS_Inc
EndIf
EndIf


// Event Handler - Object Drop
// Once every 800mS, a flag is set to initiate the next object drop.
// This is one of few classic features of tetris
If mS = 800 Then
DropObject = 1
End If


// Displays content on 64 LEDs via multiplexing
// Ensure multiplexing is enabled.
// This is vital to protect shared variables such as ObjectData and BackgroundData.
// Whenever a write to either is done outside of the interrupt, multiplexing should be disabled.
If UpdateScreen = 1 Then
// disable ALL x axis
PORTA = PORTA Or $0F
PORTB = PORTB Or $F0

// fill y axis
PORTC = ObjectData(CurrentX).Byte0 Or BackgroundData(CurrentX).Byte0
PORTD = ObjectData(CurrentX).Byte1 Or BackgroundData(CurrentX).Byte1

// enable ONE x axis (the correct one for current Y axis)
If CurrentX < 4 Then
PORTA.bits(CurrentX) = 0
Else
PORTB.bits(CurrentX) = 0
EndIf

// increment x axis, ready for the next multiplex
Inc(CurrentX)
If CurrentX = 8 Then
CurrentX = 0
EndIf

// a general purpose flag to inidcate the completion of an interrupt
InterruptComplete = 1
EndIf
EndIf
Restore
End Interrupt

// Loop until an interrupt occurs.
// Useful for semaphores - allows shared resources to be used with little (no) impact on timing
Sub WaitForInterrupt()
InterruptComplete = 0
Repeat
Until InterruptComplete = 1
End Sub

// This is the primary semaphore routine. If the program uses shared resources, this routine is called.
Sub PauseMultiplexing()
WaitForInterrupt
UpdateScreen = 0
' TMR2IE = 0
End Sub

// Enables multiplexing to resume
Sub ResumeMultiplexing()
' TMR2IE = 1
UpdateScreen = 1
End Sub

// clears the passed array of type Word
Sub ClearArray(ByRef pArray() As Word)
Dim i As Byte

For i = 0 To Bound(pArray)
pArray(i) = $0000
Next
End Sub

// select a random object based on the number of objects defined
Sub SelectNextObject(ByRef pTarget() As Word)
Dim RndSelection As Byte
Dim i As Byte
Dim Counter, Selection As Byte

// create a random number from 0-255
RndSelection = RandGen.Rand

// make a selection based on the random number created
Counter = 0
Selection = 0
Repeat
Counter = Counter + RndWindow
Selection = Selection + 1
Until Counter >= RndSelection

// initalise object variables
CurrentRotation = 0

Select Selection
Case 1
For i = 0 To 7
pTarget(i) = Graphic0(i)
Next
OriginX = Graphic0_X
OriginY = Graphic0_Y
LimitedRotation = LimitedRotation0
Case 2
For i = 0 To 7
pTarget(i) = Graphic1(i)
Next
OriginX = Graphic1_X
OriginY = Graphic1_Y
LimitedRotation = LimitedRotation1
Case 3
For i = 0 To 7
pTarget(i) = Graphic2(i)
Next
OriginX = Graphic2_X
OriginY = Graphic2_Y
LimitedRotation = LimitedRotation2
Case 4
For i = 0 To 7
pTarget(i) = Graphic3(i)
Next
OriginX = Graphic3_X
OriginY = Graphic3_Y
LimitedRotation = LimitedRotation3
Case 5
For i = 0 To 7
pTarget(i) = Graphic4(i)
Next
OriginX = Graphic4_X
OriginY = Graphic4_Y
LimitedRotation = LimitedRotation4
Case 6
For i = 0 To 7
pTarget(i) = Graphic5(i)
Next
OriginX = Graphic5_X
OriginY = Graphic5_Y
LimitedRotation = LimitedRotation5
Case 7
For i = 0 To 7
pTarget(i) = Graphic6(i)
Next
OriginX = Graphic6_X
OriginY = Graphic6_Y
LimitedRotation = LimitedRotation6
// else statement, just in case (prefer not to, but hey)
Else
For i = 0 To 7
pTarget(i) = Graphic0(i)
Next
OriginX = Graphic0_X
OriginY = Graphic0_Y
LimitedRotation = LimitedRotation0
End Select
End Sub

// Merge two arrays with the selected mode
// 0 - Overwrite
// 1 - Or
Sub MergeObjects(ByRef pSource() As Word, ByRef pTarget() As Word, ByVal pMode As Byte)
Dim i As Byte
Dim tmpWord As Word

If pMode = 0 Then
For i = 0 To Bound(pSource)
pTarget(i) = pSource(i)
Next
ElseIf pMode = 1 Then
For i = 0 To Bound(pSource)
tmpWord = pTarget(i) Or pSource(i)
pTarget(i) = tmpWord
Next
EndIf
End Sub

// Move an objects y axis in pDirection
// 0 - move object down
// 1 - move object up
Sub MoveObjectY(ByRef pObject() As Word, pDirection As Byte, ByVal pCycles As Byte)
Dim i,c As Byte
Select pDirection
Case 0
For c = 1 To pCycles
For i = 0 To Bound(pObject)
pObject(i) = pObject(i) << 1
Next
OriginY = OriginY + 1
Next
Case 1
For c = 1 To pCycles
For i = 0 To Bound(pObject)
pObject(i) = pObject(i) >> 1
Next
OriginY = OriginY - 1
Next
End Select
End Sub

// Move an objects x axis in pDirection
// 0 - move object right
// 1 - move object left
Sub MoveObjectX(ByRef pObject() As Word, pDirection As Byte)
Dim i As Byte

Select pDirection
Case 0
For i = 7 To 1 Step -1
pObject(i) = pObject(i-1)
Next
pObject(0) = 0
OriginX = OriginX + 1
Case 1
For i = 0 To 6
pObject(i) = pObject(i+1)
Next
pObject(7) = 0
OriginX = OriginX - 1
End Select
End Sub


// check the passed object to see if it has reached the bottom
// return true if so
Function CheckForBottom(ByRef pObject() As Word) As Byte
Dim i As Byte

Result = 0
For i = 0 To Bound(pObject)
If pObject(i).Bits(15) = 1 Then
Result = 1
EndIf
Next
End Function

// check the passed object to see if it is against the left wall already
// return true if so
Function CheckForLeftWall(ByRef pObject() As Word) As Byte
Result = 1
If pObject(0) = 0 Then
Result = 0
EndIf
End Function

// check the passed object to see if it is against the right wall already
// return true if so
Function CheckForRightWall(ByRef pObject() As Word) As Byte
Result = 1
If pObject(7) = 0 Then
Result = 0
EndIf
End Function

// compare the passed source and target for a collision
// return true if so
Function CollisionDetect(ByRef pSource() As Word, ByRef pTarget() As Word) As Byte
Dim i As Byte
Dim tmpWord As Word

Result = 0
For i = 0 To Bound(pSource)
tmpWord = pSource(i) And pTarget(i)
If tmpword > 0 Then
Result = 1
Break
EndIf
Next
End Function

// An extremely quick way to rotate objects +90/-90 degrees.
//
// Notes:
// Work out the centre of the block (to be used as a pivot point), i.e. the centre of the block shape. Call that (px, py).
// Each brick that makes up the block shape will rotate around that point. For each brick, you can apply the following calculation.
// Where each brick's width and height is q, the brick's current location (of the upper left corner) is (x1, y1) and the new brick location is (x2, y2):
// x2 = (y1 + px - py)
// y2 = (px + py - x1 - q)
// To rotate the opposite direction:
// x2 = (px + py - y1 - q)
// y2 = (x1 + py - px)
//
// Based on a 2D affine matrix transformation.
Sub NewRotation(ByRef pSource() As Word, ByRef pTarget() As Word, ByVal pDirection As Byte)
Dim X2,Y2,Q,PX,PY As Integer
Dim X1,Y1 As Byte

// check to see if rotations are disabled for current object
If LimitedRotation = 2 Then
For X1 = 0 To 7
pTarget(X1) = pSource(X1)
Next
Else
// define object origin
PX = OriginX
PY = OriginY
// define Q
Q = 0


// clear the target array
For X1 = 0 To 7
pTarget(X1) = 0
Next

// if the object is limited by rotation, then reverse
// rotations 1 & 3. This will make the object turn like so
// CW, CCW, CW, CCW
If LimitedRotation = 1 Then
If CurrentRotation = 1 Then
pDirection = CCW
EndIf
EndIf
// analyse each pixel (working with 5x5 graphic)
For X1 = 0 To 7
For Y1 = 0 To 15
If pSource(X1).Bits(Y1) = 1 Then
If pDirection = CW Then
X2 = (PX + PY - Y1 - Q)
Y2 = (X1 + PY - PX)
Else
X2 = (Y1 + PX - PY)
Y2 = (PX + PY - X1 - Q)
EndIf
If X2 >= 0 And X2 <= 7 Then
If Y2 >= 0 And Y2 <= 15 Then
pTarget(X2).Bits(Y2) = 1 //pDestinationObject(GetIndexY(Int(Y2)), GetIndexX(Int(X2))) = 1
EndIf
EndIf
End If
Next
Next
EndIf
End Sub

// Count the number of pixels that equal "1". Standard bit-wise operators did not suit
// this routine as pixels could very well end up ANYWHERE after a rotation.
Function PixelCount(ByRef pSource() As Word) As Byte
Dim X,Y As Byte

Result = 0
For X = 0 To 7
For Y = 0 To 15
If pSource(X).Bits(Y) = 1 Then
Result = Result + 1
EndIf
Next
Next
End Function

// Drop the object by one Y increment. Return 0 if failed.
Function MoveObjectDown(ByRef pObject() As Word) As Byte
Result = 1
// Semaphore, to protect shared variables
PauseMultiplexing
// check for a collision with the bottom of the screen
If CheckForBottom(pObject) = 1 Then
// ... yes it has - time to save it there
Result = 0
// OR the object into the background
MergeObjects(pObject,BackgroundData,1)
// get a new object up-and-running
SelectNextObject(pObject)
// check for new lines
CheckForNewLines = 1
Else
// Move the object down
MoveObjectY(pObject,0,1)
// check for a collision with the background
If CollisionDetect(pObject,BackgroundData) = 1 Then
// the object HIT something in the background. The object needs to be
// moved BACK UP and saved to the background.
Result = 0
// move the object up one
MoveObjectY(pObject,1,1)
// move the object to the background (OR it over)
MergeObjects(pObject,BackgroundData,1)
// get a new object up-and-running
SelectNextObject(ObjectData)
// check if the object has collided with the background already. If yes, then
// the game is over.
If CollisionDetect(pObject,BackgroundData) = 1 Then
Result = 0
EndOfGame = 1
EndIf
// it's always possible that new lines may have been made already
CheckForNewLines = 1
EndIf
// resume multiplexing, shared resources are done with
EndIf
ResumeMultiplexing
End Function

// Check the state of each button. Because this routine is called often, the chances of missing a button press
// are very unlikely.
Sub CheckButtons()
// check if left button pressed
If Left = 0 And Left_Debounce = 0 Then
// semaphore - shared variables are about to be accessed
PauseMultiplexing
// ensure the object is not ALREADY against the left wall
If CheckForLeftWall(ObjectData) = 0 Then
// move the object to a temporary buffer
MergeObjects(ObjectData,tmpObjectData,0)
// Decrement the x axis
MoveObjectX(tmpObjectData,1)
// ensure no collisions with background
If CollisionDetect(tmpObjectData,BackgroundData) = 0 Then
// all went well, merge the array to the working buffer
MergeObjects(tmpObjectData,ObjectData,0)
// enable the debounce timer (prevents double presses etc)
Left_Delay = DebounceDelay
Left_Debounce = 1
// always a chance that a new line was just made
CheckForNewLines = 1
EndIf
EndIf
ResumeMultiplexing
EndIf
// check if the right button is pressed
// NOTE: THESE COMMENTS ARE MUCH THE SAME AS ABOVE, excluded for that reason
If Right = 0 And Right_Debounce = 0 Then
// semaphore - shared variables are about to be accessed
PauseMultiplexing
// ensure not already on the right wall
If CheckForRightWall(ObjectData) = 0 Then
MergeObjects(ObjectData,tmpObjectData,0)
MoveObjectX(tmpObjectData,0)
// ensure no collisions with objects
If CollisionDetect(tmpObjectData,BackgroundData) = 0 Then
MergeObjects(tmpObjectData,ObjectData,0)
Right_Delay = DebounceDelay
Right_Debounce = 1
CheckForNewLines = 1
EndIf
EndIf
ResumeMultiplexing
EndIf
// check if rotate button is pressed
If Rotate = 0 And Rotate_Debounce = 0 Then
// semaphore - shared variables are about to be accessed
PauseMultiplexing
// new rotation method, named accordingly, more info there
NewRotation(ObjectData,tmpObjectData,CW)
ResumeMultiplexing
// ensure nothing has fallen off due to near-wall rotations
If PixelCount(ObjectData) = PixelCount(tmpObjectData) Then
// check for object collision due to rotation
If CollisionDetect(tmpObjectData,BackgroundData) = 0 Then
// FINALLY, if it gets here then ALL WENT WELL.
// Temp buffer merged with working buffer
PauseMultiplexing
MergeObjects(tmpObjectData,ObjectData,0)
ResumeMultiplexing
// update the current angle (0=0, 1=90, 2=180, 3=270)
CurrentRotation = CurrentRotation + 1
If CurrentRotation = 2 Then
CurrentRotation = 0
EndIf
Rotate_Delay = DebounceDelay
Rotate_Debounce = 1
EndIf
EndIf
EndIf
// check if down is pressed
If Down = 0 And Down_Debounce = 0 Then
Down_Delay = DebounceDelay
Down_Debounce = 1
// move the current object straight to the bottom
Repeat
Until MoveObjectDown(ObjectData) = 0
EndIf
End Sub

// remove the line at location pY
Sub RemoveLine(ByRef pObject() As Word, ByRef pY As Byte)
Dim X,Y,CurrentLine As Byte

// shift each line down
For Y = pY-1 To 0 Step - 1
CurrentLine = Y+1
For X = 0 To 7
pObject(X).Bits(CurrentLine) = pObject(X).Bits(Y)
Next
Next
// clear the top line
For X = 0 To 7
pObject(X).Bits(0) = 0
Next
End Sub

// remove COMPLETED lines & return the number of lines found
Sub CheckForLines(ByRef pObject() As Word)
Dim X,Y,Pixels As Byte

For Y = 0 To 15
Pixels = 0
For X = 0 To 7
If pObject(X).Bits(Y) = 1 Then
Pixels = Pixels + 1
EndIf
Next
If Pixels = 8 Then
RemoveLine(pObject, Y)
NumberOfLines = NumberOfLines + 1
EndIf
Pixels = 0
Next
End Sub

// initialise TMR2
Private Sub Initialise_TMR2()
TMR2ON = 0 // Disable TMR2
TMR2IE = 0 // Turn off TMR2 interrupts
mS = 0 // Initialise mS
PR2 = 199 // TMR2 Period register PR2
T2CON = %00100011 // T2CON 0:1 = Prescale
// 00 = Prescaler is 1:1
// 01 = Prescaler is 1:4
// 1x = Prescaler is 1:16
// 3:6 = Postscale
// 0000 = 1:1 postscale
// 0001 = 1:2 postscale
// 0010 = 1:3 postscale...
// 1111 = 1:16 postscale

TMR2 = 0 // Reset TMR2 Value
TMR2IE = 1 // Enable TMR2 interrupts
TMR2ON = 1 // Enable TMR2 to increment
Enable(TMR2_Interrupt)
End Sub

// initialise the program
Sub InitialiseProgram()
// make all inputs digital
Utils.SetAllDigital

// configure I/O
TRISB = $0F
PORTB = $00
TRISC = $00
PORTC = $00
TRISD = $00
PORTD = $00
TRISA = $00
PORTA = $11
// enable PORTB weakpullups
INTCON2.7 = 0
// intialise variables
ClearArray(BackgroundData)
ClearArray(ObjectData)
OriginX = 0
OriginY = 0
CurrentX = 0
NumberOfLines = 0
mS = 0
// initialise events
DropObject = 0
EndOfGame = 0
CheckForNewLines = 0
sWDT = 0

// initialise buttons
Left_Debounce = 0
Left_Delay = 0
Right_Debounce = 0
Right_Delay = 0
Rotate_Debounce = 0
Rotate_Delay = 0
Down_Debounce = 0
Down_Delay = 0
End Sub

Sub SplashScreen()
Dim i As Byte

// semaphore - shared variables are about to be accessed
PauseMultiplexing

For i = 0 To 7
ObjectData(i) = TETRIS(i)
Next

ResumeMultiplexing

DelayMS(3500)
End Sub

Sub GetNumber(ByRef pDigit As Byte, ByRef pTarget() As Word)
Dim i As Byte
Select pDigit
Case 0
For i = 0 To 7
pTarget(i) = Number_0(i)
Next
Case 1
For i = 0 To 7
pTarget(i) = Number_1(i)
Next
Case 2
For i = 0 To 7
pTarget(i) = Number_2(i)
Next
Case 3
For i = 0 To 7
pTarget(i) = Number_3(i)
Next
Case 4
For i = 0 To 7
pTarget(i) = Number_4(i)
Next
Case 5
For i = 0 To 7
pTarget(i) = Number_5(i)
Next
Case 6
For i = 0 To 7
pTarget(i) = Number_6(i)
Next
Case 7
For i = 0 To 7
pTarget(i) = Number_7(i)
Next
Case 8
For i = 0 To 7
pTarget(i) = Number_8(i)
Next
Case 9
For i = 0 To 7
pTarget(i) = Number_9(i)
Next
End Select
End Sub

Sub ShowScore(ByRef pScore As Word)
Dim i As Byte
Dim CurrentNumber As Byte

// semaphore - shared variables are about to be accessed
PauseMultiplexing

// clear all graphic buffers
ClearArray(tmpObjectData)
ClearArray(ObjectData)
ClearArray(BackgroundData)

For i = 1 To 3
CurrentNumber = Utils.Digit(pScore,i)
GetNumber(CurrentNumber, tmpObjectData)
// shift the result down, depending on index
Select i
Case 2
MoveObjectY(tmpObjectData,0,5)
Case 3
MoveObjectY(tmpObjectData,0,10)
End Select
// or result with graphic object
MergeObjects(tmpObjectData,ObjectData,1)
Next

ResumeMultiplexing

// wait for "down" button to be pressed

// perform button debounce
Repeat
DelayMS(10)
Until Down = 1

// wait for button to be pressed
Repeat
Until Down = 0

// perform button debounce
Repeat
DelayMS(10)
Until Down = 1
End Sub

Sub ReadHighScore()
Dim tmpByte As Byte
Dim LastHighScore As Word

EE.Read(0,tmpByte)
If tmpByte = $77 Then
EE.Read(1,LastHighScore)
ShowScore(LastHighScore)
Else
LastHighScore = 0
EE.Write(0,$77,LastHighScore)
ShowScore(LastHighScore)
EndIf
End Sub

Sub WriteHighScore()
Dim LastHighScore As Word

EE.Read(1,LastHighScore)
If NumberOfLines > LastHighScore Then
EE.Write(1,NumberOfLines)
EndIf
End Sub

// this is the main game loop for Tetris
Sub MainGameLoop()
// initialise screen and variables
InitialiseProgram

// enable screen multiplexing & other timer functions
UpdateScreen = 1
Initialise_TMR2

// display the flash screen
SplashScreen

// Show last high score from EEPROM
ReadHighScore

// re-initialise screen and variables (splash screen and highscores may have altered stuff..)
PauseMultiplexing
InitialiseProgram
Initialise_TMR2
ResumeMultiplexing

// select an object and place it in ObjectData
SelectNextObject(ObjectData)

Repeat
// check if drop object flag has been set (invoked occurs by the interrupt "TimerObjectDrop")
If DropObject = 1 Then
DropObject = 0
MoveObjectDown(ObjectData)
EndIf
// check for completed lines. any routine that moves an object should enable this flag.
If CheckForNewLines = 1 Then
CheckForLines(BackgroundData)
EndIf
// scan buttons and action as necessary
CheckButtons()
// reset software watch dog timer
sWDT = 0
// loop forever, or until the EndOfGame event is set true
Until EndOfGame = 1

// write the high score to EEPROM
WriteHighScore()
// display the score!
ShowScore(NumberOfLines)
End Sub


// main program start

// seed randgen module
RandGen.Initialize($77)

While True
// enter main game program, will stay there until an END event occurs
MainGameLoop
Wend
 
Bu siteyi kullanmak için çerezler gereklidir. Siteyi kullanmaya devam etmek için onları kabul etmelisiniz. Daha fazla bilgi edin…