forked from billychasen/sms-door-opener
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBrilldea_W5100_Indirect_Driver_Ver006.spin
1853 lines (1527 loc) · 170 KB
/
Brilldea_W5100_Indirect_Driver_Ver006.spin
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
''**************************************
''
'' WIZnet W5100 Indirect Driver Ver. 00.6
''
'' Timothy D. Swieter, P.E.
'' Brilldea - purveyor of prototyping goods
'' www.brilldea.com
''
'' Generously funded by Parallax
'' www.parallax.com
''
'' Copyright (c) 2010 Timothy D. Swieter, P.E.
'' See end of file for terms of use and MIT License
''
'' Updated: Dec 10, 2010
''
''Description:
''
'' This is an Indirect/parallel Assembly language driver for the W5100.
'' This driver requires /RESET, /WR, /RD, /CS, 8x data and 2x address lines.
'' The SEN singal should be tied low to disable SPI mode. The /INT signal is
'' not employed in this version of the driver.
''
'' The functions are mostly implemented in ASM for very fast access. There is high level access
'' to the Indirect/parallel bus, but going through SPIN to do many of the functions adds considerable time.
''
'' One thing to note about this driver is the assumption is makes regarding the pins used for exchanging data
'' with the W5100. When starting the driver you provide the function with the first data pin - that is Data0.
'' The driver then assumes that all data pins are consecuitive and increasing. So if you define P0 as Data0, then
'' P2 is Data1....P7 is Data7.
''
'' In the program that calls this driver you will need to set up variables for such as the following:
''
'' 'Variables to hold the address configuration information as set
'' byte myMAC[6] '6 element array contianing MAC or source hardware address ex. "02:00:00:01:23:45"
'' byte myGateway[4] '4 element array containing gateway address ex. "192.168.0.1"
'' byte mySubnet[4] '4 element array contianing subnet mask ex. "255.255.255.0"
'' byte myIP[4] '4 element array containing IP address ex. "192.168.0.13"
''
''reference:
'' W5100_Data Sheet
''
'' 2711015Eady.pdf (Circuit Cellar Magazine Article: http://www.circuitcellar.com/archives/viewable/Eady207/2711015Eady.pdf)
'' Hydra EtherX Documentation
''
'' Programming and Customizing the multicore Propeller Microcontroller by various
'' TCP/IP Application Layer Protocols for Embedded Systems by M. Tim Jones
'' Networking and Internetworking with Microcontrollers by Fred Eady
''
'' Initial indirect driver coding done by Patrick von den Driesch (patrick1ab on Parallax's Forum)
''
''To do:
''
'' -in tx/rxUDP there are referneces to $0100 and $0800. Review if any of these should be made to variables or constants for better readability or future expansion
'' -test i variable initializing at start of tx/rxUDP is needed
'' -see if there is a command parameters that aren't being used - if so remove some of the longs located at the end of the ASM that are read from byte ram on each command execution
'' -add ability to change socket memory size.
''
''Revision Notes:
'' 0.5 ....start of fork from SPI code
'' 0.6 Code enhancements and optimizing
'' Fixed problem in UDP buffer losing data - thanks to Marko! Problem was in txUDP.
'' 0.6-patch1 Bugfix: Avoid deadlock in txTCP, corrected return value in rxTCP /kuisma
''
''**************************************
CON 'Constants to be located here
'***************************************
'***************************************
' Firmware Version
'***************************************
FWmajor = 0
FWminor = 6
DAT
TxtFWdate byte "Dec 10, 2010",0
CON
'***************************************
' System Definitions
'***************************************
_OUTPUT = 1 'Sets pin to output in DIRA register
_INPUT = 0 'Sets pin to input in DIRA register
_HIGH = 1 'High=ON=1=3.3V DC
_ON = 1
_LOW = 0 'Low=OFF=0=0V DC
_OFF = 0
_ENABLE = 1 'Enable (turn on) function/mode
_DISABLE = 0 'Disable (turn off) function/mode
'***************************************
' W5100 Common Register Definitions
'***************************************
_MR = $0000 'Mode Register
_GAR0 = $0001 'Gateway Address Register
_GAR1 = $0002
_GAR2 = $0003
_GAR3 = $0004
_SUBR0 = $0005 'Subnet Mask Address Register
_SUBR1 = $0006
_SUBR2 = $0007
_SUBR3 = $0008
_SHAR0 = $0009 'Source Hardware Address Register (MAC)
_SHAR1 = $000A
_SHAR2 = $000B
_SHAR3 = $000C
_SHAR4 = $000D
_SHAR5 = $000E
_SIPR0 = $000F 'Source IP Address Register
_SIPR1 = $0010
_SIPR2 = $0011
_SIPR3 = $0012
'Reserved space $0013 - $0014
_IR = $0015 'Interrupt Register
_IMR = $0016 'Interrupt Mask Register
_RTR0 = $0017 'Retry Time Register
_RTR1 = $0018
_RCR = $0019 'Retry Count Register
_RMSR = $001A 'Rx Memory Size Register
_TMSR = $001B 'Tx Memory Size Register
_PATR0 = $001C 'Authentication Type in PPPoE Register
_PATR1 = $001D
'Reserved space $001E - $0027
_PTIMER = $0028 'PPP LCP Request Timer
_PMAGIC = $0029 'PPP LCP Magic Number
_UIPR0 = $002A 'Unreachable IP Address Register
_UIPR1 = $002B
_UIPR2 = $002C
_UIPR3 = $002D
_UPORT0 = $002E 'Unreachable Port Register
_UPORT1 = $002F
'Reserved space $0030 - $03FF
'***************************************
' W5100 Socket 0 Register Definitions
'***************************************
_S0_MR = $0400 'Socket 0 Mode Register
_S0_CR = $0401 'Socket 0 Command Register
_S0_IR = $0402 'Socket 0 Interrupt Register
_S0_SR = $0403 'Socket 0 Status Register
_S0_PORT0 = $0404 'Socket 0 Source Port Register
_S0_PORT1 = $0405
_S0_DHAR0 = $0406 'Socket 0 Destination Hardware Address Register
_S0_DHAR1 = $0407
_S0_DHAR2 = $0408
_S0_DHAR3 = $0409
_S0_DHAR4 = $040A
_S0_DHAR5 = $040B
_S0_DIPR0 = $040C 'Socket 0 Destination IP Address Register
_S0_DIPR1 = $040D
_S0_DIPR2 = $040E
_S0_DIPR3 = $040F
_S0_DPORT0 = $0410 'Socket 0 Destination Port Register
_S0_DPORT1 = $0411
_S0_MSSR0 = $0412 'Socket 0 Maximum Segment Size Register
_S0_MSSR1 = $0413
_S0_PROTO = $0414 'Socket 0 Protocol in IP Raw Mode Register
_S0_TOS = $0415 'Socket 0 IP TOS Register
_S0_TTL = $0416 'Socket 0 IP TTL Register
'Reserved space $0417 - $041F
_S0_TX_FSRO = $0420 'Socket 0 TX Free Size Register
_S0_TX_FSR1 = $0421
_S0_TX_RD0 = $0422 'Socket 0 TX Read Pointer Register
_S0_TX_RD1 = $0423
_S0_TX_WR0 = $0424 'Socket 0 TX Write Pointer Register
_S0_TX_WR1 = $0425
_S0_RX_RSR0 = $0426 'Socket 0 RX Received Size Register
_S0_RX_RSR1 = $0427
_S0_RX_RD0 = $0428 'Socket 0 RX Read Pointer Register
_S0_RX_RD1 = $0429
'Reserved space $042A - $04FF
'***************************************
' W5100 Socket 1 Register Definitions
'***************************************
_S1_MR = $0500 'Socket 1 Mode Register
_S1_CR = $0501 'Socket 1 Command Register
_S1_IR = $0502 'Socket 1 Interrupt Register
_S1_SR = $0503 'Socket 1 Status Register
_S1_PORT0 = $0504 'Socket 1 Source Port Register
_S1_PORT1 = $0505
_S1_DHAR0 = $0506 'Socket 1 Destination Hardware Address Register
_S1_DHAR1 = $0507
_S1_DHAR2 = $0508
_S1_DHAR3 = $0509
_S1_DHAR4 = $050A
_S1_DHAR5 = $050B
_S1_DIPR0 = $050C 'Socket 1 Destination IP Address Register
_S1_DIPR1 = $050D
_S1_DIPR2 = $050E
_S1_DIPR3 = $050F
_S1_DPORT0 = $0510 'Socket 1 Destination Port Register
_S1_DPORT1 = $0511
_S1_MSSR0 = $0512 'Socket 1 Maximum Segment Size Register
_S1_MSSR1 = $0513
_S1_PROTO = $0514 'Socket 1 Protocol in IP Raw Mode Register
_S1_TOS = $0515 'Socket 1 IP TOS Register
_S1_TTL = $0516 'Socket 1 IP TTL Register
'Reserved space $0517 - $051F
_S1_TX_FSRO = $0520 'Socket 1 TX Free Size Register
_S1_TX_FSR1 = $0521
_S1_TX_RD0 = $0522 'Socket 1 TX Read Pointer Register
_S1_TX_RD1 = $0523
_S1_TX_WR0 = $0524 'Socket 1 TX Write Pointer Register
_S1_TX_WR1 = $0525
_S1_RX_RSR0 = $0526 'Socket 1 RX Received Size Register
_S1_RX_RSR1 = $0527
_S1_RX_RD0 = $0528 'Socket 1 RX Read Pointer Register
_S1_RX_RD1 = $0529
'Reserved space $052A - $05FF
'***************************************
' W5100 Socket 2 Register Definitions
'***************************************
_S2_MR = $0600 'Socket 2 Mode Register
_S2_CR = $0601 'Socket 2 Command Register
_S2_IR = $0602 'Socket 2 Interrupt Register
_S2_SR = $0603 'Socket 2 Status Register
_S2_PORT0 = $0604 'Socket 2 Source Port Register
_S2_PORT1 = $0605
_S2_DHAR0 = $0606 'Socket 2 Destination Hardware Address Register
_S2_DHAR1 = $0607
_S2_DHAR2 = $0608
_S2_DHAR3 = $0609
_S2_DHAR4 = $060A
_S2_DHAR5 = $060B
_S2_DIPR0 = $060C 'Socket 2 Destination IP Address Register
_S2_DIPR1 = $060D
_S2_DIPR2 = $060E
_S2_DIPR3 = $060F
_S2_DPORT0 = $0610 'Socket 2 Destination Port Register
_S2_DPORT1 = $0611
_S2_MSSR0 = $0612 'Socket 2 Maximum Segment Size Register
_S2_MSSR1 = $0613
_S2_PROTO = $0614 'Socket 2 Protocol in IP Raw Mode Register
_S2_TOS = $0615 'Socket 2 IP TOS Register
_S2_TTL = $0616 'Socket 2 IP TTL Register
'Reserved space $0617 - $061F
_S2_TX_FSRO = $0620 'Socket 2 TX Free Size Register
_S2_TX_FSR1 = $0621
_S2_TX_RD0 = $0622 'Socket 2 TX Read Pointer Register
_S2_TX_RD1 = $0623
_S2_TX_WR0 = $0624 'Socket 2 TX Write Pointer Register
_S2_TX_WR1 = $0625
_S2_RX_RSR0 = $0626 'Socket 2 RX Received Size Register
_S2_RX_RSR1 = $0627
_S2_RX_RD0 = $0628 'Socket 2 RX Read Pointer Register
_S2_RX_RD1 = $0629
'Reserved space $062A - $06FF
'***************************************
' W5100 Socket 3 Register Definitions
'***************************************
_S3_MR = $0700 'Socket 3 Mode Register
_S3_CR = $0701 'Socket 3 Command Register
_S3_IR = $0702 'Socket 3 Interrupt Register
_S3_SR = $0703 'Socket 3 Status Register
_S3_PORT0 = $0704 'Socket 3 Source Port Register
_S3_PORT1 = $0705
_S3_DHAR0 = $0706 'Socket 3 Destination Hardware Address Register
_S3_DHAR1 = $0707
_S3_DHAR2 = $0708
_S3_DHAR3 = $0709
_S3_DHAR4 = $070A
_S3_DHAR5 = $070B
_S3_DIPR0 = $070C 'Socket 3 Destination IP Address Register
_S3_DIPR1 = $070D
_S3_DIPR2 = $070E
_S3_DIPR3 = $070F
_S3_DPORT0 = $0710 'Socket 3 Destination Port Register
_S3_DPORT1 = $0711
_S3_MSSR0 = $0712 'Socket 3 Maximum Segment Size Register
_S3_MSSR1 = $0713
_S3_PROTO = $0714 'Socket 3 Protocol in IP Raw Mode Register
_S3_TOS = $0715 'Socket 3 IP TOS Register
_S3_TTL = $0716 'Socket 3 IP TTL Register
'Reserved space $0717 - $071F
_S3_TX_FSRO = $0720 'Socket 3 TX Free Size Register
_S3_TX_FSR1 = $0721
_S3_TX_RD0 = $0722 'Socket 3 TX Read Pointer Register
_S3_TX_RD1 = $0723
_S3_TX_WR0 = $0724 'Socket 3 TX Write Pointer Register
_S3_TX_WR1 = $0725
_S3_RX_RSR0 = $0726 'Socket 3 RX Received Size Register
_S3_RX_RSR1 = $0727
_S3_RX_RD0 = $0728 'Socket 3 RX Read Pointer Register
_S3_RX_RD1 = $0729
'Reserved space $072A - $07FF
'***************************************
' W5100 Register Masks & Values Defintions
'***************************************
'Used in the mode register (MR)
_RSTMODE = %1000_0000 'If 1, internal registers are initialized
_PBMODE = %0001_0000 'Ping block mode, 1 is enabled
_PPPOEMODE = %0000_1000 'PPPoE mode, 1 is enabled
_AIMODE = %0000_0010 'Address auto-increment mode
_INDMODE = %0000_0001 'Indirect bus mode
'Used in the Interrupt Register (IR) & Interrupt Mask Register (IMR)
_CONFLICTM = %1000_0000
_UNREACHM = %0100_0000
_PPPoEM = %0010_0000
_S3_INTM = %0000_1000 'Socket 3 interrupt bit mask (1 = interrupt)
_S2_INTM = %0000_0100 'Socket 2 interrupt bit mask (1 = interrupt)
_S1_INTM = %0000_0010 'Socket 1 interrupt bit mask (1 = interrupt)
_S0_INTM = %0000_0001 'Socket 0 interrupt bit mask (1 = interrupt)
'Used in the RX memory size register(RMSR)
_S3_SM = %1100_0000 'Socket 3 size mask
_S2_SM = %0011_0000 'Socket 2 size mask
_S1_SM = %0000_1100 'Socket 1 size mask
_S0_SM = %0000_0011 'Socket 0 size mask
_1KB = %00 '1KB memory size
_2KB = %01 '2KB memory size
_4KB = %10 '4KB memory size
_8KB = %11 '8KB memory size
'Used in the socket n mode register (Sn_MR)
_MULTIM = %1000_0000 'Enable/disable multicasting in UDP
_PROTOCOLM = %0000_1111 'Registers for setting protocol
_CLOSEDPROTO = %0000 'Closed
_TCPPROTO = %0001 'TCP
_UDPPROTO = %0010 'UDP
_IPRAWPROTO = %0011 'IPRAW
_MACRAW = %0100 'MACRAW (used in socket 0)
_PPPOEPROTO = %0101 'PPPoE (used in socket 0)
'Used in the socket n command register (Sn_CR)
_OPEN = $01 'Initialize a socket
_LISTEN = $02 'In TCP mode, waits for request from client
_CONNECT = $04 'In TCP mode, sends connect request to server
_DISCON = $08 'In TCP mode, request to disconnect
_CLOSE = $10 'Closes socket
_SEND = $20 'Transmits data
_SEND_MAC = $21 'In UDP mode, like send, but uses MAC
_SEND_KEEP = $22 'In TCP mode, check connection status by sending 1 byte
_RECV = $40 'Receiving is processed
'Used in socket n interrupt register (Sn_IR)
_SEND_OKM = %0001_0000 'Set to 1 if send operation is completed
_TIMEOUTM = %0000_1000 'Set to 1 if timeout occured during transmission
_RECVM = %0000_0100 'Set to 1 if data is received
_DISCONM = %0000_0010 'Set to 1 if connection termination is requested
_CONM = %0000_0001 'Set to 1 if connection is established
'Used in socket n status register (Sn_SR)
_SOCK_CLOSED = $00
_SOCK_INIT = $13
_SOCK_LISTEN = $14
_SOCK_SYNSENT = $15
_SOCK_SYNRECV = $16
_SOCK_ESTAB = $17
_SOCK_FIN_WAIT= $18
_SOCK_CLOSING = $1A
_SOCK_TIME_WAIT=$1B
_SOCK_LACK_ACK =$1D
_SOCK_CLOSE_WT= $1C
_SOCK_UDP = $22
_SOCK_IPRAW = $32
_SOCK_MACRAW = $42
_SOCK_PPPOE = $5F
_SOCK_ARP1 = $11
_SOCK_ARP2 = $21
_SOCK_ARP3 = $31
'SPI OP-code when assembly packet to read/write to W5100
_WRITEOP = $F0 'Signals a write operation in SPI mode
_READOP = $0F 'Signals a read operation in SPI mode
'RX & TX definitions
_TX_base = $4000 'Base address of TX buffer
_RX_base = $6000 'Base address of RX buffer
_TX_mask = $7FF 'Mask for default 2K buffer for each socket
_RX_mask = $7FF 'Mask for default 2K buffer for each socket
_UDP_header = 8 '8 bytes of data in the UDP header from the W5100
'***************************************
' Command Definitions for ASM W5100 Indirect/parallel Routine
'***************************************
'_reserved = 0 'This is the default state - means ASM is waiting for command
_readIND = 1 << 16 'High level access to reading from the W5100 via indirect/parallel
_writeIND = 2 << 16 'High level access to writing to the W5100 via indirect/parallel
_SetMAC = 3 << 16 'Set the MAC ID in the W5100
_SetGateway = 4 << 16 'Set the gateway address in the W5100
_SetSubnet = 5 << 16 'Set the subnet address in the W5100
_SetIP = 6 << 16 'Set the IP address in the W5100
_ReadMAC = 7 << 16 'Recall the MAC ID in the W5100
_ReadGateway = 8 << 16 'Recall the gateway address in the W5100
_ReadSubnet = 9 << 16 'Recall the subnet address in the W5100
_ReadIP = 10 << 16 'Recall the IP address in the W5100
_PingBlock = 11 << 16 'Enable/disable ping response
_rstHW = 12 << 16 'Reset the W5100 IC via hardware
_rstSW = 13 << 16 'Reset the W5100 IC via hardware
_Sopen = 14 << 16 'Open a socket
_Sdiscon = 15 << 16 'Disconnect a socket
_Sclose = 16 << 16 'Close a socket
_lastCmd = 17 << 16 'Place holder for last command
'***************************************
' Driver Flag Definitions
'***************************************
_Flag_ASMstarted = |< 1 'Flag to indicated asm routine is started succesfully
'**************************************
VAR 'Variables to be located here
'***************************************
'processor overhead
long W5100cog 'Cog ID
long W5100flags 'Flags for status
'Command setup
long command 'stores command and arguments for the ASM driver
'W5100 Indirect/Parallel pin definitions
'Pins/masks are actually setup in SPIN by modifying the memory that is copied into the cog. This saves space.
'The pins/masks are defined in the dat section. The definitions include the following pins:
'Address[0] - output
'Address[1] - output
'Chip Select - active low, output
'Read cmd - active low, output
'Write cmd - active low, output
'Reset - active low, output
'Data[0] to [7] - output/input
'SPI Enable - output
'***************************************
OBJ 'Object declaration to be located here
'***************************************
'none
'~~~~~~~~~~~~~~~~~~~~~~~~~~Start/Stop Routines~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'***************************************
PUB StopINDIRECT
'***************************************
'' Stop the W5100 Indirect/parallel Driver cog if one is running.
'' Only a single cog can be running at a time.
'' This routine will free a cog.
''
'' params: none
'' return: none
if W5100cog 'Is cog non-zero?
cogstop(W5100cog~ - 1) 'Yes, stop the cog and then make value zero
'Reset any data held by the driver
W5100flags := 0 'Clear all the flags
ADD0mask := 0 'Clear all masks
ADD1mask := 0
CSmask := 0
RDmask := 0
WRmask := 0
RESETmask := 0
DATAmask := 0
SENmask := 0
WRCSmask := 0
RDCSmask := 0
WRRDCSmask := 0
return 'end of StopINDIRECT
'***************************************
PUB StartINDIRECT(_databit0, _addr0, _addr1, _cs, _rd, _wr, _reset, _sen) : okay
'***************************************
'' Initializes the I/O and registers based on parameters.
'' After initilization another cog is started which is the
'' cog responsible for the Indirect/parallel communication to the W5100.
''
'' The W5100 Indirect/parallel cog will allow only one instance of itself
'' to run and the it consumes only 1 cog.
''
'' params: the seven pins of required for indirect/parallel
'' _databit0 is the pin for bit0, the other pins are assumed to be sequential following this pin.
'' _sen = the pin of the W5100 SPI_EN. If not used, set to -1
'' return: value of cog if started or zero if not started
'Keeps from two cogs running
StopINDIRECT
'Initialize the I/O for writing the mask data to the memory area that will be copied into a COG.
'This routine assumes Indirect/parallel connection, SPI_EN will be made output low by the ASM cog
ADD0mask := |< _addr0
ADD1mask := |< _addr1
CSmask := |< _cs
RDmask := |< _rd
WRmask := |< _wr
RESETmask := |< _reset
BASEpin := _databit0 'The base pin of data byte for shifting operations
DATAmask := %1111_1111 << _databit0 'Special mask setup with eight pins
WRCSmask := WRmask | CSmask
RDCSmask := RDmask | CSmask
WRRDCSmask:= WRmask | RDmask | CSmask
if _sen <> -1
SENmask := |< _sen
else
SENmask := 0
'Clear the command buffer - be sure no commands were set before initializing
command := 0
'Start a cog to execute the ASM routine
okay := W5100cog := cognew(@Entry, @command) + 1
'Set a flag if cog started succesfully
if okay
W5100flags := _Flag_ASMstarted
return 'end of StartINDIRECT
'~~~~~~~~~~~~~~~~~~~~~~~~~~Command Routines~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'***************************************
PUB InitAddresses( _block, _macPTR, _gatewayPTR, _subnetPTR, _ipPTR)
'***************************************
'' Initialize all four addresses.
''
'' params: _block if true will wait for ASM routine to send before returning from this function
'' _mac, _gateway, _subnet, _ip are pointers to appropriate size byte arrays
'' return: none
'Checks on if the ASM cog is running is done in each of the following routines
WriteMACaddress(_block, _macPTR)
WriteGatewayAddress(_block, _gatewayPTR)
WriteSubnetMask(_block, _subnetPTR)
WriteIPaddress(_block, _ipPTR)
return 'end of InitAddresses
'***************************************
PUB WriteMACaddress( _block, _macPTR)
'***************************************
'' Write the specified MAC address to the W5100.
''
'' params: _block if true will wait for ASM routine to send before continuing
'' The pointer should point to a 6 byte array.
'' byte[0] = highest octet and byte[5] = lowest octet
'' example 02:00:00:01:23:45 where byte[0] = $02 and byte[5] = $45
''
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _SetMAC + _macPTR
'wait for the command to complete or just move on
if _block
repeat while command
return 'end of WriteMACaddress
'***************************************
PUB WriteGatewayAddress(_block, _gatewayPTR)
'***************************************
'' Write the specified gateway address to the W5100.
''
'' params: _block if true will wait for ASM routine to send before continuing
'' The pointer should point to a 4 byte array.
'' byte[0] = highest octet and byte[3] = lowest octet
'' example 192.168.0.1 where byte[0] = 192 and byte[3] = 1
''
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _SetGateway + _gatewayPTR
'wait for the command to complete or just move on
if _block
repeat while command
return 'end of WriteGatewayAddress
'***************************************
PUB WriteSubnetMask(_block, _subnetPTR)
'***************************************
'' Write the specified Subnet mask to the W5100.
''
'' params: _block if true will wait for ASM routine to send before continuing
'' The pointer should point to a 4 byte array.
'' byte[0] = highest octet and byte[3] = lowest octet
'' example 255.255.255.0 where byte[0] = 255 and byte[3] = 0
''
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _SetSubnet + _subnetPTR
'wait for the command to complete or just move on
if _block
repeat while command
return 'end of WriteSubnetMask
'***************************************
PUB WriteIPaddress(_block, _ipPTR)
'***************************************
'' Write the specified IP address to the W5100.
''
'' params: _block if true will wait for ASM routine to send before continuing
'' The pointer should point to a 4 byte array.
'' byte[0] = highest octet and byte[3] = lowest octet
'' example 192.168.0.13 where byte[0] = 192 and byte[3] = 13
''
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _SetIP + _ipPTR
'wait for the command to complete or just move on
if _block
repeat while command
return 'end of WriteIPaddress
'***************************************
PUB ReadMACaddress(_macPTR)
'***************************************
'' Read the MAC address from the W5100.
''
'' params: none
'' return: The pointer should point to a 6 byte array.
'' byte[0] = highest octet and byte[5] = lowest octet
'' example 02:00:00:01:23:45 where byte[0] = $02 and byte[5] = $45
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _ReadMAC + _macPTR
'wait for the command to complete
repeat while command
return 'end of ReadMACaddress
'***************************************
PUB ReadGatewayAddress(_gatewayPTR)
'***************************************
'' Read the gateway address from the W5100.
''
'' params: none
'' return: The pointer should point to a 4 byte array.
'' byte[0] = highest octet and byte[3] = lowest octet
'' example 192.168.0.1 where byte[0] = 192 and byte[3] = 1
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _ReadGateway + _gatewayPTR
'wait for the command to complete
repeat while command
return 'end of ReadGatewayAddress
'***************************************
PUB ReadSubnetMask(_subnetPTR)
'***************************************
'' Read the specified Subnet mask from the W5100
''
'' params: none
'' return: The pointer should point to a 4 byte array.
'' byte[0] = highest octet and byte[3] = lowest octet
'' example 255.255.255.0 where byte[0] = 255 and byte[3] = 0
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _ReadSubnet + _subnetPTR
'wait for the command to complete
repeat while command
return 'end of ReadSubnetMask
'***************************************
PUB ReadIPaddress(_ipPTR)
'***************************************
'' Read the specified IP address from the W5100
''
'' params: none
'' return: The pointer should point to a 4 byte array.
'' byte[0] = highest octet and byte[3] = lowest octet
'' example 192.168.0.13 where byte[0] = 192 and byte[3] = 13
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _ReadIP + _ipPTR
'wait for the command to complete
repeat while command
return 'end of ReadIPaddress
'***************************************
PUB PingBlock(_block, _bool)
'***************************************
'' Enable/disable if the W5100 responds to pings.
''
'' params: _block if true will wait for ASM routine to send before continuing
'' _bool is a bool, true is W5100 will NOT respond, false W5100 will respond
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _pingBlock + @_bool
'wait for the command to complete or just move on
if _block
repeat while command
return 'end of PingBlock
'***************************************
PUB ResetHardware(_block)
'***************************************
'' Reset the W5100 via hardware
''
'' params: _block if true will wait for ASM routine to send before continuing
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _rstHW
'wait for the command to complete or just move on
if _block
repeat while command
return 'end of ResetHardware
'***************************************
PUB ResetSoftware(_block)
'***************************************
'' Reset the W5100 via software
''
'' params: _block if true will wait for ASM routine to send before continuing
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _rstSW
'wait for the command to complete or just move on
if _block
repeat while command
return 'end of ResetSoftware
'***************************************
PUB SocketOpen(_socket, _mode, _srcPort, _destPort, _destIP)
'***************************************
'' Open the specified socket in the specified mode on the W5100.
'' The mode can be either TCP or UDP.
''
'' params: _socket is a value of 0 to 3 - only four sockets on the W5100
'' _mode is one of the constants specifing closed, TCP, UDP, IPRaw etc
'' _srcPort, _destPort are the ports to use in the connection pass by value
'' _destIP is a pointer to the destination IP byte array (use the @on the variable)
'' return: none
'maybe add validation of data up here in spin as oppose to ASM??
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _Sopen + @_socket
'wait for the command to complete
repeat while command
return 'end of SocketOpen
'***************************************
PUB SocketTCPlisten(_socket) | temp0
'***************************************
'' Check if a socket is TCP and open and if so then set the socket to listen on the W5100
''
'' params: _socket is a value of 0 to 3 - only four sockets on the W5100
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Check if the socket is TCP and open by looking at socket status register
readIND((_S0_SR + (_socket * $0100)), @temp0, 1)
if temp0.byte[0] <> _SOCK_INIT
return
'Tell the W5100 to listen on the particular socket
temp0 := _LISTEN
writeIND(true, (_S0_CR + (_socket * $0100)), @temp0, 1)
return 'end of SocketTCPlisten
'***************************************
PUB SocketTCPconnect(_socket) | temp0
'***************************************
'' Check if a socket is TCP and open and if so then set the socket to connect on the W5100
''
'' params: _socket is a value of 0 to 3 - only four sockets on the W5100
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Check if the socket is TCP and open by looking at socket status register
readIND((_S0_SR + (_socket * $0100)), @temp0, 1)
if temp0.byte[0] <> _SOCK_INIT
return
'Tell the W5100 to connect to a particular socket
temp0 := _CONNECT
writeIND(true, (_S0_CR + (_socket * $0100)), @temp0, 1)
return 'end of SocketTCPconnect
'***************************************
PUB SocketTCPestablished(_socket) | temp0
'***************************************
'' Check if a socket has established a TCP connection
''
'' params: _socket is a value of 0 to 3 - only four sockets on the W5100
'' return: True if established, false if not
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Check if the socket is established or not
readIND((_S0_SR + (_socket * $0100)), @temp0, 1)
if temp0.byte[0] <> _SOCK_ESTAB
return false
else
return true
return false 'end of SocketTCPestablished
'***************************************
PUB SocketTCPdisconnect(_socket)
'***************************************
'' Disconnects the specified socket on the W5100.
''
'' params: _socket is a value of 0 to 3 - only four sockets on the W5100
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _Sdiscon + @_socket
'wait for the command to complete
repeat while command
return 'end of SocketTCPdisconnect
'***************************************
PUB SocketClose(_socket)
'***************************************
'' Closes the specified socket on the W5100.
''
'' params: _socket is a value of 0 to 3 - only four sockets on the W5100
'' return: none
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Send the command
command := _Sclose + @_socket
'wait for the command to complete
repeat while command
return 'end of SocketClose
'***************************************
PUB rxTCP(_socket, _dataPtr) | temp0, RSR, pcktptr, pcktoffset, pcktstart, rolloverpoint
'***************************************
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Check if there is data to receive from the W5100
readIND((_S0_RX_RSR0 + (_socket * $0100)), @temp0, 2)
RSR.byte[1] := temp0.byte[0]
RSR.byte[0] := temp0.byte[1]
'Bring over the data if there is data
if RSR.word[0] <> 0
'Determine the offset and location to read data from in the W5100
readIND((_S0_RX_RD0 + (_socket * $0100)), @temp0, 2)
pcktptr.byte[1] := temp0.byte[0]
pcktptr.byte[0] := temp0.byte[1]
pcktoffset := pcktptr & _RX_mask
pcktstart := (_RX_base + (_socket * $0800)) + pcktoffset
'Read the data of the packet
if (pcktoffset + RSR.word[0]) > constant(_RX_mask + 1)
'process the data in two parts because the buffers rolls over
rolloverpoint := constant(_RX_mask + 1) - pcktoffset
readIND(pcktstart, _dataPtr, rolloverpoint)
pcktstart := (_RX_base + (_socket * $0800))
readIND(pcktstart, (_dataPtr + rolloverpoint), (RSR.word[0] - rolloverpoint))
else
'process the data in one part
readIND(pcktstart, _dataPtr, RSR.word[0])
'Update the W5100 registers, the packet pointer
temp0 := (pcktptr + RSR.word[0])
pcktptr.byte[1] := temp0.byte[0]
pcktptr.byte[0] := temp0.byte[1]
writeIND(true, (_S0_RX_RD0 + (_socket * $0100)), @pcktptr, 2)
'Tell the W5100 we received a packet
temp0 := _RECV
writeIND(true, (_S0_CR + (_socket * $0100)), @temp0, 1)
return RSR.word[0] 'bugfix /Q
return 0 'end of rxTCP
'***************************************
PUB txTCP(_socket, _dataPtr, _size) | temp0, freespace, pcktptr, pcktoffset, pcktstart, rolloverpoint, chunksize
'***************************************
'If the ASM cog is running, execute the command
if (W5100flags & _Flag_ASMstarted)
'Initialize
freespace := 0
repeat while _size > 0
'wait for room in the W5100 to send some of the data
repeat until (freespace.word[0] > 0)
readIND((_S0_TX_FSRO + (_socket * $0100)), @temp0, 2)
freespace.byte[1] := temp0.byte[0]
freespace.byte[0] := temp0.byte[1]
chunksize := _size <# freespace.word[0]
'Get the place where to start writing the packet in the W5100
readIND((_S0_TX_WR0 + (_socket * $0100)), @temp0, 2)
pcktptr.byte[1] := temp0.byte[0]
pcktptr.byte[0] := temp0.byte[1]
pcktoffset := pcktptr & _TX_mask
pcktstart := (_TX_base + (_socket * $0800)) + pcktoffset
'Write the data based on rolling over in the buffer or not
if (pcktoffset + chunksize) > constant(_TX_mask + 1)
'process the data in two parts because the buffers rolls over
rolloverpoint := constant(_TX_mask + 1) - pcktoffset
writeIND(true, pcktstart, _dataPtr, rolloverpoint)
pcktstart := (_TX_base + (_socket * $0800))
writeIND(true, pcktstart, (_dataPtr + rolloverpoint), (chunksize - rolloverpoint))
else
'process the data in one part
writeIND(true, pcktstart, _dataPtr, chunksize)